打開頁面看到一個滑稽表情,f12發現提示source.php
進入該頁面,發現是代碼審計,代碼如下:
<?php highlight_file(__FILE__); //打印代碼 class emmm //定義emmm類 { public static function checkFile(&$page) //將傳入參數賦值給$page { $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; //申明白名單 if (! isset($page) || !is_string($page)) { //若$page變量不存在或存在非法字符 echo "you can't see it"; return false; //返回false } if (in_array($page, $whitelist)) { $page在數組中 return true; //返回true } $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } //截取$page中?前部分,若沒有截取整個$page $_page = urldecode($page); //url解碼 $_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 "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; } ?>
- 非空
- 類型為字符串
- 能夠通過checkFile()函數校驗
看到其中$whitelist數組有兩個值分別為source.php和hint.php,進入hint.php頁面:
- 第一個if語句對變量進行檢驗,要求$page為字符串,否則返回false
- 第二個if語句判斷$page是否存在於$whitelist數組中,存在則返回true
- 第三個if語句判斷截取后的$page是否存在於$whitelist數組中,截取$page中'?'前部分,存在則返回true
- 第四if語句判斷url解碼並截取后的$page是否存在於$whitelist中,存在則返回true
若以上四個if語句均未返回值,則返回false
有三個if語句可以返回true,第二個語句直接判斷$page,不可用
第三個語句截取'?'前部分,由於?被后部分被解析為get方式提交的參數,也不可利用
第四個if語句中,先進行url解碼再截取,因此我們可以將?經過兩次url編碼,在服務器端提取參數時解碼一次,checkFile函數中解碼一次,仍會解碼為'?',仍可通過第四個if語句校驗。('?'兩次編碼值為'%253f'),構造url:
http://***:***/source.php?file=source.php%253f../ffffllllaaaagggg
無返回值,由於我們不知道ffffllllaaaagggg文件的具體位置,只能依次增加../,最終在
http://***:***/source.php?file=source.php%253f../../../../../ffffllllaaaagggg中成功回顯flag
。