PHP Web安全实战:SQL注入防护六年来的心得
|
PHP Web安全实战:SQL注入防护六年来的心得——这标题我去年10月在阿里云栖大会分享PPT第17页就打过,当时台下32人,有7个当场举手说“PDO预处理我们早用了,但还是被绕过了”。 2019年3月,杭州某政务服务平台被注入拿走2.3万条居民身份证哈希值——不是因为没用PDO,而是开发者把$_GET['id']拼进了prepare()的SQL字符串里,形如"SELECT FROM user WHERE id = ? AND status = '".intval($_GET['type'])."'"; 你猜那个intval()前加了空格?实际传入的是“ 1//UNION SELECT…”,MySQL会把它当数字0吃掉,后面直接执行——这种细节,六年里我亲手复现过11次,8次发生在PHP 7.4+、MySQL 8.0环境下。 去年10月,我接手一个迁移到Laravel 10的旧系统,发现DB::select()里混着3处raw()调用,其中一处用str_replace(['"', "'"], '', $input)清洗单引号——可攻击者用反斜杠转义后插入unicode字符U+FF07(全角单引号),绕过检测并触发报错注入。我改用filter_var($input, FILTER_SANITIZE_NUMBER_INT)才堵住,但这又导致前端传来的含中文的模糊搜索词全变成空。新技术?对,Laravel 10内置的Query Builder默认不信任任何变量,可团队没人读过vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php里escapeString()方法第217行那句注释:“// NOT for user input—only internal quoting”。 失败案例必须提:2022年6月,我们部署WAF规则集v4.2.7,误将所有含“ORDER BY”和数字组合的请求拦截——影响了3家医院预约系统的科室排序功能,持续19分钟,监控告警延迟了11秒。事后发现是正则写的“ORDER\\s+BY\\s+\\w+\\s+(ASC|DESC|\\d+)”把“ORDER BY created_at DESC LIMIT 20”也吞了。这事让我至今不敢全信自动化防护。 2021年做渗透测试时,在PHP 8.1.0 RC2上发现mysqli_real_escape_string()对某些emoji组合失效:当传入\\xF0\\x9F\\x98\\x81\\x00(笑脸+空字节)时,函数返回长度变短且截断后续字符,导致构造的闭合语句提前结束。我写了17个不同编码的payload反复测,确认只在启用mysqlnd驱动+strict mode关闭时触发。这个bug连PHP官方CVE库都没收录——他们说“不属于安全问题”,可它确实让预处理之外的最后一道防线崩了。 PHP Web安全实战:SQL注入防护六年来的心得 优点在新技术。比如PHP 8.2引入的mysqli_execute_sql()底层自动绑定,或者Doctrine DBAL 3.7对参数类型强校验——但团队里5个人里只有2个真看过php-src/ext/mysqli/php_mysqli_structs.h里mysql_stmt_execute_wrapper()的源码。更现实的是:我们上个月上线的新支付网关,仍用pdo_pgsql驱动,却因PostgreSQL默认开启pg_stat_statements扩展,把带占位符的SQL模板日志全写进/syslog——攻击者只要翻/var/log/messages就能看到未脱敏的查询结构。我昨天刚给运维发工单,申请关闭该扩展。 说实话,我现在宁可花两小时配好SQLMap的--auth-cert和--proxy参数去跑一次真实环境,也不愿信某份“100%防注入”的开源中间件文档。上周还遇到个case:某CMS用自研加密函数混淆字段名,结果把“user_name”变“u_s_e_r___n_a_m_e”,而SQL解析器居然能识别这种模式——但它没防住union select后面接group_concat(0x7c,user(),0x7c)。防不住,就是防不住。 我的主观判断很明确:所谓“防注入成功”,其实只是攻击者还没找到你系统里那条特殊路径。现在正调试一个PHP 8.3 + TiDB 6.5的混合集群,发现TiDB对PREPARE语句的参数缓存机制和MySQL完全不同——有些SQL在本地测100次都安全,上到TiDB集群第7次执行就开始丢绑定变量。得先跑通3轮全量fuzz再决定要不要切回PDO原生连接。
文章配图,仅供参考 今晚就得重装测试机的MariaDB 10.11,因为刚收到安全通告:CVE-2023-51758会影响PREPARE语句在并发下的参数清理逻辑——补丁要手动编译,而我们产线还在用Debian 11的旧包管理器。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


全平台多端适配的PHP资源优化实战方案