程式碼審計--變數覆蓋漏洞
可能會導致變數覆蓋漏洞的函式有parse_str(),extract(),import_request_variables()以及$$。
1.parse_str()導致的漏洞
<!--
parse_str($a = $_GET['flag']);
if ($bdctf == "BCDEF") {
echo $flag;
}
-->
原始碼分析:a獲得一個get值$flag ,如果$bdctf == "BCDEF"輸出flag。
思路:由程式碼知,如果想要得到flag必須先輸入一個flag。看到 parse_str()想到變數覆蓋,構造payloa ?flag=&bdctf=BDCTF 得到flag
parse_str()定義和用法
parse_str() 函式把查詢字串解析到變數中。
註釋:如果未設定 array 引數,則由該函式設定的變數將覆蓋已存在的同名變數。
註釋:php.ini 檔案中的 magic_quotes_gpc 設定影響該函式的輸出。如果已啟用,那麼在 parse_str() 解析之前,變數會被 addslashes() 轉換。
語法
parse_str(string,array)
引數 | 描述 |
---|---|
string | 必需。規定要解析的字串。 |
array |
可選。規定儲存變數的陣列的名稱。該引數指示變數將被儲存到陣列中。 |
2.extract()漏洞
<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));
if($shiyan==$content)
{
echo'flag{xxx}';
}
else
{
echo'Oh.no';
}
}
?>
原始碼分析: extract() 獲得一個get值是shiyan。content從flag裡獲得一個去空的flag字串。如果相等,輸出flag。
思路:: 看到extract(),想到變數覆蓋,構造payload ?shiyan=&flag= 得到flag
extract()定義和用法
extract() 函式從陣列中將變數匯入到當前的符號表。
該函式使用陣列鍵名作為變數名,使用陣列鍵值作為變數值。針對陣列中的每個元素,將在當前符號表中建立對應的一個變數。
第二個引數 type 用於指定當某個變數已經存在,而陣列中又有同名元素時,extract() 函式如何對待這樣的衝突。
該函式返回成功匯入到符號表中的變數數目。
語法
extract(array,extract_rules,prefix)
引數 | 描述 |
---|---|
array | 必需。規定要使用的陣列。 |
extract_rules | 可選。extract() 函式將檢查每個鍵名是否為合法的變數名,同時也檢查和符號表中已存在的變數名是否衝突。對不合法和衝突的鍵名的處理將根據此引數決定。 |
prefix | 可選。請注意 prefix 僅在 extract_type 的值是 EXTR_PREFIX_SAME,EXTR_PREFIX_ALL,EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS 時需要。如果附加了字首後的結果不是合法的變數名,將不會匯入到符號表中。 字首和陣列鍵名之間會自動加上一個下劃線。 |
3.$$漏洞
1.<?php
2.include “flag.php”;
3.$_403 = “Access Denied”;
4.$_200 = “Welcome Admin”;
5.if ($_SERVER["REQUEST_METHOD"] != “POST”)
6. die(“BugsBunnyCTF is here :p…”);
7.if ( !isset($_POST["flag"]) )
8. die($_403);
9.foreach ($_GET as $key => $value)
10. $$key = $$value;
11.foreach ($_POST as $key => $value)
12. $$key = $value;
13.if ( $_POST["flag"] !== $flag )
14. die($_403);
15.echo “This is your flag : “. $flag . “\n”;
16.die($_200);
17.?>
原始碼分析:
1、 Include 呼叫了flag.php檔案
2、$_200,$403 定義兩個引數,以及引數值。
3、接著是兩個判斷語句,判斷訪問頁面的方法是否為post方法和有沒有引數flag。
4、再接著兩個foreach函式遍歷陣列函式,這裡就是把我們用get方法傳輸的資料當做陣列進行遍歷,並將遍歷的引數賦值給key,將引數值複製給value。
5、還有一個if判斷語句,判斷用post方法傳輸的資料是不是和$flag的值相同,如果相同,輸出flag。
6、最後輸出$200的內容。
解題思路:
由於第7,11-14行間的程式碼會將$flag的值給覆蓋掉,所以只能利用第一個foreach先將$flag的值賦給$_200,然後利用die($_200)將原本的flag值打印出來。
payload:
Get方法傳輸:?_200=flag
Post方法傳輸:flag=abcde