当前位置:首页 > 综合

php漏洞修复补丁

去年秋天,洞修丁一个做外贸站的复补朋友半夜给我打电话,说网站首页被挂了一串博彩链接。洞修丁我让他把Web目录打包发过来,复补翻了一遍没发现后门。洞修丁最后在`/vendor/`里找到一段被篡改的复补代码——攻击者利用的是一个三个月前就公开的PHP反序列化漏洞。他服务器上跑的洞修丁还是PHP 7.2,补丁一直没打。复补

这事不新鲜。洞修丁PHP漏洞修复补丁这件事,复补很多团队的洞修丁态度是“等有空再说”。但攻击者不等你有空。复补

补丁到底补的洞修丁是什么

PHP本身的漏洞大致分几类:内存破坏(比如`buffer overflow`)、反序列化问题、复补`include`路径穿越、洞修丁以及扩展层面的问题。拿最常见的反序列化来说,`unserialize()`函数在解析恶意构造的字符串时,可以触发对象注入,进而执行任意代码。2020年那个`PHP 7.4`的`filter_var`绕过漏洞就是一个典型——攻击者构造特殊输入,绕过`FILTER_VALIDATE_URL`的校验,最终导致SSRF。

补丁做的事情,往往就是在函数入口加一层校验。比如对输入长度做限制、对魔术方法调用链做白名单、对`__destruct`和`__wakeup`的触发条件加约束。听起来简单,但漏掉一个分支就是0day。

为什么很多人不打补丁

我观察下来,原因就三个字:怕出事。

一个跑了三年的老项目,PHP版本从7.0升到7.4,中间跨了好几个小版本。贸然打补丁,可能某个废弃函数被移除,某个扩展行为变了,网站直接白屏。测试环境又不完整,谁敢动?

另一个原因是“我觉得没人会盯上我”。小站、内部系统、测试环境——这些恰恰是自动化扫描工具的首选目标。攻击成本太低了,一个脚本扫全网,有漏洞的就打。

打补丁的正确姿势

别直接在生产环境上`apt upgrade php`。先做隔离测试。把当前PHP版本、已加载扩展、以及项目依赖的扩展版本全部列出来。然后在一个容器或虚拟机里,装目标版本的PHP,跑一遍项目的核心流程。我一般会写一个简单的`smoke test`脚本,覆盖登录、支付回调、文件上传这几个关键路径。

确认没问题后,再上生产。但别一次全量替换。用负载均衡把流量切一小部分到新版本节点上,观察错误日志和响应时间。没问题再逐步扩大。

还有一点:补丁不是只打PHP核心。扩展也要跟。比如`gd`、`curl`、`openssl`这些,它们自身的漏洞同样能拖垮整个应用。`php -m`看一眼加载了哪些,然后对照CVE列表逐个排查。

一个具体的修复案例

之前处理过一个`ThinkPHP 5.0`的远程代码执行漏洞。攻击者通过构造特定的`controller`和`action`参数,调用`Request`类的`filterValue`方法,最终执行`system()`。官方补丁是在`Request.php`里加了对`$this->filter`的白名单校验。

我手动合并补丁的时候发现,项目里有人改过这个文件,加了一些自定义的过滤逻辑。直接覆盖会丢代码,用`git merge`又冲突。最后是把官方补丁的那几行单独摘出来,手动插到自定义逻辑前面。这件事说明:打补丁不是无脑替换文件,得先看项目有没有魔改过核心代码。

补丁之外的事

打完补丁不代表就安全了。`php.ini`里的配置同样关键。`disable_functions`把`exec`、`system`、`passthru`这些禁掉,能挡掉一大半webshell。`open_basedir`限制PHP能访问的目录范围,防止跨站读取。`expose_php = Off`,别让响应头暴露PHP版本。

还有日志。很多人不打补丁是因为不知道自己的站已经被扫了。在Nginx或Apache层面记录所有包含`eval`、`assert`、`base64_decode`的请求,定期看日志,能提前发现攻击尝试。

补丁管理是个持续动作。我现在的习惯是:每周五下午花半小时,看一眼PHP官方安全公告和所用框架的更新日志。有补丁就评估,评估完就排期。不拖。

拖的成本,比打补丁高得多。

分享到: