平滑升级到PHP 5.6.9,顺带升级Nginx 1.9.0

提醒:本文最后更新于 2627 天前,文中所描述的信息可能已发生改变,请仔细核实。

说要把 PHP 更新到5.6也不是一天两天了。前期做了很多准备,检查了所有这台 VPS 的线上项目,特别是把 PHP 所有过期代码更新为新函数。所幸没遇到坑。

然后因为最近也比较忙,每天很晚才到家,所以没有执行更新操作,经常大清晨就有人打电话来找。诶。

最近爆出 PHP 远程 DoS 漏洞,官方编号
69364(CVE-ID: 2015-4024)。几乎覆盖全版本。该漏洞利用 PHP 多次合并 boundary 里的参数,从而造成多次内存分配和拷贝,使得CPU资源占用100%,造成性能下降。攻击者利用并发多包的方式,可以达到使目标系统拒绝服务的目的。我使用的5.5.20版本,也在影响之列。

略微做了测试,发现被我做的规则挡掉了,还好,还好。

据我所了解的,微博用的最多了(Multipart/form-data),虽然我使用微博API并不完全遵从此协议(补充:所以旧的请求模式已经被拒绝了,过段时间再修复下文章同步微博的问题)。

攻击者可通过发送一个 2M 左右的包含多行 multipart 头部数据的 HTTP 请求来发起攻击,无需认证,也不依赖 PHP 程序本身的内容。例如,通过发送畸形请求,每隔若干秒,同时并发多个这样的请求,就会耗尽目标主机的 CPU 资源。

目前PHP 5.4、5.5、5.6均有官方版本解决该漏洞,其他更低版本PHP,也有民间组织做好了 patch 补丁。

星期四晚,比较累,睡了个早觉,星期五晚上,一大早,就把PHP升级到5.6.9,解决潜在问题,顺便把每个项目做一次调试,一切正常。发现离上班时间还早,遂把Nginx也给升级到最新版本1.9.0。

据说Nginx 1.9.0比较有特色的是流模块支持 TCP 代理和负载均衡(删除过时的 aio 和 rtsig 事件处理方法、还有可在 upstream 块中使用 "zone" 指令)。不过我都不需要用到。

Stream 模块(ngx_stream_core_module)在1.9.0后的版本将被启用。但是并不会默认安装,需要在编译时通过指定 --with-stream 参数来激活这个模块。

最后跑了一天,感觉上,没什么差异吧。反正正常就是了。

最后最后,把漏洞分析放上来:

HTTP协议中,multipart/form-data中可以包含多个报文,它们被合并在一个复杂报文中发送,每一个部分都是独立的,以':'分隔各自的参数和值,不同部分的报文通过分界字符串(boundary)连接在一起。

PHP中实现了解析multipart/form-data协议的功能,在解析时,当出现一个不包含':'的行,且之前有一个有效键值对,则说明该行是上一个键值对里的值,PHP会将值拼接到上一个键值对里。在拼接的过程里,PHP进行了一次内存分配,两次内存复制,以及一次内存释放。当出现多个不包含':'的行时,PHP就会进行大量内存分配释放的操作,从而导致消耗CPU资源性能下降。短时间多次发送这类畸形请求将导致目标服务器DoS。

转载请注明转自:kn007的个人博客的《平滑升级到PHP 5.6.9,顺带升级Nginx 1.9.0