天天看點

NodeJS反序列化RCE漏洞的完美利用

本文講的是<b>NodeJS反序列化RCE漏洞的完美利用</b>,幾天前,我在opsecx部落格上注意到一篇博文,是談論有關于利用nodejs的node-serialize子產品中的RCE(遠端執行代碼)漏洞的文章。 文章很清楚地解釋了存在安全問題的子產品的詳細資訊,但有一件事情讓我覺得不太妥當,使用Burp進行這個漏洞的利用,其過程比較複雜。 我沒有攻擊Burp不好用,相反,這是個極好的黑客工具 – 但我認為在這個漏洞的利用上我們可以做得更好。

在這篇文章中,我想說明一下我對這個特定的RCE漏洞的看法,也會分享一些額外的見解,這些可能對以後是有幫助的 ,也可能有助于你自己的研究。

攻擊面

在我們開始之前,先來評估這個漏洞的攻擊面是有用的。 node-serialize子產品的使用程度還算不錯。 在寫本文時,每月大約有2000次的下載下傳,并且有9個依賴中是沒有子依賴關系的。

NodeJS反序列化RCE漏洞的完美利用

下面是所有依賴子產品的清單:cdlib,cdlibjs,intelligence,malice,mizukiri,modelproxy-engine-mockjs,node-help,sa-sdk-node,scriby,sdk-sa-node,shelldoc,shoots。 我沒有分析代碼,也沒有辦法來識别這些依賴的實作中是否也是有漏洞的,但是由于這個RCE漏洞的性質我将假設這些依賴是有漏洞的。

盡管,更重要的是,我們還沒有很好的回答一個問題——這個子產品的使用實際上有多麼廣泛。不過,每月2000次的下載下傳可能意味着許多事情,同時,也很難估計這個數字後面的應用程式的數量。 快速浏覽github和google是獲得關于這個問題的一些答案的唯一方法,并且這就是這個問題開始變得有趣的地方。

通過GitHub搜尋顯示了有97個潛在的易受攻擊的公共子產品和應用程式,這些子產品或應用程式最可能被個人使用,因為這些項目并沒有與npmjs.com謀求建立關系。 通過浏覽項目代碼,讓我明白了這個漏洞的影響範圍有多麼廣泛(或者沒有)。 我很驚訝地發現,這個漏洞竟然與Pokémon有關。 繼續去搞清楚!

在這裡我要支援一下https://nodesecurity.io,因為它是現在這種情況下發現NodeJS安全問題的唯一方法,特别是與NodeJS子產品系統有關系的安全問題。 它對開源項目是免費的。

測試環境

到目前為止,我們認為我們正在處理的這個漏洞是一個濫用潛力有限的漏洞,這從公共安全角度來看是有好處的。 讓我們走近更加“學術”的一面,并利用這個漏洞。 為了測試漏洞,我們需要一個易被這個漏洞攻擊的應用程式。 Opsecx的博文中提供了一個Demo是以我們使用它進行練習吧。 代碼相當簡單。

你需要以下package.json檔案來完成工作(npm install)。

讓我們跳過一些事情。 直接看代碼吧,從代碼中我們可以看到,此示例Web應用程式使用使用者資訊去設定了cookie,并且使用者資訊是使用有漏洞的node子產品的進行了序列化對象。 且使用的是base64編碼。我們可以使用ENcoder進行Base64解碼來看看到底對那些資訊做了序列化。

NodeJS反序列化RCE漏洞的完美利用

這看起來像一個标準的JSON。 同時,看起來也可以進行欺騙,這個問題我們将在後面讨論。 首先,讓我們打開Rest測試工具,以便可以對它進行請求測試。 請注意,我們使用Cookie建構器來擷取正确的編碼,并使用Encode小工具将JSON字元串轉換為Base64編碼的格式。

NodeJS反序列化RCE漏洞的完美利用

EXP

現在我們有了一個可以正常工作的HTTP請求,我們需要将它轉換為漏洞的Exp。 不過,首先要做的是了解node-serialize中的漏洞是如何産生的。 看看源代碼,很明顯,子產品中的序列化函數如下所示。

檢視完整代碼:

一旦我們調用unserialize方法,這個問題就會顯現出來。 确切的代碼行如下:

這意味着如果我們建立一個JSON對象,并且這個對象包含以_ $$ND_FUNC$$_開頭的任意參數的值,我們将可以遠端執行代碼,因為代碼中執行了eval函數。 要測試這個想法,我們可以使用以下設定。

