php拒绝服务,源码级剖析PHP 7.2.x GD拒绝服务漏洞

*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。

*本文原创作者:chilau,本文属FreeBuf原创奖励计划,未经许可禁止转载

触发条件:php 7.2.x,开启gd库。只需要三行代码即可完成!

我在本地调试php的时候发现某个老代码能够直接把php给crash掉,因此成文。

c7c48d49f826e83c22ca976ccdfd1e72.png

php没有报错,直接死掉了,应该是内部逻辑有问题。再传到服务器上试试:

e36565ebe53a8db7f666917ac6aac779.png

啊哈,一样的结果。触发这个问题的代码如下:$im=imagecreate(100,100);

imageantialias($im,true);

imageline($im,0,0,10,10,0xffffff);

话不多说,上vs调试。先看调用堆栈吧。

c2d058d167b9c1d8398be45056748583.png

从这里可以看出是在GD库的画像素点的地方出了错,被调试器断在了gdImageSetAAPixelColor这个函数里。

0ab1e5db94bd12af75d5b8411c13995a.png

再看对应代码,访问了gdImagePtr结构体中的一个成员,导致访问违例。我们再从即时窗口检查一下:

888bfcd369484d0b434a8cf6cd31ea79.png

没错,tpixels是个空指针!

那tpixels是干啥的呢?在gd.h里面有如下说明:/* Truecolor flag and pixels. New 2.0 fields appear here at the

end to minimize breakage of existing object code. */

int trueColor;

int ** tpixels;

看来是和真彩色相关的东西,我们再沿着调用堆栈往前看。

c693862fb43fb6e70c6cae8e07fbb44d.png

这里是gdImageAALine函数,一个个点地画线,干的是苦力活。从gdImageLine里调用了它:

03551936240583b5842b925a26f314a9.png

这里的条件判断是是否开启了防锯齿功能。如果我们调用imageantialias函数打开这个功能,那么就会走这里来。

2710b1f77f1a52d2af966ade9defc2d8.png

上面图里就是我们从php调用的imageline函数的实现啦,非常简单。可以看出图片是真彩色的时候它会默认开启防锯齿功能。

这里问题就在于,我们创建(imagecreate)的图片不是真彩色的图,而后我们手动开启了防锯齿(imageantialias),调用进去想当然地把它当作一张真彩色图,从而导致了错误。

最后我们来看看两个函数的不同:

ed8f0f448cd77dfbfb778ef3e5752c9c.png

跟进去,可以看到imagecreate函数调用的gdImageCreate里直接把真彩色相关的成员设为了null。

与之对比,imagecreatetruecolor函数调用的gdImageCreateTrueColor函数里为每个像素点都分配了对应内存并初始化为0了:

2f88a7c593c1af8503275a2e19388eeb.png

总结一下,从上面分析可以看出,触发这个问题的条件有3个:1.php版本为7.2.x且开启了gd库

2.创建了非真彩色图且开启抗锯齿

3.在创建的图句柄上进行像素点写入

导致这个问题的原因还是代码修改考虑不周全,引入了新的漏洞;没有对所有可能条件进行测试,所以从php 7.2.0一直到php 7.2.4都还存在问题。

已经向php官方报告,如果正在生产环境使用相关版本请退回旧版本,旧版本里不存在这个问题。

*本文原创作者:chilau,本文属FreeBuf原创奖励计划,未经许可禁止转载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值