PHP防SQL注入:18年经验总结的三层硬核防御
|
器械区那股铁味混着前台的老歌,老张把25kg的杠铃片摔得震天响——那声巨响跟2026年4月我审的那套PHP代码里的漏洞警报声似的。当时甲方要求三天内上线,我原以为用PDO预处理就能兜底,结果测试组直接甩过来个SQL注入的攻击视频:输入框里填个`' OR 1=1--`,数据库直接吐了整张用户表。那阵子我蹲在办公室改代码,地上全是用了一半的粉笔——画防御架构图画的,画完擦,擦完再画。 第一层防御是预处理语句,这招我用了十八年,从mysqli到PDO,从`?`占位符到命名参数,闭着眼都能写。但去年碰见个狠角色——攻击者用宽字节注入绕过了预处理。具体咋绕的?我到现在也没完全想明白,只记得他往输入里塞了个`%bf%27`,把单引号转义成了乱码,数据库直接当正常字符吃了。那天我盯着日志看了俩小时,镜子上那块手印都没擦——最后发现是字符集配置的问题,`SET NAMES gbk`跟`addslashes()`混用,等于给攻击者开了后门。现在我的代码里第一行就是`mysqli_set_charset($conn, 'utf8mb4')`,谁再提gbk我跟谁急。 第二层是存储过程,这招是跟银行系统的老哥学的。他们连预处理都不用,所有SQL都封装在存储过程里,参数传进去,结果吐出来,中间过程黑盒。我原以为这招万无一失,结果去年给某金融APP做安全加固时,测试组用`EXEC sp_executesql`动态拼接存储过程名,直接把整个数据库拖了。那阵子我天天泡在SQL Server的文档里,发现存储过程本身也能被注入——只要攻击者能控制存储过程名或参数类型,就能往里塞恶意代码。现在我的存储过程都带参数类型检查,比如`@name NVARCHAR(50)`,超长直接截断,宁可报错也不给机会。 第三层是权限控制,这招是血的教训换来的。2018年我给某电商APP写后台,觉得预处理+存储过程够硬了,结果运维给数据库账号开了`db_owner`权限——攻击者注入成功后,直接删库跑路了。那阵子我天天往甲方公司跑,看他们恢复备份,地上全是咖啡渍和烟头。现在我的代码里,数据库账号只给`SELECT, INSERT, UPDATE, DELETE`权限,连`DROP`都不给,更别说`EXEC`了。有人跟我说“这样写代码麻烦”,我直接回他:“你嫌麻烦,攻击者可不嫌。”
文章配图,仅供参考 老张在拉伸区打哈欠,杠铃片还在地上滚。我跟他讲这三层防御,他撇撇嘴:“不就是预处理+存储过程+权限控制吗?我十年前就知道。”我笑了:“你知道的是皮毛,真正硬核的是这三层的组合——预处理防普通注入,存储过程防动态拼接,权限控制防提权。就像深蹲,光练股四头肌不行,得臀大肌、腘绳肌、核心一起发力,才能蹲得稳。”他没接话,蹲下做了个离心收缩——慢得像在数数,我知道他在想啥:这老家伙,又在装逼。前台的老歌换成了《海阔天空》,有人把粉笔捡起来,在墙上画了个SQL注入的攻击流程图。我瞅了眼,画得比我还糙——但关键点都对了:字符集、动态拼接、权限提升。这行当就这样,优胜劣汰,谁偷懒谁死。我原以为十八年的经验能让我少走点弯路,结果每年都有新漏洞冒出来,逼着你学,逼着你改。就像练腿,今天蹲100kg,明年就得蹲120kg,不然肌肉就萎缩了。 地上那个用了一半的粉笔,我捡起来,在墙上补了行注释:`// 防御不是目的,活着才是`。老张在旁边做了个半程深蹲,膝盖咔吧响了一声——他最近在冲重量,代偿得厉害。我没提醒他,就像没人提醒我,三年前那个漏洞是怎么绕过预处理的。有些事,得自己摔过才知道疼。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

