我使用了一个特殊的图片上传技巧,绕过PHP GD库对图片的转换处理,最终成功实现了远程代码执行。php
事情是这样的。当时我正在测试该网站上是否存在sql注入漏洞,不经意间我在网站我的页面发现了一个用于上传头像的文件上传表单。开始时我并没期望在上传功能处发现漏洞,但我决定试试。html
我上传了一个图片文件,经过截断http数据包,修改jpg图片的文件名后缀为php,而后继续上传。我惊讶的竟然上传成功了,我几乎不敢相信这么简单的漏洞竟然存在。因而我复制了图片url而且在浏览器上打开。进入我眼帘的是图片的二进制代码,这意味着图片以php解析了,并根据响应包里的content-type以text/html格式返回。sql
我如今要作的是在jpg文件中注入php代码以进行远程代码执行,因而我尝试将代码<? phpinfo(); ?>写入图片的EXIF头里,可是悲剧的是再次上传发现php代码没有被执行。浏览器
在本机进行了测试,结果仍然无效——代码没有被执行服务器
在上传到服务器后,EXIF里的代码都被删除了,应用经过imagecreatefromjpeg()函数调用了PHP GD库(GD库,是php处理图形的扩展库),对图片进行了转换。那么若是不将代码注入EXIF头而是注入到图片里呢?编辑器
本机测试经过,但当我上传“1.jpg”到服务器上,返回如下结果:ide
报错上写着“文件必须是合法的图片(.gif, .jpg, .jpeg, 或.png)”,我惊叹于应用是怎么判断图片不合法的。我又测试了一些其余jpg文件,结果发现修改任何一个图片字符都会引发php-gd库的错误判断,进而形成上传失败。函数
接下来我又使用gif图片进行了一样的操做,结果是:图片上传成功了,可是图片中的php代码彻底被删除了。测试
虽然这看起来难以想象,可是我不能放弃,由于如今距离成功利用远程代码执行(RCE)只有一步之遥,我必须绕过imagecreatefromgif()函数。我对图片的处理和php GD库的运行知之甚少,但是这不影响我使用一些传统渗透测试方法。网站
我想到一个方法:对比两张通过php-gd库转换过的gif图片,若是其中存在相同之处,这就证实这部分图片数据不会通过转换。而后我能够注入代码到这部分图片文件中,最终实现远程代码执行。连我本身都佩服个人机智!
如图,我用十六进制编辑器打开图片文件,找到了php转换先后仍然保持相同的十六进制串“3b45d00ceade0c1a3f0e18aff1”并修改它为<?phpinfo()?>。
保存图片,上传到服务器:
个人PHP代码被执行了,我最终成功实现了远程代码执行。
POC图片下载地址:
POC.rar 密码freebuf