CTFshow-Web12:巧用PHP glob函数绕过文件读取限制
1. 初探CTFshow-Web12:一个典型的文件读取挑战
大家好,我是你们的技术朋友,今天我们来聊聊CTF比赛中一个非常经典的PHP文件读取绕过场景——CTFshow-Web12。这个题目看似简单,但里面藏着不少值得深挖的技术细节,特别是关于PHP中glob函数的巧妙应用。
先说说我最初接触这道题时的感受。打开题目链接,第一眼看到的是一个看似普通的网页,但经验告诉我,这种CTF题目往往在源码里藏着关键提示。果然,右键查看页面源代码,发现了一段注释,提示我们需要通过GET方式向cmd参数传入指令。这种设计在CTF中很常见,考察的就是我们对PHP代码执行和文件操作的理解。
我尝试直接调用系统命令,比如system('ls'),但没有回显。这说明题目可能对某些危险函数做了过滤。接着测试phpinfo(),发现能够正常执行并显示PHP配置信息,这确认了代码执行漏洞确实存在。不过,系统命令被限制,意味着我们需要寻找其他途径来读取文件内容。
这里就引出了今天要重点讨论的两个PHP函数:scandir()和glob()。很多人在做这类题目时,第一反应是用scandir()来列出目录内容,这确实是个好方法。但我想说的是,glob()函数在某些场景下更加灵活,特别是在需要绕过某些限制时。这道题的精髓就在于,它引导我们去思考:当常规方法受限时,如何利用PHP内置函数的特性来达到目的。
在实际的渗透测试或CTF比赛中,我们经常会遇到各种过滤和限制。这时候,对PHP函数的深入理解就显得尤为重要。glob()函数不仅能够列出文件,还支持通配符匹配,这个特性在绕过特定文件名的过滤时特别有用。我遇到过不少情况,题目过滤了常见的文件读取函数,但glob()往往能成为突破口。
2. 从scandir到glob:两种文件遍历方式的深度对比
2.1 scandir函数的基础与应用
我们先从大家更熟悉的scandir()函数说起。这个函数的作用是返回指定目录中的文件和目录数组,语法很简单:scandir(directory, sorting_order, context)。第一个参数是必需的,指定要扫描的目录;第二个参数可选,控制排序方式;第三个参数也很少用到,是目录句柄的上下文。
在CTFshow-Web12中,我们可以构造这样的payload:?cmd=print_r(scandir('./'))。这里有个小细节需要注意:最初我用了print()函数,但发现输出不完整。这是因为scandir()返回的是数组,而print()只能处理简单类型变量。换成print_r()后,就能清晰地看到当前目录下的所有文件了。
这时候,我发现了一个奇怪的文件名:903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php。这种长哈希值的文件名在CTF中很常见,通常是为了增加难度,让选手不能直接猜出flag文件的位置。看到这个文件,下一步自然是想查看它的内容。
我用了highlight_file()函数来读取文件:?cmd=highlight_file('903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php')。这个函数会把PHP代码高亮显示,非常适合查看源码。果然,文件里藏着flag:ctfshow{eae7ce01-7143-4333-aecb-6862cab465ce}。
2.2 glob函数的独特优势
现在来说说glob()函数。这个函数可能很多人不太熟悉,但它其实非常强大。glob()的作用是根据指定的模式匹配文件或目录,返回一个包含匹配结果的数组。它的基本语法是:glob(pattern, flags)。
与scandir()相比,glob()有几个明显的优势。首先,它支持通配符匹配。比如glob("*")会匹配所有文件,glob("*.php")则只匹配PHP文件。这种模式匹配能力在CTF中特别有用,尤其是当文件名未知或部分已知时。
在Web12这道题中,我们可以用?cmd=print_r(g