1、查看source.php出现如上php代码审计的页面
查看页面可以看到emmn类,其中的checkFile函数中有一个白名单(whitelist),其中包括source.php,和hint.php,在checkFile()函数中包括3个if语句,接着看到要打开file文件,就要执行include函数,而include函数执行的条件是if (true && true && true)才能执行,即要实现如下3个要求:
1)$_REQUEST['file']不为空,!empty($_REQUEST['file'] 才会返回true;
2)$_REQUEST['file']是字符串,is_string($_REQUEST['file']才会返回true;
3)checkFile($_REQUEST['file']返回true,emmm::checkFile($_REQUEST['file']才会返回true;
前面两个条件很好满足,只需要 source.php?file=字符串 。重点是需要让checkeFile函数返回true,则会进行文件包含include函数。
2、chechkFile()函数分析
首先函数里的语句碰到return就会终止函数的执行,不管下面还有没有语句。函数中共有4个if,只需要让其中一个if返回true,则checkFile函数即返回ture,第一个if不能执行括号中的内容,否则return false,函数终止执行。只需满足$page存在且为字符串。第2个语句可以执行,返回true。in_array函数是检查数组中是否存在某个值(找到true;找不false),特别注意这是在数组的键值中找,不包括键。即只要让$page值为source.php或者为hint.php就可以返回true。
所以根据第二个if,尝试访问 /source.php?file=hint.php,没有出现滑稽图,而出现了一个flag提示“flag not here, and flag in ffffllllaaaagggg”,提示flag存在于“ffffllllaaaagggg”这个文件中,如上图。
3、此时我们需要利用 “ ../ ” 这个命令来返回到文件的最上层并查询 “ffffllllaaaagggg” 这个文件,所以根据题目提示我们可以尝试构造如下进行获取flag(../的个数可以随便),source.php?file=hint.php../../../../../ffffllllaaaagggg(这里其实包含的就是ffffllllaaaagggg,而不包含hint.php),此时函数实参 $page的值为 “hint.php../../../../../ffffllllaaaagggg”,但其并不在$whitelist白名单列表中,函数不会返回true。所以出现如下的画面
4、我们再回到checkFile函数中,第二个if是不能返回true了。观察第三个if代码,这里的mb_substr()函数是表示截取的函数
,红色框中的意思为截取出$page问号?前的字符再赋值给$page,最后再判断$_page是否在白名单里,若存在则返回true;仔细分析后发现这段代码是有问题的,那如果构造poc如下,在hint.php后加上?。则经过mb_substr()的截取,返回的$page的值为 hint.php,刚好在白名单中通过校验,函数返回true。相当于访问?file=ffffllllaaaagggg,成功包含ffffllllaaaagggg文件,如下图。