背景
在之前一些版本的 PHP 中, 由于PHP解析multipart/form-datahttp请求的body part请求头时,重复拷贝字符串导致DOS。 如果远程攻击者通过发送恶意构造的multipart/form-data请求,会导致服务器CPU资源被耗尽,从而远程DOS服务器。 相关漏洞分析参见:
PHP multipart/form-data 远程DOS漏洞- 百度安全攻防实验室
事态发展
该漏洞 PHP 官方已经认可,针对 PHP 5.4 5.5 版本发布了官方漏洞补丁,由于 PHP 5.3 版本已经超过了官方的支持年限,故没有官方的不定。 针对 PHP 5.3 版本有
民间补丁
现有服务器环境分析
- Centos 5.8.x
- yum 安装的 Apache PHP Mysql
PHP 是 yum 安装的,所以打补丁的方式排除。只能升级 PHP 版本解决这个问题了。 由于是线上环境,删掉旧版本 PHP,然后用 yum 安装新版本 PHP 的风险感觉太大。 讨论发现,编译安装一个新版本的 PHP,然后用 Apache 连接新的 PHP 的风险最小
升级过程记录
预备
PHP7 移除了 mysql 扩展,由于不清楚老项目的相关连接,所以直接升级为 PHP7 的风险较大,转而打算升级为 PHP 5.6.25。
PHP 编译安装
wget 下载 PHP 5.6.25 , 然后编译安装
cd /opt
wget http://am1.php.net/get/php-5.6.25.tar.gz/from/this/mirror
tar zvxf php-5.6.25.tar.gz
cd php-5.6.25
yum -y install libxml2 libxml2-devel openssl openssl-devel curl-devel libjpeg-devel libpng-devel freetype-devel libmcrypt-devel
./configure --prefix=/usr/local/php56 \
--with-config-file-path=/usr/local/php56/etc \
--with-config-file-scan-dir=/usr/local/php56/etc/php.d \
--with-apxs2=/usr/sbin/apxs \
--with-mcrypt=/usr/include \
--enable-mysqlnd \
—with-mysql
--with-mysqli \
--with-pdo-mysql \
--with-gd \
--with-iconv \
--with-zlib \
--enable-xml \
--enable-shmop \
--enable-sysvsem \
--enable-inline-optimization \
--enable-mbregex \
--enable-mbstring \
--enable-ftp \
--enable-gd-native-ttf \
--with-openssl \
--enable-pcntl \
--enable-sockets \
--with-xmlrpc \
--enable-zip \
--enable-soap \
--without-pear \
--with-gettext \
--enable-session \
--with-curl \
--with-jpeg-dir \
--with-freetype-dir \
--enable-opcache
make
make install
cp php.ini-production /usr/local/php56/etc/php.ini
小插曲一
在 PHP 编译的时候使用了 apxs2 的方式,至于是为什么,是因为在 Apache 配置文件 httpd.conf 看见引用 PHP 是使用 so 文件的方式。 除此之外, PHP 与 Apache 连接有cgi , fastcgi,php-fpm 和 php.so这几种方式。不同的方式在编译的时候加的参数不同,需要注意一下,编译成想要的东西
小插曲二
在写 PHP 编译参数的时候,我发现找不到 apxs2,最后通过文章
Apache HTTP服务器扩展模块的工具-apxs 解决了问题。 也就是在编译之前执行了
yum install httpd-devel –y
rpm –ql httpd-devel | grep “apxs”
然后指定了 apxs2 的路径
Apache 连接新版本的 PHP
Apache 是通过 so 文件连接 PHP 的,由于我们配置了 apxs,所以会自动生成相关的东西(不是很清楚到底是怎么回事,突然就好了。。。)
升级后续
- HOJ 题目列表无法打开
查看日志,发现是timezone问题,设置 timezone 即可
- Error establishing database connection
无法连接数据库,解决过程如下: 首先,编写了测试脚本,然后就发现了奇怪的问题,浏览器中查看发现HTTP connection reset ,日志中返回 200
思考: 估计是工大的防火墙会过滤服务器输出的错误信息。因此,要debug这类问题,可以写一个脚本,在命令行中执行:
/usr/local/php56/bin/php a.php
直接在命令行中查看输出的错误信息,从而定位问题。
最终原因: PHP 5.6 中 mysqlnd 不支持 Mysql 的 old_password 格式(16字节)
解决方案:
mysql_connect(): The server requested authentication method unknown to the client [mysql_old_password] in 将 my.cnf 中的 old_passwords 暂时关闭,重启 Msyql 服务并更新指定用户的密码,然后再打开 old_passwords ,再重启 Mysql 即可。
comment old_passwords=1
restart mysql
add/modify user
uncomment old_passwords=1
restart mysql
兼容性考虑: 上述方案保持了其他用户的密码格式不变,从而最大限度保持兼容性
注意
此记录为个人事后记录,难免可能会忘掉一些细节性的东西