csrf漏洞防御方案_变量覆盖漏洞利用及防御方案
一、漏洞簡介
變量覆蓋漏洞是指攻擊者使用自定義的變量去覆蓋源代碼中的變量,從而改變代碼邏輯,實現攻擊目的的一種漏洞。通常來說,單獨的變量覆蓋漏洞很難有利用價值,但是在與其他應用代碼或漏洞結合后,其造成的危害可能是無法估量的。例如購買商品的支付系統若存在變量覆蓋漏洞,就可能存在0元支付下單的情況。
二、漏洞產生的原因
變量覆蓋漏洞大多數由函數使用不當導致,經常引發變量覆蓋漏洞的函數有:
- extract()
- parse_str()
- import_request_variables()
- $$(可變變量)
- register_globals=On (PHP5.4之后正式移除此功能)
三、漏洞挖掘
1. extract()函數使用不當導致的變量覆蓋
extract()函數覆蓋變量需要一定條件,它的官方說明為“從數組中將變量導入到當前的符號表”,即將數組中的鍵值對注冊成函數,使用數組鍵名作為變量名,使用數組鍵值作為變量值。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 時需要。如果附加了前綴后的結果不是合法的變量名,將不會導入到符號表中。
前綴和數組鍵名之間會自動加上一個下劃線。
從以上說明我們可以看到第一個參數是必須的,會不會導致變量覆蓋漏洞由第二個參數決定,該函數有三種情況會覆蓋已有變量,分別如下:
第一種:當第二個參數為EXTR_OVERWRITE 時,它表示如果有沖突,則覆蓋已有的變量。
第二種:當只傳入第一個參數,這時候默認為EXTR_OVERWRITE模式。
第三種:當第二個參數為EXTR_IF_EXISTS 時,它表示僅在當前表中已有同名變量時,覆蓋它們的值,其他的都不注冊新變量。
下面我們用代碼來說明,測試代碼如下:
點擊添加圖片描述(最多60個字)編輯
測試結果如下:
點擊添加圖片描述(最多60個字)編輯
原本變量$a的值為1,經過extract()函數對變量$b處理后,變量$a的值被成功覆蓋為了3.
2. parse_str()函數使用不當導致的覆蓋
parse_str()函數的作用是解析字符串并且注冊陳變量,它在注冊變量之前不會驗證當前變量是否已經存在,所以會直接覆蓋掉已有的變量。parse_str()函數的結構如下:
parse_str(string,array)
參數
描述
string
必需。規定要解析的字符串
array
可選。規定存儲變量的數組的名稱。該參數指示變量將被存儲到數組中。
從以上說明我們可以看到第一個參數是必須的,它代表要解析注冊成變量的字符串,形式為“a=1”,經過parse_str()函數之后會注冊變量$a并且賦值為1。
測試代碼如下:
點擊添加圖片描述(最多60個字)編輯
測試結果如下,變量$a原有的值1被覆蓋成了5.
點擊添加圖片描述(最多60個字)編輯
3. import_request_variables()所導致的變量覆蓋
import_request_variables()函數作用是把GET、POST、COOKIE的參數注冊成變量,該函數只能用在PHP4.1 ~ PHP5.4之間。
import_request_variables()函數的結構如下:
import_request_variables ( string $types , string $prefix )
其中$type代表要注冊的變量,當$type為GPC的時候,則會注冊GET、POST、COOKIE參數為變量。
測試代碼如下:
點擊添加圖片描述(最多60個字)
測試結果如下,變量$a原有的值1被覆蓋成了6.
點擊添加圖片描述(最多60個字)編輯
4. 由$$變量賦值引發的覆蓋
$$是一種可變變量的寫法,它可以使一個普通變量的值作為可變變量的名字,這種類型常常會使用遍歷的方式來釋放變量的代碼,最常見的就是foreach的遍歷,示例代碼如下:
點擊添加圖片描述(最多60個字)編輯
從代碼中我們可以看出$_key為COOKIE、POST、GET中的參數,$key的值為a而還有一個$在a的前面,結合起來則是$a=addslashes($_value);所以這樣會覆蓋已有的變量$a的值。在瀏覽器輸入http://127.0.0.1/test.php?a=666,結果如下,可以看到已經成功把變量$a的值由2覆蓋成了666。
點擊添加圖片描述(最多60個字)編輯
5.全局變量的覆蓋
register_globals的意思就是注冊為全局變量,所以當On的時候,傳遞過來的值會被直接的注冊為全局變量直接使用,而Off的時候,我們需要到特定的數組里去得到它。下面我們來看如下一段代碼:
點擊添加圖片描述(最多60個字)編輯
當register_globals為OFF時,我們無法將未初始化的變量進行注冊,如下圖所示:
點擊添加圖片描述(最多60個字)編輯
當register_global=ON時,可以看到已經成功注冊了一個未初始化的變量,如下圖所示:
點擊添加圖片描述(最多60個字)編輯
還有一種情況,通過$GLOBALS獲取的變量在使用不當時也會導致變量覆蓋,同樣漏洞觸發的前提是register_globals為ON,如下圖所示,已成功通過注入GLOBALS[a]來改變$a的值:
點擊添加圖片描述(最多60個字)編輯
tips:從PHP 4.2.0 版開始配置文件中PHP指令register_globals的默認值從on改為off了,自PHP 5.3.0起廢棄并將自PHP 5.4.0起移除。
四、漏洞防范
變量覆蓋漏洞最常見的漏洞點是在做變量注冊時沒有驗證變量是否存在,以及在賦值給變量的時候,所以一般推薦使用原始的變量數組,如$_GET、$_POST,或者在注冊變量前一定要驗證變量是否存在。
①使用原始變量
建議不注冊變量,直接用原生的$_GET、$_POST等數組變量進行操作,如果考慮程序可讀性等原因,需要注冊個別變量,可以直接在代碼中定義變量,然后再把請求中的值賦值給他們。
②驗證變量存在
如果一定要使用前面幾種方式注冊變量,為了解決變量覆蓋的問題,可以再注冊變量前先判斷變量是否存在。如使用extract( )函數則可以配置第二個參數為EXTR_SKIP。使用php parse_str函數注冊變量前需要先自行通過代碼判斷變量是否存在。最重要的一點,自行申明的變量一定要初始化,不然即使注冊變量代碼在執行流程最前面也能覆蓋掉這些未初始化的變量。
總結
以上是生活随笔為你收集整理的csrf漏洞防御方案_变量覆盖漏洞利用及防御方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lua与python结合_Lua和Pyt
- 下一篇: 怎么开机选择系统 如何在开机时选择系统