靶場首頁
打開靶場后,查看源碼即可看到<!--source.php-->
打開source.php頁面
代碼如下
<?php highlight_file(__FILE__); class emmm { public static function checkFile(&$page) { $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; if (! isset($page) || !is_string($page)) { echo "you can't see it"; return false; } if (in_array($page, $whitelist)) { return true; } $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); if (in_array($_page, $whitelist)) { return 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 "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; } ?>
審計php代碼
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
得到另一個地址/hint.php,打開以后提示我們flag在ffffllllaaaagggg里面
接下來,繼續審計source.php代碼
if (! empty($_REQUEST['file']) //$_REQUEST['file']值非空 && is_string($_REQUEST['file']) //$_REQUEST['file']值為字符串 && emmm::checkFile($_REQUEST['file']) //能夠通過checkFile函數校驗 ) { include $_REQUEST['file']; //包含$_REQUEST['file']文件 exit; } else { echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; //打印滑稽表情 }
這段代碼告訴們需要滿足三個條件
1.值為非空 2.值為字符串 3.能夠通過checkFile()函數校驗 否則打印滑稽
查看checkfile()函數
highlight_file(__FILE__); //打印代碼 class emmm //定義emmm類 { public static function checkFile(&$page)//將傳入的參數賦給$page { $whitelist = ["source"=>"source.php","hint"=>"hint.php"];//聲明$whitelist(白名單)數組 if (! isset($page) || !is_string($page)) {//若$page變量不存在或非字符串 echo "you can't see it";//打印"you can't see it" return false;//返回false } if (in_array($page, $whitelist)) {//若$page變量存在於$whitelist數組中 return true;//返回true } $_page = mb_substr(//該代碼表示截取$page中'?'前部分,若無則截取整個$page $page, 0, mb_strpos($page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } $_page = urldecode($page);//url解碼$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語句
1.第一個if語句對變量進行檢驗,要求$page為字符串,否則返回false 2.第二個if語句判斷$page是否存在於$whitelist數組中,存在則返回true 3.第三個if語句判斷截取后的$page是否存在於$whitelist數組中,截取$page中'?'前部分,存在則返回true 4.第四個if語句判斷url解碼並截取后的$page是否存在於$whitelist中,存在則返回true 若以上四個if語句均未返回值,則返回false 有三個if語句可以返回true,第二個語句直接判斷$page,不可用 第三個語句截取'?'前部分,由於?被后部分被解析為get方式提交的參數,也不可利用 第四個if語句中,先進行url解碼再截取,因此我們可以將?經過兩次url編碼,在服務器端提取參數時解碼一次,checkFile函數中解碼一次,仍會解碼為'?',仍可通過第四個if語句校驗。('?'兩次編碼值為'%253f'),構造url: http://399fe153-1f62-43d5-a67f-e645a0e7ac66.node3.buuoj.cn/source.php?file=source.php%253f../ffffllllaaaagggg
經過測試發現無返回值,這可能是因為我們不知道ffffllllaaaagggg文件存放的具體位置
所以依次增加../,最終成功拿到flag
http://xxxx:xxxx/source.php?file=source.php%253f../../../../../ffffllllaaaagggg