1. 程式人生 > >程式碼審計--變數覆蓋漏洞

程式碼審計--變數覆蓋漏洞

可能會導致變數覆蓋漏洞的函式有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