天天看點

變量覆寫漏洞變量覆寫漏洞

**

變量覆寫漏洞

**

全局變量覆寫

1)變量如果未被初始化,且能被使用者所控制,那麼很可能會導緻安全問題。而在PHP中, 這種情況在register_globals為ON時尤其嚴重。在PHP 4.2.0之後的版本中,register_globals預設由ON變為了 OFF。register_globals的意思就是注冊為全局變量,是以當On的時候,傳遞過來的值會被直接的注冊為全局變量直接使用,而Off的時候,我們需要到特定的數組裡去得到它。

<?php
// 當使用者合法的時候,指派 $authorized = true
if (authenticated_user()) {
    $authorized = true;
} 
// 由于并沒有事先把 $authorized 初始化為 false,
// 當 register_globals 打開時,可能通過GET auth.php?authorized=1 來定義該變量值
// 是以任何人都可以繞過身份驗證
if ($authorized) {
    include "/highly/sensitive/data.php"; phperz.com
}
?>  
           

2)通過GLOBALS擷取的變量,也可能導緻變量覆寫。

<_?php
echo ,Register_globals:(int) ini_get ("register_globals") . "<br/>n;
if (ini_get(register一globals) foreach($_REQUEST as $k=>$v) unset($($k)); //此代碼是禁用register_globals,如上所述,會以數組的形式通路變量。
print $a; 
print $__GET [b];
?>
           

比如我們有一個url:

http://www.axom/testl .php?a=l &b=2
           

當register_globals=on的時候,我們輸入以上url,由于變量a沒有被初始化,并且因為有禁用代碼(此時register_globals為off)會出錯。但是如果我們輸入以下url:

http://www.a.com/test I .php?GL0BALS[a]=1&b=2
           

即使我們的register_globals為off,但是此時變量a變成了全局變量,unset函數隻會銷毀局部變量,而不會銷毀全局變量,是以變量a成功輸出沒有報錯。

我們要摧毀局部變量必須使用$GLOBALS。我們看以下代碼:

<?php
function foo{
unset($GL0BALS[ 'bar']);//此代碼的作用就是銷毀全局變量bar
$bar = "something”;
} 
foo();
?>
           

這段代碼使用了全局變量,但是當我們的register_globals=off的時候,無法覆寫到全局變量。

總的來說就是,我們能否使用全局變量取決于register_globals是否開啟。

總結以上:

就是說我們在防止全局變量覆寫的時候,首先我們可以使用register_globals=off,但是使用者使用全局變量GLOBALS的仍然能夠突破register_globals=off的限制,要解決此問題我們可以用$GLOBALS來銷毀全局變量。

**

extract()變量覆寫

**

extractO函數能将變量從數組導入目前的符号表,其函數定義如下:

int extract ( array $var_array [, int $extract_type] [, string $prefix ])

其中,第二個參數指定函數将變量導入符号表時的行為,最常見的兩個值是“EXTR_OVERWRITE” 和 “EXTR—SKIP”。當值為“EXTR_OVERWRITE”時,在将變量導入符号表的過程中,如果變量名發生沖突, 則覆寫已有變量:值為“EXTR_SKIP”則表示跳過不覆寫。若第二個參數未指定,則在預設情 況下使用“ EXTR_OVERWRITE。

<?php
$auth = 0;
extract($_GET);
if ($auth == 1){
echo "private!";
}
else {
echo "public"
}
?>
           

當extract()函數從使用者可以控制的數組中導出變量時,可能發生變量覆寫。在這個例 子裡,extract() 從$_GET中導出變量,進而可以導緻任意變量被覆寫。假設使用者構造以下 連結:

http://www.a.com/testl.php?auth=l
           

一種較為安全的做法是确定register_globals = OFF後,在調用extract()時使用 EXTR_SKIP保證已有變量不會被覆寫。但extract()的來源如果能被使用者控制,則仍然是一種非常糟糕的使用習慣。同時還要留意變量擷取的順序,在PHP中是由php.ini中的 variables_order所定義的順序來擷取變量的。

variables_order:

該設定描述PHP解析變量順序,包括GET,_POST,COOKIE,_ENV ,$_SERVER 數組,

解析順序從左到右,後解析新值覆寫舊值。預設設定為EGPCS(Environment,GET,POST,Cookie,Server)。

如果将其設為“GP”,會導緻 PHP 完全忽略環境變量,cookies 和 server 變量,并用 POST 方法的變量覆寫 GET 方法的同名變量。

在這裡我們實戰一下 :

BUGKU代碼審計之extract變量覆寫

**

周遊初始化變量

**

常見的一些以周遊的方式釋放變量的代碼,可能會導緻變量覆寫。

$ehs =";
if($_POST && $charset != 'utf-8') {
$chs = new Chinese('UTF-8', $charset); 
foreach ($__POST as $key => $value) {
$$key = $chs->Convert($value);
}
unset($chs);
           
<?php
$a = 'abc';
$$a = 789;
echo $abc;
?>
           

簡單的解釋一下代碼:

$a =abc;

 $$a可以了解為先解析後邊這個$a,然後在進行解析,最終解析成為$abc

  是以直接列印$abc就是一個變量,列印出來就是789
           

具體實戰:

¥¥變量覆寫問題

**

import—request_variables 變量覆寫

**

import_request_variables()将GET、POST、Cookie中的變量導入到全局,使用這個函數隻 需要簡單地指定類型即可。其中第二個參數是為導入的變量添加的字首,如果沒有指定,則将 覆寫全局變量。

<?php
$auth = 'O';
import_request一variables('G');
if ($auth ~ 1){
 echo "private!";
}
else {
echo "public!"; 
}
?>
           

以上代碼中,import_request_variablesCG’)指定導入GET請求中的變量,進而導緻變量覆 蓋問題。

import_request_variables — 将 GET/POST/Cookie 變量導入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局變量,那麼此函數就很有用。

**

parse_str()變量覆寫

**

parse_str() 函數用于把查詢字元串解析到變量中,如果沒有array 參數,則由該函數設定的變量将覆寫已存在的同名變量。 極度不建議 在沒有 array參數的情況下使用此函數,并且在 PHP 7.2 中将廢棄不設定參數的行為。此函數沒有傳回值。

如果指定了 parse_str()的第二個參數,則會将query string中的變量解析後存入該數組變量 中。是以在使用parSe_str()時,應該養成指定第二個參數的好習慣。

parse_str函數導緻的變量覆寫問題