首頁 > 軟體

PHP變數覆蓋漏洞小結

2020-09-23 22:30:54

前言

變數覆蓋漏洞是需要我們需要值得注意的一個漏洞,下面就對變數覆蓋漏洞進行一個小總結。

變數覆蓋概述

變數覆蓋指的是可以用我們自定義的參數值替換程式原有的變數值,通常需要結合程式的其他功能來實現完整攻擊。那麼它是如何引起的?其實,大多數變數覆蓋漏洞是函數使用不當導致的。比如extract()函數和parse_str()。還有一個函數是import_request_variables(),它是在沒有開啟全局變數註冊的時候,呼叫這個函數相當於開啟了全局變數註冊,在PHP5.4之後,這個函數被取消了。還有一種是利用$$的方式來註冊變數,但是沒有驗證已有變數,導致被覆蓋。

extract()函數使用不當導致變數覆蓋

函數結構:
int extract( array &$var_array[, int $extract_type = EXTR_OVERWRITE[, string $prefix = NULL]] )
再看一下PHP手冊對這個函數的說明

說的通俗點就是將陣列中的鍵值對註冊成變數。extract()函數想要變數覆蓋,需要一定的條件。它最多允許三個參數,用表格說明一下這三個參數:

由上圖可知,該函數有三種情況會覆蓋掉已有變數。下面用一段簡單的程式碼來加深印象。

<?php
$b=2;
$a=array('b'=>'123');
extract($a);
echo $b;
?>

原來$b=2,經過extract()函數對$a處理後,$b被成功覆蓋為123。

parse_str()函數使用不當導致變數覆蓋

parse_str()函數的作用是解析字元串並且註冊成變數,它在註冊變數之前不會驗證當前變數是否存在,所以會直接覆蓋掉原有變數。函數說明如下:
void parse_str( string $str[, array &$arr] )
函數有兩個參數,第一個是必須的,代表要解析註冊成變數的字元串,比如“a=1”經過parse_str()函數後會註冊$a並複製為1,第二個參數是一個數組,當第二個參數存在時,註冊的變數會放到這個數組裡,如果原來有相同的鍵值,則會覆蓋掉它。
用一段簡單的程式碼加深印象:

<?php
$b=2;
parse_str($b=321);
print_r($b);
?>

我們發現$b的值被覆蓋為321。

$$變數覆蓋

先看引起覆蓋的一小段程式碼:

<?php
$a=1;
foreach (array('_COOKIE','_POST','_GET') as $_request){
    foreach ($$_request as $_key =>$_value){
        $$_key = addslashes($_value);
    }
}
echo $a;
?>

它為什麼會導致變數覆蓋呢?重點在$$符號,從程式碼中,我們可以看出$_key為COOKIR、POST、GET中的參數,如果我們提交?a=3,那麼$key的值就為3,還有一個$在a的前面,結合起來就是$a=addslashes($_value),所以會覆蓋原有a的值。上面的程式碼我們執行一下,如下圖,發現a被覆蓋成由GET方式傳的8。

變數覆蓋防範

變數覆蓋最常見的漏洞點是做變數註冊時沒有驗證變數是否存在。所以想要防範,推薦使用原始的變數陣列,如$_GET、$_POST等,或者在註冊變數前一定要驗證變數是否存在。


IT145.com E-mail:sddin#qq.com