目录
访问除了一张滑稽图,就没其他的了
查看源码,有一个注释了的 source.php,可以尝试直接访问一下。同时进行目录扫描
访问source.php,里面包含php代码,题目说了是php代码审计,那就先从这里进行分析
提取其中的php代码
-
- highlight_file(__FILE__);
- class emmm
- {
- public static function checkFile(&$page)
- {
- //定义了一个白名单:source.php和hint.php,判断$page是否为空、是否为字符串
- $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
- if (! isset($page) || !is_string($page)) {
- echo "you can't see it";
- return false;
- }
- //判断&page是否在白名单中
- if (in_array($page, $whitelist)) {
- return true;
- }
-
- //取出$page问号前的东西,然后再判断$_page是否在白名单里,若存在则返回true;
- $_page = mb_substr(
- $page,
- 0,
- mb_strpos($page . '?', '?') //获取?号的位置索引
- );
- if (in_array($_page, $whitelist)) {
- return true;
- }
- //如果上一步判断失败,则又考虑了url编码的问题,因为url在传入以后服务器会自动进行一次解码。因此传入二次编码后的内容,就可以使checkfile返回true。
- $_page = urldecode($page);
- $_page = mb_substr(
- $_page,
- 0,
- mb_strpos($_page . '?', '?')
- );
- if (in_array($_page, $whitelist)) {
- return true;
- }
- echo "you can't see it";
- return false;
- }
- }
-
-
- if (! empty($_REQUEST['file'])
- && is_string($_REQUEST['file'])
- && emmm::checkFile($_REQUEST['file'])
- ) {
- include $_REQUEST['file'];
- exit;
- } else {
- echo "
"; - }
- ?>
1. 代码整体结构分析
首先定义了一个emmn的类,并且在类emm中定义了一个checkFile()函数,接着判断函数下面的if语句,即if (true && true && true)才能执行include函数,所以需要满足如下3个要求:
前面两个条件很好满足,只需要 source.php?file=字符串 ,即可。所以重点需要让checkeFile函数返回true,则会进行文件包含
2. chechkFile()函数分析
首先函数里的语句碰到return就会终止函数的执行,不管下面还有没有语句。函数中共有4个if,只需要让一个if返回true即可
所以根据第二个if,尝试访问 /source.php?file=hint.php,没有出现滑稽图,而出现了一个flag提示“flag not here, and flag in ffffllllaaaagggg”,提示flag存在于“ffffllllaaaagggg”这个文件中
../即回退到上级目录,在url中使用../的时候 ../最前面随便写什么都行,只返回../最后面的文件数据。
1.txt的内容如下
“ ?filename=1.txt../../../../../../../../../../Windows/System32/drivers/etc/hosts“,在这里../最前面的1.txt不会返回,只会返回后面的hosts
1.txt可以换成任何的字符都不会影响返回hosts
所以根据题目提示我们可以尝试构造如下进行获取flag(../的个数可以随便尝试)
- //这里其实包含的就是ffffllllaaaagggg,而不包含hint.php
- source.php?file=hint.php../../../../../ffffllllaaaagggg
此时函数实参 $page的值为 “hint.php../../../../../ffffllllaaaagggg”,但其并不在$whitelist白名单列表中,函数不会返回true。所以出现如下的画面
我们再回到checkFile函数中,第二个if是不能返回true了。观察第三个if代码,红色框中的意思为取出$page问号?前的字符再赋值给$page,最后再判断$_page是否在白名单里,若存在则返回true;
仔细分析后发现这段代码是有问题的。那如果构造poc如下,在hint.php后加上?。则经过mb_substr()的截取,返回的$page的值为 hint.php,刚好在白名单中通过校验。函数返回true。相当于访问?file=ffffllllaaaagggg,成功包含ffffllllaaaagggg文件
source.php?file=hint.php?../../../../../ffffllllaaaagggg
访问,获取flag{1eee2ed7-7ba6-498e-b1ae-ab2c59863701}