JSON劫持漏洞分析

FLy_鵬程萬里發表於2018-05-17

什麼是JSON劫持

單從字面上就可以理解的出來,JSON是一種輕量級的資料交換格式,而劫持就是對資料進行竊取(或者應該稱為打劫、攔截比較合適。惡意攻擊者通過某些特定的手段,將本應該返回給使用者的JSON資料進行攔截,轉而將資料傳送回給惡意攻擊者,這就是JSON劫持的大概含義。一般來說進行劫持的JSON資料都是包含敏感資訊或者有價值的資料。

造成JSON劫持漏洞的成因

正所謂無風不起浪,無根不長草,要發動一次成功的JSON劫持攻擊必須要有這些先決條件

1、受攻擊的網站URL返回一個JSON物件或者陣列,並且返回的資料有重要的價值,也就是敏感的資料。(PS:JSON Hijacking 裡說只支援陣列,但是物件也是可以進行劫持的,具體在下面的流程中會說明)
2、受攻擊的網站地址支援GET請求的響應(PS:其實POST請求也可以做到JSON劫持,只不過需要對受害人進行誘導提及表單以傳送POST請求。相比GET請求來說十分麻煩
3、受害人的瀏覽器沒有禁用javascript(PS:現在一般也不會禁用js,畢竟目前許多網站都依賴於指令碼所展現的強大功能和絢麗的效果)

4、受害人瀏覽了釣魚/惡意網站,並且受害人在受攻擊的網站中,儲存在COOKIE中的身份驗證資訊尚未清除。(PS:除非受攻擊的站點沒有做任何的身份驗證!一般響應重要資料的JSON服務都是需要做身份驗證的)
5、受攻擊的站點沒有做相關的防禦措施

JSON劫持攻擊的流程和手段

一、進行JSON劫持的第一步就是惡意攻擊者要確定攻擊的網站,一般會挑選大眾常去的網站或者有價值的網站(購票網站、網購網站、論壇等)。由於大部分使用JSON作為資料傳輸的網站往往會使用到AJAX技術,而AJAX作為前端指令碼,存在著透明性和公開性。這樣導致的結果是增加了攻擊層面和入口,為攻擊者新增了更多的選擇和便捷。

所以惡意攻擊者常常瀏覽網站的指令碼來尋找漏洞進行攻擊,一但確定網站存在JSON劫持漏洞,即某個JSON服務或者介面返回有價值的敏感的JSON陣列資料,那麼攻擊者就會針對這個網站進行JSON劫持攻擊。(這裡假設我們要攻擊的站點地址是:http://vulnerable.shiyousan.com/Home/GetJson,PS:該URL假設是一個JSON服務和介面,會返回一個敏感的JSON陣列資料)

伺服器的程式碼如下:

[HttpGet]
   [Authorize]
   public ActionResult GetJson()
   {
       //這裡使用了隱式型別的陣列,C#3.0的新特性
       var result=new[]{new {Id=1,Name="張三"},new {Id=2,Name="李四"}};
       return Json(result, JsonRequestBehavior.AllowGet);
   }

另外可以看到這裡設定了JsonRequestBehavior.AllowGet引數,如果不設定會提示如下錯誤:“此請求已被阻止,因為當用在 GET 請求中時,會將敏感資訊透漏給第三方網站。若要允許 GET 請求,請將 JsonRequestBehavior 設定為 AllowGet。

我們可以看到現在ASP.NET MVC預設是禁止使用GET請求來獲取JSON資料的,微軟預設已經為JSON劫持做了防禦措施。(詳情點選此連結

二、在第一步明確了要攻擊的站點後,惡意攻擊者第二步就是要誘騙受害人點選和進入到釣魚/惡意網站,這點是十分重要的,所以惡意攻擊者常常在網路上通過各種方式誘騙受害人進入到他們精心佈置的陷阱中。

常用的方式有以下幾種:

1、通過郵件群發,傳送大量垃圾/釣魚郵件等待受害者點選郵件中的連結。一般此類郵件的標題和內容往往是十分吸引人的,比如:點選這個連結看美女/點選連結觀看超級有趣的視訊/揭祕某某明星的祕密之類的連結。當然,這裡的只是隨便舉例,真正高明的欺詐師往往在內容上會做一定的處理,讓你神不知鬼不覺的進入到惡意網站中。

2、通過社交軟體和網站傳送連結,隨著各種社交軟體和網站的崛起,在資訊傳播方面也變得更加便捷與迅速。與此同時也給惡意攻擊者提供了更加便捷的釣魚和攻擊方式。

3、還有其他的各種方式,比如論壇發帖啦,前陣子的超級手機病毒蝗蟲(通過簡訊誘騙受害人下載病毒),還有各種即時通訊工具(QQ群或者陌生人的連結不要亂點)等。


三、一旦受害人點選了惡意連結進入到釣魚網站中,那麼接下的第三步就是劫持受害人的資料了。結合我所查閱的資料,在受害人進入到惡意釣魚網站後,惡意網站會進行下面這些流程:

1、首先會向進行攻擊的目標網站傳送一個GET請求(如第一步所說的,假設攻擊的URL是http://vulnerable.shiyousan.com/Home/GetJson,這個URL會返回一些重要的JSON陣列資料),只要在網頁中放置這句程式碼,就會自動朝目標傳送一個HTTP GET請求:

<script src="http://vulnerable.shiyousan.com/Home/GetJson"></scirpt>

如果目標URL地址只支援POST請求,那麼攻擊者可能要費一番功夫,誘導受害人點選提交表單,從而發生一次POST請求。

另外就向上面所說的JSON劫持形成的先決條件那樣,敏感資料的獲取都是需要進行身份驗證的,這也是JSON劫持的另一個特殊點。受害人一進入釣魚網站,就向受攻擊的網站傳送GET請求,而由於GET請求是從受害人的瀏覽器發出的,所以請求傳送的同時也會將受害人在網站中身份驗證資訊的cookie一同傳送給受攻擊的站點,這樣一來就等於是惡意攻擊者偽裝成受害人,偽裝成一個合法的使用者。而受攻擊的網站因為這個合法的身份,就會將敏感的JSON陣列資料響應給釣魚/惡意網站。

PS:這裡額外說明下,一般身份驗證資訊在COOKIE中儲存的只是一個會話ID,而真正的會話是儲存在伺服器上的,但是攻擊者只要獲取到這個會話ID併傳送給網站,就可以匹配到受害者的身份驗證會話,即等於成功的偽裝成受害者,這其實也是一種CSRF(跨站請求偽造)攻擊。

2、惡意網站成功傳送一個帶有身份驗證資訊的GET請求後,成功的獲取到了攻擊站點返回的資料,響應的資料需要是JSON陣列或者JSON物件。一般都是返回JSON陣列,如果返回JSON物件網站需要經過特殊處理,比如返回{"Id":1, "Name":"張三"}這樣的JSON物件,瀏覽器會提示非法標籤錯誤,所以伺服器上需要在返回的JSON上新增小括號:({"Id":1, "Name":"張三"})。

到了這一步是最關鍵的地方,攻擊者接下要做的就是將響應到釣魚網站的資料傳送到自己伺服器的資料庫上,這就是將資料劫持了。因為此攻擊是針對JSON格式的資料,所以也稱為JSON劫持。

那麼攻擊者是如何將資料劫持走的呢?這裡就需要用到JS中的方法覆蓋的特性或者使用JS的特殊方法__defineSetter__(__defineSetter__存在瀏覽器相容問題,所以一般是使用JS的方法覆蓋)。具體的原理可以檢視這篇文章:《Javascript方法的覆蓋和重寫》。攻擊者通過javascript中可以覆蓋掉其他方法的特性,將響應給惡意網站的JSON陣列或者物件進行建構函式的替換。

具體程式碼如下:

   <script type="text/javascript">
        function Array() {
            //這裡假設返回的JSON陣列是:[{ "Id": 1, "Name": "張三" }, { "Id": 2, "Name": "李四" }]
            var jsonData = this;
            var message = '[';
            for (var index in jsonData) {
                message += '{"Id":' + jsonData[index].Id + ',"Name":"' + jsonData[index].Name + '"}';
            }
            message += ']';
            /*
            * 彈出返回的資料,這裡我們只是將劫持到資料彈出,
            * 而惡意攻擊者則會在這裡將劫持到的JSON資料傳送到他們的伺服器中
            */
            alert(message);
        }
    </script>

當JSON資料響應給網站時,瀏覽器立即會呼叫陣列或者物件的建構函式。正是利用這一點,把構造方法替換成惡意程式碼,在構造方法中新增將JSON資料傳送給第三方即攻擊者的程式碼。到了這裡就成功的完成了整個JSON劫持攻擊的流程!!!


如何防禦JSON劫持

防禦要從兩方面著手,一是網站方面必須做好防禦機制,二是使用者也需要提高警惕。

先從網站方面來說,其實JSON劫持是一種變相的CSRF(跨站請求偽造)攻擊,所以使用通常應對CSRF攻擊的常規手段就可以很好的防禦住此類攻擊,通常是使用訪問令牌,token機制就可以較好的防禦住攻擊,在傳送請求的時候必須將token令牌也傳送給JSON服務,這樣基本可以杜絕此類攻擊。

還有敏感和重要資料的請求入口一定要設定身份驗證,而且最好限制只能POST請求,雖然這不能完全的防禦住攻擊(基本上可以杜絕大部分攻擊),但是可以為攻擊者新增難度,ASP.NET MVC中只需要在控制器的Action中宣告[HttpPost]特性就可以了。此外最好能判斷請求的來源,設定請求的黑白名單,這樣能極大的提高安全性。

另外從使用者方法來說,提高網路安全意識也是很重要的。程式中總會存在各種各樣的漏洞,漏洞無處不在,只有還未修復和破解的漏洞,只有還未發現和產生的漏洞。所以我們適當的提供一點安全意識,不隨意點選來路不明的連結,這樣可以減少進入釣魚網站的概率。

除此之外,還要注意保護自己的相關資訊不被非法竊取和利用,畢竟如果黑客不知道我們的任何聯絡方式(包括郵箱,手機號,QQ等即時通訊工具號),那麼就會減少被黑客盯上的概率。

相關文章