PHP Web安全实战:SQL注入防护详解
|
三个月之前,我接手了一个老项目的安全重构——用户登录模块存在SQL注入漏洞,攻击者能通过`admin' --`这样的输入绕过验证。当时团队用的是PHP+MySQL,原代码直接拼接SQL语句:`$sql = "SELECT FROM users WHERE username = '".$_POST['user']."'";`。测试时我用Burp Suite抓包,把user参数改成`admin' OR '1'='1`,结果直接登录成功——这让我意识到,书本上的漏洞案例真的会出现在生产环境。 后来翻看项目历史提交记录,发现2018年就有同事提过这个风险,但没人修复——可能觉得"小项目没人攻击"?可实际呢?我查日志发现,就在重构前一周,有个IP连续发送了200多次异常登录请求,参数里全是`' UNION SELECT`开头的字符串。这哪是"没人攻击"?分明是攻击者没成功而已! 修复时我试过三种方案:第一种是转义函数`mysqli_real_escape_string()`,但测试发现,如果数据库字符集设置不对(比如服务器是GBK而连接是UTF8),还是可能被绕过——这坑我踩了两天,最后发现是`mysqli_set_charset()`没调。第二种是预处理语句(Prepared Statements),这才是真正的"新技术"优势——参数和SQL逻辑分离,攻击者就算输入`'; DROP TABLE users;--`,也会被当成普通字符串处理。我用了PDO的`prepare()`和`bindParam()`,代码从5行缩到3行,性能还提升了15%(用XHProf测的)。 最坑的是第三方库的兼容问题——项目里用了个老旧的ORM,它的`where()`方法内部还是拼接SQL。我提交PR改预处理,结果测试环境报错:`SQLSTATE[HY093]: Invalid parameter number`。查了半天发现,这库的版本太旧,不支持命名参数绑定,只能用问号占位符。最后不得不降级方案,先转义再预处理——虽然不够完美,但至少比直接拼接安全。 有个细节别人很少写:参数类型必须严格匹配!比如用户ID是整数,预处理时要用`bindParam($id, PDO::PARAM_INT)`。如果用默认的字符串类型,攻击者可能通过科学计数法绕过——比如输入`1 OR 1=1`是字符串,但`1e0`会被MySQL解析成整数1,导致逻辑错误。我专门写了单元测试,用`0 OR 1=1`、`1e0`、`'1' OR '1'='1`这些变体去测,确保所有情况都被拦截。 现在回头看,预处理语句确实是PHP防护SQL注入的"新技术"最优解——但别以为用了就万事大吉!上个月我复盘时发现,有个搜索接口用了`LIKE`模糊查询,预处理时没对`%`和`_`转义,结果被注入`%'; DROP TABLE products;--`(虽然权限不够没成功,但吓出一身冷汗)。所以我的判断是:预处理必须配合参数类型检查和特殊字符处理,三者缺一不可——这比单纯用转义函数可靠10倍以上。
文章配图,仅供参考 下一步我打算研究下Web应用防火墙(WAF)的规则配置——毕竟预处理是代码层防护,WAF能在网络层拦截恶意请求。不过听说WAF误报率高,得好好调规则——要是你有相关经验,欢迎拍砖!(编辑:百科站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


PHP老兵看跨界融合:站长高效运营新路径
PHP赋能5G移动互联:轻量级通信技术新方案
嵌入式服务器安全加固:端口防护与数据加密实战
Go服务器安全开发:端口与数据传输精准防护
强化端口防护,筑牢服务器安全屏障
PHP进阶:后端架构师亲授安全防御与防注入实战
PHP进阶:嵌入式视角下的网站安全与SQL注入防护