NodeJS反序列化RCE漏洞的完美利用

如果請求成功,應該就會成功執行代碼,之後你将會收到一個錯誤,因為伺服器将在請求完成之前退出,因為我們執行了process.exit()。 現在我們有了遠端代碼執行漏洞了,但我們可以做得更好。

攻擊支點

我發現在opsecx部落格文章中提出的利用技術有點粗魯。 這對于示範目的是完全正确的,但考慮到我們已經在node程序中實作了調用eval函數,我們可以做許多事情,并且以更優雅的姿勢hack,而不需要涉及python和其他的階段攻擊。 因為我們要寫幾大段的代碼塊,可能也會修改我們的exploit,使它更容易使用。 為此,我們将使用Rest工具的變量功能。 進入變量頁籤,并設定一個名為“code”的新變量。

NodeJS反序列化RCE漏洞的完美利用

這個變量用于存儲我們的攻擊代碼,使我們不必擔心編碼問題。 現在我們要做的是修改配置檔案的cookie,以便“code”變量以正确德編碼方式嵌入在JSON和node-serialize的特殊函數中。

NodeJS反序列化RCE漏洞的完美利用

這很完美!現在每次我們更改code變量時,配置檔案的cookie中的payload将會動态更改,通過之前設定的編碼和node-serialize 魔法來使其完美的執行完成。

後門

我們需要處理我們的payload代碼。假設我們不知道應用程式是如何工作的,那我們需要一個通用的方法來利用它,或者對于任何其他的應用程式,既沒有順手的環境也沒有一些預先的知識了解情況。這意味着我們不能依賴可能存在或可能不存在的全局範圍的變量。我們不能依賴express的應用程式導出,是以它可以通過通路額外的路由進行安裝。我們不想生成新的端口或反向shell,以保持最小的配置檔案等。

這樣的要求有點高,但在做了一些研究後,很容易找到一種方法,并可以很好的工作。

我們的旅程将從http子產品引用ServerResponse函數開始。 ServerResponse的prototype被用于expressjs中的響應對象的__proto__。

這意味着如果我們更改了ServerResponse的原型也就改變了響應的__proto__。 響應對象的send方法調用了ServerResponse原型。

這意味着一旦send方法被調用,也将會調用end方法,這恰好來自ServerResponse的原型。 由于send方法被充分地用于任何與expressjs相關的事情,這也意味着我們現在有一個直接的方法來快速通路一些更有趣的結構,如目前打開的套接字對象。 如果我們重寫原型的end方法,就意味着我們可以從this對象的引用獲得一個對socket對象的引用。

實作這種效果的代碼看起來如下:

由于我們覆寫了end的原型,我們還需要以某種方式區分我們的後門啟動請求和任何其他正常請求,因為這可能會導緻一些意想不到的行為。 我們将檢查請求參數中的特殊字元串(abc123),告訴我們這是我們自己的惡意請求。 可以從socket對象通路httpMessage對象來檢索此資訊:

現在我們有了一切。 剩下的就是啟動shell。 在nodeJs中這相對簡單一些:

合并上面兩個代碼段之後,最終的代碼如下所示。 注意我們是如何通過重用已經建立的套接字來轉向到end函數并在Node程序中建立一個shell的。

現在打開netcat連接配接到localhost 3000并鍵入以下請求

NodeJS反序列化RCE漏洞的完美利用

然而這看起來并沒有按照我們的預期執行指令,不過,你看,我們正在劫持一個現有的套接字。 經過一番檢查和思考,最終的代碼看起來像這樣。

到這裡基本上就結束了。 現在,我們就可以用你所喜歡的任何方式利用這個漏洞了。 使用帶有我們的特殊字元串的參數進行請求就可以利用相同的伺服器程序和建立的套接字來獲得一個遠端shell。

NodeJS反序列化RCE漏洞的完美利用

結論

我們從一個簡單的RCE漏洞開始,最終建立了一個通用的利用已經建立的HTTP通道來生成一個shell的方法,它應該在許多類型的情況下獨立工作。 整個利用過程中最好的部分是在Rest的幫助下進行了簡單的利用過程的分析。

原文釋出時間為:2017年3月3日

本文作者:絲綢之路

本文來自雲栖社群合作夥伴嘶吼,了解相關資訊可以關注嘶吼網站。

<a href="http://www.4hou.com/technology/3457.html" target="_blank">原文連結</a>

繼續閱讀