JSONP存在的JSON Hijacking漏洞以及與csrf/xss漏洞的關係

s1mba發表於2015-01-28

在實習過程中接觸過所謂的JSON Hijacking 漏洞,但最近在寫論文時發現理解得不深,好像跟xss與csrf又有點區別與聯絡,索

性深入學習了下JSONP(JSON with Padding)


下面一段話擷取自:http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about   仔細看看就比較清晰了。

Say you're on domain abc.com, and you want to make a request to domain xyz.com. To do so, you need to cross domain boundaries, a no-no in most of browserland.

The one item that bypasses this limitation is <script> tags. When you use a script tag, the domain limitation is ignored, but under normal circumstances, you can't really DO anything with the results, the script just gets evaluated.

Enter JSONP. When you make your request to a server that is JSONP enabled, you pass a special parameter that tells the server a little bit about your page. That way, the server is able to nicely wrap up its response in a way that your page can handle.

For example, say the server expects a parameter called "callback" to enable its JSONP capabilities. Then your request would look like:

http://www.xyz.com/sample.aspx?callback=mycallback

Without JSONP, this might return some basic JavaScript object, like so:

{ foo: 'bar' }

However, with JSONP, when the server receives the "callback" parameter, it wraps up the result a little differently, returning something like this:

mycallback({ foo: 'bar' });

As you can see, it will now invoke the method you specified. So, in your page, you define the callback function:

mycallback = function(data){
  alert(data.foo);
};

And now, when the script is loaded, it'll be evaluated, and your function will be executed. Voila, cross-domain requests!


大概解釋一下。舉例:在abc.com 有這麼一段 <script src="http://www.xyz.com/sample.aspx?callback=mycallback"></script>

在 xyz.com 的 sample.aspx 可能是如下實現的:


 PHP Code 
1
2
3
4
5
6
<?php
header('Content-Type:text/html;charset=utf-8');
$callback = $_GET['callback'];
$data     = "{foo: 'bar'}";
echo $callback . "(" . $data . ");";
?>

src 標籤請求返回即 <script> mycallback({foo: 'bar'});</script> 也就是會執行函式mycallback,這裡需要明確的是mycallback 肯定是在

abc.com 上實現的,把 {foo: 'bar' } 作為引數傳遞,以便下一步操作。callback只是個key,也可以寫成jsonp,當然server獲取的key也得變換。


講到這裡,對於正常的請求,jsonp並沒有什麼安全問題。但是,對於一些在登陸態會暴露敏感資訊如使用者id和暱稱的cgi來說,我們直接用瀏覽器訪問

http://www.a.com/json.php?mod=pay&func=openvip&callback=loginInfoCallback   雖然我們並沒有實現loginInfoCallback ,但如上所述,server端會返

回 loginInfoCallback({"ret":-1102321,"data":{"_id":1032412,"_nick":"jnusimba"}});  當然這是在 jnusimba 在瀏覽器的另一個tab已經登入過 a.com 的情

形下。所以攻擊的手法是 在第三方站點通過<script src=http://www.a.com/json.php?mod=pay&func=openvip&callback=loginInfoCallback></script>

的形式就可以在函式loginInfoCallback 引數裡面取得當前使用者的id號和暱稱。


上述講到的JSON Hijacking 漏洞可以認為是 csrf漏洞的一種,也就是 csrf 寫-讀 。基本原理還是因為瀏覽器的會話機制在第三方站點請求 a.com 時

也會把a.com 相關的cookie 傳送出去。防禦來說,校驗refer/ 請求帶上form token 都是比較好的辦法,也就是帶有第三方無法預測的值。

注意:jsonp 只支援 get 請求。


對於上面server端的php程式碼來說,返回 {foo: 'bar'}  沒有帶有登陸態資訊,故沒有什麼實質的風險。但不知道有人注意到沒有,它返回的頭部

Content-Type:text/html; 即型別設定錯誤了,應該是content-type:text/javascript;  (or application/javascript) 設定成html格式,容易造成xss攻擊,比

callback=<script>alert('aaa')</script>,即瀏覽器會彈框(注意,在高版本的ie和chrome下面可能已經限制了xss攻擊,測試在firefox下檢視即可)。

(注:The MIME media type for JSON text is application/json. The default encoding is UTF-8. For JSONP with callback :application/javascript )

對於此類由jsonp引起的反射xss漏洞,一來響應頭應該設定正確;二來應該對callback引數進行過濾或者編碼,避免可以直接執行js。


關於 csrf 的防禦:

1. 檢查 http referer 是否是同域

如果網站有客戶端,需要對此開綠燈,可能是個隱患。

注意:ajax 跨域發起請求時是不可以新增 cookie、user-agent、referer、 x_forward_for 等http 頭的,可以看下w3c給出的一份頭部黑名單。

否則 referer 校驗就無效了。

此外在某些情況下,瀏覽器也不會傳送referer,比如從https 跳轉到 http;flash 的請求等。


2. 限制 cookie 的生命週期(減少發生概率)


3. 使用一次性 token

token 是一段隨機的數字字母值,經常出現在表單的隱藏項中,原理是 無法通過 ajax 獲取到外域頁面的 token 值(雖然可以通過 html 標籤帶動 ajax 跨域請求,如 <img src='http://...'  onload="load_ajax_func()">,但無法通過 javascript 讀取返回的內容)。


4. 使用驗證碼(降低使用者體驗)

當同域頁面上有xss 漏洞時,可以通過 ajax 獲取到其他頁面的 token;

token 如果出現在 get 引數中,也容易通過 refer的方式洩露;

此時只能通過驗證碼來防範csrf 了。


參考連結:

http://en.wikipedia.org/wiki/JSONP

http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about


相關文章