首頁 >運維 >安全 >javascript原型鏈污染攻擊

javascript原型鏈污染攻擊

王林
王林轉載
2019-12-27 17:41:583389瀏覽

javascript原型鏈污染攻擊

在講這個漏洞之前我們先來理解Javascript。與其他的語言不同的是,Js在Es6之前是沒有class的,他更多的是一個原型語言,在Js裡有一句話很有名——「一切皆對象」。

什麼是原型語言

1.只有對象,沒有類別;物件繼承對象,而不是類別繼承類別。

2.「原型物件」是核心概念。原型物件是新物件的模板,它將自身的屬性共享給新物件。一個物件不但可以享有自己創建時和運行時定義的屬性,而且可以享有原型物件的屬性。

3.每一個對像都有自己的原型對象,所有對象構成一個樹狀的層級系統。 root節點的頂層對像是語言原生的對象,只有它沒有原型對象,其他所有對像都直接或間接繼承它的屬性。

關於Function.prototype與Object.__proto__

#1.物件有__proto__屬性,函數有prototype屬性;

2.物件由函數產生;

3.產生物件時,物件的__proto__屬性指向函數的prototype屬性。

在沒有手動修改__proto__屬性的指向時,以上三條便是JavaScript預設原型鏈指向邏輯。如果要更形象的去理解這個就可以看下圖的這個結構:

javascript原型鏈污染攻擊

#什麼是JavaScript原型鏈污染

原型鏈污染來自一個CVE(https://github.com/jquery/jquery/pull/4333),這個CVE是一個在jquery中修復的漏洞,但是這個漏洞廣義的推廣的話,受影響的範圍應該是一切都使用了ecmascript的應用,無論前後端。關於這個漏洞,是修正了jQuery的

$.extend(true…)

方法,在jQuery中,這個方法用於將一個或多個物件的內容合併到目標物件。所以你永遠不知道有不有人會不會寫出一些類似以下的程式碼

當我們可控$.extend的參數的時候,我們就可以覆蓋物件的__proto__或prototype方法從而控制整個原型鏈的最頂端的方法,重寫該方法將覆蓋子物件或函數的方法,從而導致污染原本的方法意圖。 在npmjs官方搜下物件操作的函式庫可以看到一大堆,例如「xtend」、 「deepmerge」、 「webpack-merge 」、 「merge2」、 「

lodash.merge

」。假如一些應用使用了這些方法,但是對參數沒做任何處理。

漏洞範圍影響

提出這個Javascript原型鏈污染攻擊的作者寫了一個pdf,在該pdf中,作者不僅做了漏洞的成因分析,還針對此漏洞做了受害範圍分析,他在github上搜尋了部分的組件,這些組件都是可以操作對象,一般都是對象合併操作的,較為底層,因此也會有大量的應用基於這些組件。例如“hoek”,“lodash”,“defaults-deep”等修復了這個原型鏈污染的可能性,當然還有一些組件他沒統計到,例如“xtend”之類的,光weekly download的數量就有「12,097,425」。

筆者在npm上搜尋了基於xtend的一些應用,找到一個language-exec這樣的一個元件。這個元件是一個基於xtend的,不過這個元件好像年久失修而且沒啥人用,看了原始碼其中就有這樣的一句話

#可以看到類似的寫法都是存在問題的(主要是我沒找到具體的基於xtend的受影響應用)。

所以基於這個,大家不是有了刷CVE的想法了?沒錯…只要你敢花時間去爬全部的dependence就可以有機會獲得javascript pollution attack CVE。

案例一遠端指令執行

作者在github上搜到了一個叫做ghost cms的應用程式,當然這個漏洞已經修復,當駭客發送以下請求即可實作控制任意方法或物件的任意屬性。當然也就是rce了

###在一切皆物件的JavaScript中,所有物件都可以呼叫toString和valueOf方法,當你透過__proto__重寫這2個方法的時候,就容易在express等web框架中產生dos,導致服務無法正常運作。類似以下的寫法就容易產生拒絕服務。 ###

javascript原型鏈污染攻擊

案例二DOS

在所有物件的JavaScript中,所有物件都可以呼叫toString和valueOf方法,當你透過__proto_ _重寫這2個方法的時候,就容易在express等web框架中產生dos,導致服務無法正常運作。類似以下的寫法就容易產生拒絕服務

javascript原型鏈污染攻擊

案例三任意檔案讀取

如果你可以透過污染原型鏈來重寫一些「私有屬性」的話(Javascript沒有私有屬性),可能可以重寫那些在WEB中用來定義渲染模板檔案的屬性值,就有可能產生任意檔案讀取了,如以下這個圖片:

javascript原型鏈污染攻擊

如何防禦

在這裡我們了解下這類攻擊,如何從程式碼上更安全的編寫,更好的防禦這類漏洞。漏洞發現的作者給了2個解決方案,先來看看我是如何防禦的。

如果是我來解決這個問題的話,我會選擇迭代物件的屬性,直到查找到__proto__和prototype這2個屬性名,如果出現就乾掉。但是這個方法還是有缺陷,一個是建立於黑名單,需要列入的屬性太多了,例如Dos的話就要把tostring和valueof等方法列入,而且遇到私有屬性覆蓋的話,怎麼確保參數,接口很多。

原作者提出了3點:

1、使用Object.freeze來凍結對象,幾乎所有的JavaScript物件都是Object的實例。所以凍結Object.prototype即可。具體大家可以去了解下es5就新增的Object.freeze方法,使用了這個方法,那麼駭客就無法對prototype新增或重寫對應原型鏈上的方法,不過這樣可能會導致一些隱性的bug產生,而且可能還不知道是哪裡出錯了。

2、用map資料結構來取代自帶的物件結構。 Es6就有map結構啦,這個map和Object的差別就是map的鍵可以是任意的物件類型,陣列也好,物件也好。

3、使用Object.create(null)(強烈建議), 使用這個方法就可以更好的防禦原型鏈污染攻擊了,因為Object.create(null)使得創建的新物件沒有任何的原型鏈,是null的,不具備任何的繼承關係,當你接受一個客戶端的參數並且打算merge的話,可以使用此方法後去merge,這樣的對像是比較安全的,客戶端沒辦法通過原型鏈來污染攻擊(因為壓根就沒原型鏈通往其他的對象)。我們可以簡單的透過一個實驗來看下。

javascript原型鏈污染攻擊

javascript原型鏈污染攻擊

相關文章教學推薦:web伺服器安全性

#

以上是javascript原型鏈污染攻擊的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:freebuf.com。如有侵權,請聯絡admin@php.cn刪除