Buuctf-Web-[HCTF 2018]WarmUp
前言
刷題地址:https://buuoj.cn/challenges
首先開啟是一個笑臉,檢視原始碼,如下圖發現了,一個檔案
一.程式碼分析
發現是一堆程式碼,需要PHP程式碼審計,全部程式碼如下。
1 <?php 2 highlight_file(__FILE__); 3 class emmm 4 { 5 public static function checkFile(&$page) 6 { 7 $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; 8 if (! isset($page) || !is_string($page)) { 9 echo "you can't see it"; 10 return false; 11 } 12 13 if (in_array($page, $whitelist)) { 14 return true; 15 } 16 17 $_page = mb_substr( 18 $page, 19 0, 20 mb_strpos($page . '?', '?') 21 ); 22 if (in_array($_page, $whitelist)) { 23 return true; 24 } 25 26 $_page = urldecode($page); 27 $_page = mb_substr( 28 $_page, 29 0, 30 mb_strpos($_page . '?', '?') 31 ); 32 if (in_array($_page, $whitelist)) { 33 return true; 34 } 35 echo "you can't see it"; 36 return false; 37 } 38 } 39 40 if (! empty($_REQUEST['file']) 41 && is_string($_REQUEST['file']) 42 && emmm::checkFile($_REQUEST['file']) 43 ) { 44 include $_REQUEST['file']; 45 exit; 46 } else { 47 echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; 48 } 49 ?>
檢視到了關鍵字眼hint.php
。
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
我們訪問這個檔案檢視,如下圖,發現flag在ffffllllaaaagggg
裡面
首先先看40-48行的內容! empty($_REQUEST['file']
的意思是傳參file
不能為空
is_string($_REQUEST['file']
的意思是傳參必須要字串
emmm::checkFile($_REQUEST['file']
這句話的意思是要經過checkFile函式的檢查
如果都為真那麼就執行include $_REQUEST['file'];
如果為否那麼就輸出滑稽圖片
由此可以總結
1.file傳參不能為空
2.file傳參必須要字串
3.需要經過checkFile函式的檢測
40 if (! empty($_REQUEST['file']) 41 && is_string($_REQUEST['file']) 42 && emmm::checkFile($_REQUEST['file']) 43 ) { 44 include $_REQUEST['file']; 45 exit; 46 } else { 47 echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; 48 }
接下來來看看,函式程式碼為5-38行,首先來看第一個if語句issset()
函式判斷是否設定了$page
,或者如果$page
不是字串就輸出you can't see it
然後返回為假。
第二個if語句判斷的是$page
是否在$whitelist
裡面,如果在那麼就返回true。
然後17行-21行是擷取$page
?前面的東西mb_substr()
函式是擷取,mb_strpos()
涵數是判斷字串首次出現的位置就是,擷取$page
0-?首次出現的位置的地方也就是擷取?前面的東西
22-24行又判斷$page
是否在$whitelist
裡面如果有那麼就返回true
26行對傳參進行了一次url編碼解碼
27-31又進行了一次擷取
32-34又進行了一次判斷是否在$whitelist
裡面,如果有那麼就返回true
總結來說
1.第一個if判斷是$是否設定了值或者是$page是否為字串,如果不是返回false
2.第二個if判斷的是$page是否在$whitelist列表裡面如果在就返回true
3.第三個語句是擷取$page問號前面的東西
4.第四個語句會對$page進行一次url編碼的解碼,加上瀏覽器就是兩次解碼
5.第五個語句還是擷取$page問好前面的東西
6.最後一個語句判斷$page是否在$whitelist裡面
如果上面四個if語句都沒返回那麼就返回false
class emmm
4 {
5 public static function checkFile(&$page)
6 {
7 $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
8 if (! isset($page) || !is_string($page)) {
9 echo "you can't see it";
10 return false;
11 }
12
13 if (in_array($page, $whitelist)) {
14 return true;
15 }
16
17 $_page = mb_substr(
18 $page,
19 0,
20 mb_strpos($page . '?', '?')
21 );
22 if (in_array($_page, $whitelist)) {
23 return true;
24 }
25
26 $_page = urldecode($page);
27 $_page = mb_substr(
28 $_page,
29 0,
30 mb_strpos($_page . '?', '?')
31 );
32 if (in_array($_page, $whitelist)) {
33 return true;
34 }
35 echo "you can't see it";
36 return false;
37 }
38 }
所以經過上面的判斷,payload應該是如下,測試其實不需要兩次編碼都可以,因為?
的解碼還是?
所以也可以直接/source.php?file=source.php?../../../../../../../../../../ffffllllaaaagggg
/source.php?file=source.php%253f../../../../../../../../../../ffffllllaaaagggg