PHP Web安全实战:SQL注入防护全解析
|
文章配图,仅供参考 前年我接手一个PHP老项目,用户登录模块被黑客用SQL注入搞瘫了三次——第一次是直接在用户名框输入`admin' --`,第二次升级防护后对方用`1' OR '1'='1`绕过,第三次更离谱,用`admin' AND 1=CONVERT(int, (SELECT @@version))--`直接把数据库版本号吐出来了。那会儿我天天盯着日志,发现攻击者连参数编码都懒得改,直接拿现成的SQLMap工具扫,半小时就能试出漏洞点。后来我翻遍PHP安全文档,发现最坑的是老代码里还在用`mysql_query()`——这函数2012年就被弃用了,但项目里70%的SQL操作都是它写的。比如有个查询用户余额的接口,参数直接拼进SQL字符串:`$sql = "SELECT balance FROM users WHERE id = ".$_GET['id'];`,攻击者输入`id=1; DROP TABLE users--`,数据库直接被清空。这种写法现在看简直像在门口贴"欢迎来黑"的告示。 新技术里最让我惊艳的是预处理语句(Prepared Statements)——用PDO或MySQLi扩展的`prepare()`和`bindParam()`,参数和SQL逻辑彻底分离。我测试过,同样用`1' OR '1'='1`攻击,预处理语句会把它当普通字符串处理,根本不会解析成SQL条件。去年我重构了整个项目的数据库层,把200多个SQL查询全换成预处理,攻击日志里的注入尝试直接归零——这效果比任何防火墙都实在。 但别以为换了预处理就万事大吉——我遇到过个更隐蔽的漏洞。有个搜索接口用`LIKE`模糊查询,代码里这么写:`$keyword = $_GET['q']; $sql = "SELECT FROM products WHERE name LIKE '%$keyword%'";`。虽然主查询用了预处理,但`LIKE`的通配符是直接拼进去的,攻击者输入`%'; DROP TABLE products--`,预处理只处理了变量部分,单引号还是能闭合语句。最后我改成用`CONCAT()`函数动态拼接通配符:`$sql = "SELECT FROM products WHERE name LIKE CONCAT('%', ?, '%')";`,这才彻底堵住漏洞。 还有个细节容易忽略——字符编码。前年有个项目用的`GBK`编码,攻击者输入`%df%' OR 1=1--`,`%df`在GBK里是"運"字的前半部分,和后面的单引号组成`運'`,刚好能闭合字符串。这种编码攻击在UTF-8里不会触发,但很多老系统为了兼容性还在用GBK。我的解决方案是统一用UTF-8,并在数据库连接时显式设置`SET NAMES 'utf8'`,同时在PHP端用`mb_convert_encoding()`检查输入是否合法。 最近我测了个新防护方案——用RASP(运行时应用自我保护)技术监控SQL执行。它在PHP扩展层拦截所有数据库操作,比如发现`DROP`、`TRUNCATE`这类危险命令直接阻断。我模拟攻击时,用`1; SELECT FROM information_schema.tables--`,RASP不仅拦截了语句,还记录了攻击者的IP和请求路径。不过这技术对性能有影响,高并发场景下响应时间增加了15%,小项目可能扛不住。 说句主观的——现在还在用字符串拼接写SQL的开发者,要么是刚入门,要么是懒到家了。预处理语句、ORM框架、RASP防护,这些新技术早该成标配。我承认,完全杜绝SQL注入不可能——比如0day漏洞、内网渗透这些场景,但把基础防护做好,至少能挡住90%的攻击。下次遇到有人问"怎么防SQL注入",直接甩他一句:别用`mysql_query()`,用预处理,设置字符编码,再加个WAF——这三板斧下去,黑客得换更高级的攻击方式了。 下一步我打算研究下AI检测SQL注入——比如用机器学习分析正常查询和攻击查询的语法差异。不过现在数据集太少,误报率可能很高,先拿测试环境跑跑看。你要是也有类似经历,欢迎来聊聊——说不定你的案例能帮我避开几个坑呢? (编辑:应用网_常德站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


PHP工程师私藏的12个冷门高效科技网站资源
PHP老兵看跨界融合:站长高效运营新路径
浙公网安备 33038102330457号