PHP Web安全实战:19年物联网工程师的SQL注入防护秘籍
|
去年10月份,我接手过一个物联网设备管理平台的PHP重构项目——那套系统用了五年,被安全团队扫出17个高危SQL注入漏洞,其中3个是直接能拖库的。最离谱的是用户登录接口,参数`$username`直接拼进SQL:`"SELECT FROM users WHERE username='$username' AND password='$password'"`——这不就是给黑客递刀子?我当场把开发文档摔在桌上,发现连最基础的`addslashes()`都没用,全靠前端JS做校验,这不是自欺欺人吗? 我第一刀砍的就是参数拼接——直接上PDO预处理语句。但别以为换了PDO就万事大吉,去年我测过某IoT厂商的固件升级接口,他们用PDO却没禁用`PDO::ATTR_EMULATE_PREPARES`,结果攻击者通过`UNION SELECT`照样能读到数据库版本。所以我的做法是:初始化PDO时强制关闭模拟预处理,`$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false)`,同时设置`PDO::ATTR_ERRMODE`为异常模式,这样任何SQL错误都会直接抛出,避免信息泄露。 但预处理只能防住90%的注入——剩下的10%得靠白名单过滤。去年我处理过一个智能电表查询接口,参数是设备ID,格式是`DEV-123456`。有攻击者试了`DEV-123456' OR 1=1--`,虽然预处理挡住了,但为了彻底杜绝,我写了正则`/^DEV-\d{6}$/`,不符合格式的直接返回400错误。有人说正则性能差?在物联网场景里,设备ID查询频率本来就低,这点开销比被拖库的损失小多了——上个月那家厂商被拖了30万条设备数据,赔了200多万,这时候谁还在乎那0.1ms的延迟?
文章配图,仅供参考 新技术里最让我惊喜的是PHP 8.1的`filter_var()`增强——以前过滤参数得自己写函数,现在用`FILTER_VALIDATE_INT`、`FILTER_SANITIZE_STRING`能省一半代码。不过别迷信内置过滤器,去年我测过`FILTER_SANITIZE_STRING`,它会把单引号转成HTML实体,但不会处理反斜杠,结果攻击者用`\' OR 1=1`还是能绕过。所以我的习惯是:先用`filter_var()`做基础过滤,再用自定义正则做二次校验,双重保险才安心。失败案例?太多了——去年我同事用`mysqli_real_escape_string()`处理参数,觉得万无一失,结果被攻击者用`%df%27 OR 1=1--`绕过(GBK编码下,`%df%27`会被转义成`縗'`,但后面的`OR`能正常执行)。这事儿给我敲了警钟:老方法在新环境下可能失效,必须紧跟技术更新。现在我的代码库里有个`SqlInjectHelper`类,集成了PDO预处理、正则白名单、编码检测(特别是GBK/UTF-8切换场景),上个月安全测试零漏洞通过——这可比写100篇安全文档有用多了。 但我也承认局限——物联网设备常跑在资源受限的环境里,比如某款智能门锁的PHP解释器是5.3版本,连PDO都不支持。这时候只能用`mysqli_prepare()`,但得手动绑定参数类型,稍不注意就出错。上个月我就在这上面栽过跟头:把字符串参数绑成整数,导致预处理失败,系统直接返回原始SQL错误,差点泄露表结构。所以我的建议是:老项目升级时,先做兼容性测试,别盲目上新技术——安全是相对的,稳定才是第一位的。 下一步我打算研究PHP的JIT编译对SQL注入防护的影响——听说8.3版本的JIT能优化正则匹配性能,或许能让白名单过滤更快。另外,物联网设备常用SQLite,它的预处理机制和MySQL不太一样,得专门写套适配代码。安全这事儿,永远没有终点,你说是不是? (编辑:PHP编程网 - 钦州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


PHP工程师跨界创业:技术整合实战手册
浙公网安备 33038102330484号