HackThisSite - Extended Basic Mission 02
Challenge
You have this function, provide the value which must be POST-ed as filename to obtain the desired results: Get the source code of hackthissite.org/index.php
给出一个把 POST 参数
filename拼上.php后读取文件的函数,要求给出filename的值,读到站点根index.php的源码。
1 |
|
Solution
file_get_contents
把一个路径当文件读成字符串,返回的是原始字节,不经过
PHP 解释器,所以读 .php 文件拿到的是源码。这正是题面要的
source code:读 index.php
得到它磁盘上的内容,而不是它渲染出来的页面。
路径完全由 $_POST['filename'] 决定,程序只做两件事:拼上
.php、然后读。没有任何目录白名单,也没有过滤
..。
函数固定追加 .php,乍看像扩展名黑名单。但
file_get_contents 不执行 PHP,读 .php
文件本来就是拿源码;而目标 index.php 的文件名里正好带
.php:追加的后缀恰好对得上,不构成障碍。真正要解决的是路径:提交处理脚本在
/missions/extbasic/ 下,目标是站点根的
index.php。
处理脚本位于站点根的下面两级,往上爬两级再指名
index:
1 | /missions/extbasic/ -> .. -> /missions/ -> .. -> / |
Key points
$_POST['filename']未经校验进入file_get_contents,构成路径遍历;用户控制的路径要先规范化再校验是否落在允许目录内(realpath后做前缀比对)。file_get_contents读的是源码而不是执行结果,所以给.php目标补.php后缀不构成防护:这里的扩展名过滤是错觉。../的层数取决于处理脚本相对目标的深度:本关处理脚本在/missions/extbasic/,距站点根两级,故用../../。- 现代 PHP 里
%00空字节截断早已失效(PHP 5.3.4 起字符串不再被 NUL 截断),本关也不需要它:目标本身就以.php结尾。