提醒:本文最后更新于 2806 天前,文中所描述的信息可能已发生改变,请仔细核实。
说要把 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》
我也是版本控
@vfhky: 我仔细看了你的文章。看来你也是笔记为主。
嗯,我不大想用centos7的原因主要是命令改变太多。如果改变命令习惯,我还不如转战ubuntu。。我现在还没打定主意,还用着6.6。
php7还在等稳定版(GA、RC),我一直想找台测试机来试试,不过还没实现这一目标。
@kn007: linux基本命令还是不会变的啊,centos7和centos6系列都没区别,ubuntu也是。不是生产,所以自己就先试了下php7,还行。
@vfhky: 很多命令要带ctrl,烦。
service多好,非要systemctl。。。不习惯,hostname也是。不习惯。。
这个只能慢慢变通了
@kn007: centos7 推荐systemctl但兼容service命令,只是会自动转换成对应的systemctl操作。有影响的应该是iptables防火墙的设置,6不能直接用到7上。centos、Ubuntu、debian都差不多,稍微熟悉下一样的。
@vfhky: 嗯,但以后总归要规范的