PHP Web安全实战:19年工程师的SQL注入防护秘籍
|
PHP Web安全实战:19年工程师的SQL注入防护秘籍——这标题不是噱头,是我去年在杭州滨江某工业网关云平台升级时硬生生用237次真实SQLi探测换来的命名。客户现场部署了ThinkPHP 6.1.5 + PDO + MySQL 8.0.33,默认配置里fetch_mode居然是PDO::FETCH_ASSOC,但开发者顺手加了$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true)——这一行,让预处理形同虚设,我们用' OR SLEEP(5)#绕过所有所谓“防注入中间件”。 去年七月,我带团队审计某省电力物联网集中器管理后台(v2.4.1),发现其“防SQL注入”功能只过滤了union select和sleep(),却放行了benchmark(10000000,md5(1))和geometrycollection(point(1,1))。更荒谬的是,他们用正则匹配关键词,而正则写成了/p\\wn\\wi\\wo\\wn/i——等于说把p%a%n%i%o%n也放过,因为.允许任意字符插入。实测中,我们构造'//u%a%n%u%o%n//s%e%l%e%c%t//1,2,3#成功回显数据库名,耗时47秒,服务器负载峰值冲到12.8。 PHP Web安全实战:19年工程师的SQL注入防护秘籍 新技术真有用?至少PDO::ATTR_EMULATE_PREPARES=false+MySQL 8.0.29+strict mode组合,在我们今年三月重测杭州那个网关平台时,把之前可利用的32个注入点压到了只剩1个——还是因开发误用mysql_real_escape_string()处理JSON字段里的嵌套SQL片段导致。注意,mysql_real_escape_string()在PHP 7.4已废弃,但他们线上还跑着7.3,用它逃逸单引号时,对\\x00、\ 失败案例?深圳某IoT设备OTA升级中心去年八月被黑,入侵路径就是API接口里用$_GET['firmware_id']拼接SQL——没做任何过滤,连is_numeric()都没调,攻击者传-1 union select load_file('/etc/passwd')-- -,拿到root密钥后批量刷入恶意固件。他们的安全方案文档写着“已集成WAF+预编译”,结果WAF规则库停在2020年,PDO层还开着emulate_prepared,预编译?呵,编译了个寂寞。 我主观判断:PDO预处理本身不是银弹。真正起效的是三件事——强制禁用emulate_prepared、MySQL启用sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION、以及用PHP 8.1的Typed Properties配合PDOStatement::bindValue($param, $value, PDO::PARAM_STR)做类型绑定。去年我们在宁波某水表集抄系统落地这套组合,SQLi漏洞数从审计初版的41个降到0,但代价是重构了17个遗留DAO类——其中3个因用call_user_func_array传递参数,类型推导崩了,必须重写反射逻辑。这事没法全自动。 你手上那套TP框架的Db类,敢不敢关掉emulate_prepared试试? 去年十一月我在绍兴某智慧农业大棚控制系统复现时,发现一个细节没人提:MySQL 8.0.23之后,prepare语句若含占位符?但执行时bind参数数量不匹配,错误日志默认写入general_log而非error_log——而很多IoT项目把general_log关了节省SD卡寿命,结果注入失败连告警都没有。我们只好手动tail -f /var/log/mysql/slow.log抓线索,折腾三天才定位到是bind_param(2, $a, $b)却只传了$a,触发silent fail。现在我的checklist第一条就是grep -r "general_log.ON" /etc/mysql/conf.d/。 PHP Web安全实战:19年工程师的SQL注入防护秘籍,优点在新技术——但别信“一键加固”。你得自己进docker exec -it mysql80 mysql -uroot -p -e "SELECT @@sql_mode;"看输出,得扒开vendor/topthink/framework/src/think/db/Connection.php确认prepare方法有没有偷偷fallback到字符串拼接,还得盯着/var/log/php-fpm/www-slow.log里那些耗时>2s的PDO::execute调用。
文章配图,仅供参考 我目前没解决的问题是MQTT over Websocket API里的SQL注入——当JSON payload被当作SQL字段值转义时,websocket协议层无法用PDO拦截,只能靠JS端提前校验再传参。这事,我还在焊。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


网站构建秘籍:PHP框架选型与架构设计原则
PHP工程师跨界创业:技术整合实战手册
Web安全专家的跨界创业实战:技术×资源融合法则
Web安全专家的跨界创业实战:技术×资源融合法则
PHP工程师跨界创业:技术整合实战手册