PHP安全编码三大致命坑:网关工程师的血泪避坑指南
|
掘金这地方,老有人发“PHP安全三剑客”那种带emoji的清单体——我点开就划走。不是瞧不上,是看见那标题底下第一行写“防SQL注入只要用PDO预处理”,手就抖。上个月二十三号,地铁三号线,我蹲在车厢角落掏手机复现那个报错,手机壳边角都磨白了,屏幕反光里照见自己眼角抽动。 三个坑?真要命的就三个:动态函数调用、unserialize硬刚、PATH_INFO绕过。别的都是毛毛雨。去年七月的事,不提年份,只说那天下午四点十七分,网关日志里突然飘出三百七十二个200带Set-Cookie头的POST /api/v1/user/login,但上游Auth服务压根没打log。我们盯了十八秒,陈工把键盘拍出脆响,张工蹲在地上翻测试机——桌上排成一排七台Android机,六台亮着,一台黑屏,黑屏那台正连着Charles抓包,USB线弯了两道直角。 动态函数调用?呵。我原以为只要grep -r ‘$func(’就够了,结果漏了那个vendor包里的__call()魔改。它把method名拼进去,再eval。eval你妈啊!那个包叫php-legacy-router,某个小版本,commit哈希我敢打包票是a7c3d1f,但tag名?我说不准。产品经理站在工位隔板外头,胳膊支在塑料挡板上,说“就这么点东西,明天上线吧”,声音跟没开盖的保温杯一样闷。我回他“那你亲手写个preg_replace_callback_array出来”,他没接话,转身时把桌角一盆绿萝碰歪了,水滴到我凉了的外卖盒盖上,滋啦一声,像微型短路。
文章配图,仅供参考 第二个坑是unserialize。别跟我扯‘加白名单’,你们加的白名单还在config/autoload/allowed_classes.php里手写数组?我们上个月追查一个JWT校验失败链,最后发现是网关层接了个老系统传来的base64序列化字符串,解码后直接unserialize——它根本没走JWT验证入口,压根不在API schema里,藏在X-Forwarded-For头后面,用冒号分隔,第三个字段。谁设计的?王磊,就是总穿灰卫衣那个,他离职前写的文档里写着“兼容历史header格式”,没写“含可执行对象”。UI走查时的沉默,就是那一刻:设计师指着mockup上那个登录按钮说“这个跳转动画能不能快半帧”,没人吭声,空调风刚好吹灭了我桌上第三根烟,烟灰掉进键盘F键缝里。PATH_INFO绕过更阴。不是nginx配置问题,是PHP自己作死。某些FastCGI模式下,PATH_INFO会吃掉第一个斜杠后面的字符——比如请求/api/v2/../../etc/passwd,它解析成v2/../../etc/passwd,然后你的router::dispatch()直接按path segment切片,切出['v2', '..', '..', 'etc', 'passwd'],再手动pop掉两个..,以为安全了。其实没用。它早被PHP底层截了一刀。这个漏洞在某个小版本里修过,但补丁只打在apache SAPI上,没打CLI和FastCGI——而我们网关偏偏跑在supervisor启的php-fpm池里。这事是我查了三天strace才撞明白的。凌晨一点零七分,我在内网复盘通报里贴了tcpdump片段,配文:“看红框里那个HTTP_X_PATH_INFO,再看下面fwrite参数……它比你信任的还多一个字节。” 说到底,PHP安全不是代码问题,是淘汰机制问题。你用二十年前的扩展机制写网关路由,用十年前的session存储逻辑扛百万QPS,不出事才怪。优胜劣汰这词听着冷,但你看一眼公司内部PHP使用率曲线——从2019年起,所有新模块清一色Go,就剩我们网关还吊着,因为重构成本太高。高在哪?在那些散落在各处的__autoload()里,在那些require_once路径拼接的字符串里,在那些注释里写着“此处勿动”的二十行if-else嵌套里。不是技术不行,是沉没成本咬住了脚踝。 上周五,我和运维老赵在机房清点旧物理机,三台DELL R720,编号分别是PH-GW-01、PH-GW-02、PH-GW-03。老赵用指甲刮机箱侧面标签,说“这漆快掉完了”。我盯着其中一台电源指示灯,绿色,常亮,但面板没任何流量灯在闪。它其实在跑,跑一个三年前下线的服务的fallback逻辑,只是没人记得删掉crontab里的那个curl。现在那个curl每五分钟调一次/test.php,test.php里有一行die("ok");,就这样,一直活着。 明儿我得重装一遍本地dev环境,把PHP切到8.2,顺手试试那个disable_functions是否真能拦住pcntl_fork。如果拦不住……我可能真得去学学Lua,就Nginx自带那个。反正V2EX上有个哥们说他用openresty写网关中间件,写了七千行,没一个exec。我不信,但今晚想看看。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


缓存老兵20年实战:创业合规避坑指南
Linux新手避坑指南:5年服务网格工程师亲授
ASP脚本避坑指南:老网工血泪总结5大语法雷区
ASP脚本避坑指南:90%开发者忽略的语法雷区
网站搭建总卡壳?AI工程师的多媒体运维避坑指南
嵌入式Linux开发者Unix环境搭建避坑指南

