阿赫亞web安全JSON
前言
JSON(JavaScript Object Notation),可以說,這一事實,瀏覽器,server資料交換標準。的格式如XML,或者其他自己定義的格式會越來越少。
為什麼JSON這麼流行?
和JavaScript無縫對接是一個原因。
另一個重要原因是能夠比較輕鬆的實現跨域。假設是XML。或者其他專有格式,則非常難實現跨域。要通過flash之類來實現。
不論什麼一種資料格式,怎樣解析處理不當。都會存在安全漏洞。
以下扯談下JSON相關的一些安全東東。
在介紹之前,先來提幾個問題:
- 為什麼XMLHttpRequest要遵守同源策略?
- XMLHttpRequest 請求會不會帶cookie?
- <script scr=”…”> 的標籤請求會不會帶cookie?
- 向一個其他域名的站點提交一個form,會不會帶cookie?
- CORS請求能不能帶cookie?
JSON注入
有的時候,可能是為了方便。有人會手動拼接下JSON,可是這樣的隨手程式碼,卻可能帶來意想不到的安全隱患。
第一種方式。利用字串拼接:
String user = "test01"; String password = "12345`, admin:`true"; String json = "{user:`%s`, password:`%s`}"; System.out.println(String.format(json, user, password)); //{user:`test01`, password:`12345`, admin:`true`}
使用者新增了管理員許可權。
另外一種,利用Parameter pollution, 類似http parameter pollution
String string = "{user:`test01`,password:`hello`, password:`world`}"; JSONObject parse = JSON.parseObject(string); String password = parse.getString("password"); System.out.println(password); //world
當JSON資料key反覆了會怎麼處理?大部分JSON解析庫都是後面的引數覆蓋了前面的。
以下的演示了改動別人password的樣例:
//user%3Dtest01%26password%3D12345%27%2Cuser%3Dtest02" //user=test01&password=12345`,user=test02 HttpServletRequest request = null; String user = request.getParameter("user"); //檢查test01是否登陸 String password = request.getParameter("password"); String content = "{user:`" + user + "`, password:`" + password + "`}"; User user = JSON.parseObject(content, User.class); //{"password":"12345","user":"test02"} updateDb(user);
所以說。不要手動拼接JSON字串
瀏覽器端應該怎樣處理JSON資料?
像eval這樣的方式,自然是不能採用的。
如今的瀏覽器都提供了原生的方法 JSON.parse(str) 來轉換為JS物件。
假設是IE8之前的瀏覽器,要使用這個庫來解析:https://github.com/douglascrockford/JSON-js
參考:http://zh.wikipedia.org/wiki/JSON#.E5.AE.89.E5.85.A8.E6.80.A7.E5.95.8F.E9.A1.8C
JQuery裡內建了JSON解析庫
JSONP callback注入
簡介jsonp的工作原理。
jsonp工作原理:
用js在document上插入一個<script>標籤。標籤的src指向遠端server的API地址。client和server約定一個回撥函式的名字,然後server返回回撥函式包裹著的資料,然後瀏覽器執行回撥函式,取得資料。
比方jquery是這樣子實現的:
var url = `http://localhost:8080/testJsonp?callback=?
`;
$.getJSON(url, function(data){
alert(data)
});
jquery自己主動把?
轉成了一個帶時間戳特別的函式(防止快取):
http://localhost:8080/testJsonp?
callback=jQuery1102045087050669826567_1386230674292&_=1386230674293
相當於插入了這麼一個<script>標籤:
<script src="http://localhost:8080/testJsonp?callback=jQuery1102045087050669826567_1386230674292&_=1386230674293"></script>
server返回的資料是這樣子的:
jQuery1102045087050669826567_1386230674292({`name`:`abc`, `age`:18})
瀏覽器會執行直接執行這個JS函式。
所以。假設在callback函式的名字上做點手腳,能夠執行隨意的JS程式碼。所以說callback名字一定要嚴格過濾。
當然。callback函式的名字一般是程式自己控制的,可是不能排除有其他被利用的可能。
那麼callback函式的名字。怎樣過濾?應當僅僅同意合法的JS函式命名。用正則來匹配應該是這樣子的:
^[0-9a-zA-Z_.]+$
正則可能比較慢。能夠寫一個函式來推斷:
static boolean checkJSONPCallbackName(String name) { try { for (byte c : name.getBytes("US-ASCII")) { if ((c >= `0` && c <= `9`) || (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_`) { continue; } else { return false; } } return true; } catch (Throwable t) { return false; } }
實際上對callback函式名字進行嚴格檢驗還有其他的一個優點,就是防範了非常多UTF-7編碼攻擊。
由於UTF-7編碼的頭部都是帶有特殊字元的,如”+/v8″,”+/v9″,這樣就過濾掉非法編碼的請求了。
jsonp的請求的驗證
jsonp在使用的時候,還有easy犯的錯誤是沒有驗證使用者的身份。
第一。操作是否是使用者自己提交的,而不是別的網頁用<script>標籤,或者用<form>提交的
所以要檢查request的refer,或者驗證token。這個實際是CSRF防護的範疇。可是非常easy被忽略。
第二,要驗證使用者的許可權。
非常多時候。可能僅僅是驗證了使用者是否登入 。卻沒有細緻推斷使用者是否有許可權。
比方通過JSONP請求改動了別的使用者的資料。
所以說,一定要難證來源。推斷refer。驗證使用者的身份。
到烏雲上搜尋。能夠找到不少類似的漏洞,都是由於沒有嚴格驗證使用者的許可權。http://www.wooyun.org/searchbug.php?q=jsonp
JSON hijacking
在JS裡能夠為物件定義一些setter函式。這種話就存在了能夠利用的漏洞。
比方在瀏覽器的JS Console裡執行:
window.__defineSetter__(`x`, function() { alert(`x is being assigned!`); }); window.x=1;
會非常奇妙地彈出一個alert窗體,說明我們定義的setter函式起作用了。
結合這個,當利用<script>標籤請求外部的一個JSON API時,假設返回的是陣列型,就能夠利用竊取資料。
比方有這種一個API:
http://www.test.com/friends
返回的資料是JSON Array:
[{`user`:`test01`,`age`:18},{`user`:`test02,`age`:19},{`user`:`test03`,`age`:20}]
在攻擊頁面上插入下面的程式碼,就能夠獲取到使用者的全部的朋友的資訊。
<script> Object.prototype.__defineSetter__(`user`,function(obj) {alert(obj); } ); </script> <script src="http://www.test.com/friends"></script>
這個漏洞在前幾年非常流行,比方qq郵箱的一個漏洞:http://www.wooyun.org/bugs/wooyun-2010-046
如今的瀏覽器都已經修復了,能夠下載一個Firefox3.0版本號來測試下。眼下的瀏覽器在解析JSON Array字串的時候。不再去觸發setter函式了。
但對於object.xxx 這種設定。還是會觸發。
IE的utf-7編碼解析問題
這個漏洞也以前非常流行。
利用的是老版的IE能夠解析utf-7編碼的字串或者檔案,繞過server的過濾。舉個烏雲上的樣例:http://www.wooyun.org/bugs/wooyun-2011-01293
有這種一個jsonp呼叫介面:
http://jipiao.taobao.com/hotel/remote/livesearch.do?callback=%2B%2Fv8%20%2BADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAYwByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADsAPAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHkAPgA8AC8AaAB0AG0APg
url decoder之後是:
http://jipiao.taobao.com/hotel/remote/livesearch.do?callback=+/v8 +ADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAYwByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADsAPAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHkAPgA8AC8AaAB0AG0APg
由於jsonp呼叫是直接返回callback包裝的資料。所以實際上。上面的請求直接返回的是:
+/v8 +ADwAaAB0AG0APgA8AGIAbwBkAHkAPgA8AHMAYwByAGkAcAB0AD4AYQBsAGUAcgB0ACgAMQApADsAPAAvAHMAYwByAGkAcAB0AD4APAAvAGIAbwBkAHkAPgA8AC8AaAB0AG0APg-(呼叫結果資料)
IE做了UTF-7解碼之後資料是這樣子的:
<htm><body><script>alert(1);</script></body></htm>(呼叫結果資料)
於是。就執行了XSS。
另外用IFrame也是能夠的。
可是我在IE8上測試,url的字尾須要是html才會觸發。
IE把沒有宣告返回Content-Type的請求當做了”text/html”型別的。然後解析就有問題了。僅僅要server端顯式設定了Content-Type為”application/json”,則IE不會識別編碼,就不會觸發漏洞。所以說server端的Content-Type一定要設定對。雖然設定之後除錯有點麻煩。可是卻大大提高了安全性。
JSON格式設定為:”application/json”
JavaScript設定為:”application/x-javascript”
JavaScript另一些設定為:”text/javascript”等,都是不規範的。
其他的一些東東
MongoDB注入
這個實際上就是JSON注入,簡單的字串拼接。可能會引發各種資料被改動的問題。
JSON解析庫的問題
有些JSON庫解析庫支援迴圈引用,那麼能否夠構造特別的資料,導致其解析失敗?從而引起CPU使用過高,拒絕服務等問題?
FastJSON的一個StackOverflowError Bug:
https://github.com/alibaba/fastjson/issues/76
有些JSON庫解析有問題:
http://www.freebuf.com/articles/web/10672.html
JSON-P
有人提出一個JSON-P的規範,可是貌似眼下都沒有瀏覽器有支援這個的。
原理是對於JSONP請求。瀏覽器能夠要求server返回的MIME是”application/json-p”,這樣能夠嚴格校驗是否合法的JSON資料。
CORS(Cross-Origin Resource Sharing)
為了解決跨域呼叫的安全性問題。眼下實際上可用的方案是CORS:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
http://www.w3.org/TR/cors/
原理是通過server端設定同意跨域呼叫,然後瀏覽器就同意XMLHttpRequest跨域呼叫了。
CORS能夠發起GET/POST請求。不像JSONP。僅僅能發起GET請求。
預設情況下,CORS請求是不帶cookie的。
我個人覺得,這個方法也非常蛋疼。一是須要server配置。二是協議複雜。瀏覽器假設不能確定是否可以跨域呼叫。還要先進行一個Preflight Request。。
實際上,即使server不同意CORS,XMLHttpRequest請求實際上是傳送出去,而且返回資料的了。僅僅是瀏覽器沒有讓JS環境拿到而已。
另外。我覺得有第二種資料洩露的可能:黑客可能控制了某個路由,他不能任意抓包,可是他能夠在回應頭裡插入一些特別的頭部。比方:
Access-Control-Allow-Credentials: true
那麼。這時XMLHttpRequest請求就是帶cookie的了。
最初的問題
回到最初的問題:
- 為什麼XMLHttpRequest要遵守同源策略?
- XMLHttpRequest 請求會不會帶cookie?
- <script scr=”…”> 的標籤請求會不會帶cookie?
- 向一個其他域名的站點提交一個form,會不會帶cookie?
總結:
- 禁止手動拼接JSON字串。一律應當用JSON庫輸出。也不應使用自己實現的ObjectToJson等方法,由於可能有各種沒有考慮到的地方。
- jsonp請求的callback要嚴格過濾,僅僅同意”_”,0到9。a-z, A-Z,即合法的javascript函式的命名。
- jsonp請求也要推斷合法性,比方使用者是否登陸(這點非常easy被忽略)。
- 設定好Content-Type(這點對於除錯不方便。可是提高了安全性)。
- 以jsonp方式呼叫第三方的介面。實際相當於引入了第三方的JS程式碼,要謹慎。
相關文章
- JSON Web Token - 在Web應用間安全地傳遞資訊(zhuan)JSONWeb
- Json web tokenJSONWeb
- JWT(Json WEB Token)JWTJSONWeb
- 理解JSON Web TokenJSONWeb
- JSON Web Token 的理解JSONWeb
- 理解JSON Web Token (一)JSONWeb
- web安全Web
- Rails與web安全[Web安全大家談]薦AIWeb
- 深入淺出 JSON Web TokenJSONWeb
- JSON Web Token 使用詳解JSONWeb
- JSON Web Token(JWT) 簡介JSONWebJWT
- JSON Web Token 入門教程JSONWeb
- web安全類Web
- Web安全概述Web
- web安全—TokenWeb
- PHP web 安全PHPWeb
- Node.js JSON Web Token 使用Node.jsJSONWeb
- JSON Web Token in ASP.NET Web API 2 using OwinJSONWebASP.NETAPI
- 談談 Web 安全Web
- 淺談 Web 安全Web
- Web安全測試Web
- WEB安全知多少Web
- Web安全-XSSWeb
- Web安全基礎Web
- web安全系列Web
- Web安全實戰Web
- web安全淺析Web
- Web框架自身安全Web框架
- web安全面經Web
- JSON WEB TOKEN 從原理到實戰JSONWeb
- 亞信安全中標南方電網把守企業郵件安全大門
- “網際網路+教育”時代亞信安全助力江漢大學“安全”雲化
- 什麼是web安全?web安全主要分為幾個部分?Web
- 樹(4)--赫夫曼樹及其應用
- 亞信安慧AntDB:為資料安全和穩定而生
- web安全入門課程推薦--Web 安全恩仇錄:漏洞原理Web
- 什麼是Web安全?Web安全主要分為哪幾個方面?Web
- json web token for Egg.js 實踐JSONWeb