PHP安全程式設計之跨站請求偽造CSRF的防禦

2021-07-16 09:57:34 字數 2597 閱讀 5003

跨站請求偽造(csrf)是一種允許攻擊者通過受害者傳送任意http請求的一類攻擊方法。此處所指的受害者是乙個不知情的同謀,所有的偽造請求都由他發起,而不是攻擊者。這樣,很你就很難確定哪些請求是屬於跨站請求偽造攻擊。事實上,如果沒有對跨站請求偽造攻擊進行特意防範的話,你的應用很有可能是有漏洞的。

請看下面乙個簡單的應用,它允許使用者購買鋼筆或鉛筆。介面上包含下面的表單:

乙個攻擊者會首先使用你的應用以收集一些基本資訊。例如,攻擊者首先訪問表單並發現兩個表單元素item及quantity,他也同時知道了item的值會是鉛筆或是鋼筆。

下面的buy.php程式處理表單的提交資訊:

<?php 

session_start();

$clean = array();

if (isset($_request['item'] && isset($_request['quantity']))

else

} ?>

攻擊者會首先使用這個表單來觀察它的動作。例如,在購買了一支鉛筆後,攻擊者知道了在購買成功後會出現感謝資訊。注意到這一點後,攻擊者會嘗試通過訪問下面的url以用get方式提交資料是否能達到同樣的目的:

如果能成功的話,攻擊者現在就取得了當合法使用者訪問時,可以引發購買的url格式。在這種情況下,進行跨站請求偽造攻擊非常容易,因為攻擊者只要引發受害者訪問該url即可。

雖然有多種發起跨站請求偽造攻擊的方式,但是使用嵌入資源如的方式是最普遍的。為了理解這個攻擊的過程,首先有必要了解瀏覽器請求這些資源的方式。

當你訪問你的瀏覽器首先會請求這個url所標識的資源。你可以通過檢視該頁的原始檔(html)的方式來看到該請求的返回內容。在瀏覽器解析了返回內容後發現了google的標誌。這個是以html的img標籤表示的,該標籤的src屬性表示了的url。瀏覽器於是再發出對該的請求,以上這兩次請求間的不同點只是url的不同。

根據上面的原理,跨站請求偽造攻擊可以通過img標籤來實現。考慮一下如果訪問包括下面的源**的網頁會發生什麼情況:

由於buy.php指令碼使用$_request而不是$_post,這樣每乙個只要是登入在store.example.org商店上的使用者就會通過請求該url購買50支鉛筆。

跨站請求偽造攻擊的存在是不推薦使用$_request的原因之一。

當請求乙個時,某些瀏覽器會改變請求頭部的accept值以給型別以乙個更高的優先權。需要採用保護措施以防止這種情況的發生。

你需要用幾個步驟來減輕跨站請求偽造攻擊的風險。一般的步驟包括使用post方式而不是使用get來提交表單,在處理表單提交時使用$_post而不是$_request,同時需要在重要操作時進行驗證(越是方便,風險越大,你需要求得方便與風險之間的平衡)。

任何需要進行操作的表單都要使用post方式。在rfc 2616(http/1.1傳送協議,譯註)的9.1.1小節中有一段描述:

「特別需要指出的是,習慣上get與head方式不應該用於引發乙個操作,而只是用於獲取資訊。這些方式應該被認為是『安全』的。客戶瀏覽器應以特殊的方式,如post,put或delete方式來使使用者意識到正在請求進行的操作可能是不安全的。」

最重要的一點是你要做到能強制使用你自己的表單進行提交。儘管使用者提交的資料看起來象是你表單的提交結果,但如果使用者並不是在最近呼叫的表單,這就比較可疑了。請看下面對前例應用更改後的**:

<?php 

session_start();

$token = md5(uniqid(rand(), true));

$_session['token'] = $token;

$_session['token_time'] = time();

?>

表單:

通過這些簡單的修改,乙個跨站請求偽造攻擊就必須包括乙個合法的驗證碼以完全模仿表單提交。由於驗證碼的儲存在使用者的session中的,攻擊者必須對每個受害者使用不同的驗證碼。這樣就有效的限制了對乙個使用者的任何攻擊,它要求攻擊者獲取另外乙個使用者的合法驗證碼。使用你自己的驗證碼來偽造另外乙個使用者的請求是無效的。

該驗證碼可以簡單地通過乙個條件表示式來進行檢查:

<?php 

if (isset($_session['token']) && $_post['token'] == $_session['token'])

?>

你還能對驗證碼加上乙個有效時間限制,如5分鐘:

<?php 

$token_age = time() - $_session['token_time'];

if ($token_age <= 300)

?>

通過在你的表單中包括驗證碼,你事實上已經消除了跨站請求偽造攻擊的風險。可以在任何需要執行操作的任何表單中使用這個流程。

儘管我使用img標籤描述了攻擊方法,但跨站請求偽造攻擊只是乙個總稱,它是指所有攻擊者通過偽造他人的http請求進行攻擊的型別。已知的攻擊方法同時包括對get和post的攻擊,所以不要認為只要嚴格地只使用post方式就行了。

跨站請求偽造

跨站請求偽造 英語 cross site request forgery 是一種挾制使用者在當前已登入的web應用程式上執行非本意的操作的攻擊方法。跟跨 指令碼 xss 相比,xss利用的是使用者對指定 的信任,csrf 利用的是 對使用者網頁瀏覽器的信任。防止方法 1,利用referer判斷,但是...

跨站請求偽造 安全方面

一級類 跨站指令碼 二級類 跨站請求偽造 數量 126 詳細資訊 跨站請求偽造 csrf 是偽造客戶端請求的一種攻擊。應用程式允許使用者提交不包含任何保密資訊的請求,將可能導致csrf攻擊。例如 以下 片段用於銀行轉賬功能,對於該重要敏感的操作沒有進行相應防護,將易於導致跨站請求偽造攻擊。修復建議 ...

web安全 跨站請求偽造(CSRF)

0x00 簡介 csrf攻擊滿足的 必要 條件 使用者 c 登入受信任 a,並在本地生成 cookie 在不登出 a 的情況下,訪問危險 b 0x01 csrf舉例 用虛擬的銀行轉賬操作的例子演示csrf的攻擊過程 使用者 c 先登入銀行 a a 會在瀏覽器本地生成cookie 使用者 c 不關閉 ...