作者:niubl@TSRC
1. 漏洞簡介
2017年9月28日,公司掃描器發現某業務存在一例任意文件讀取漏洞,團隊跟進分析后發現這是Node.js和Express共同導致的一個通用漏洞。在我們準備告知官方時,發現Node.js官網于9月29號給出了漏洞公告,對應的CVE編號為CVE-2017-14849。
1.1 關于Node.js
Node.js是一個Javascript運行環境(runtime),發布于2009年5月,由Ryan Dahl開發,實質是對Chrome V8引擎進行了封裝。Node.js對一些特殊用例進行優化,提供替代的API,使得V8在非瀏覽器環境下運行得更好。
1.2 關于Express
Express 是一個簡潔而靈活的 node.js Web應用框架, 提供一系列強大特性幫助你創建各種Web應用。Express 不對 node.js 已有的特性進行二次抽象,我們只是在它之上擴展了Web應用所需的功能。豐富的HTTP工具以及來自Connect框架的中間件隨取隨用,創建強健、友好的API變得快速又簡單。
1.3 漏洞影響
Node.js 8.5.0 + Express 3.19.0-3.21.2
Node.js 8.5.0 + Express 4.11.0-4.15.5
2. 漏洞演示
- 安裝Node.js 8.5.0
- 下載并解壓express-4.15.5.zip
- expresss-4.15.5目錄下執行npm install
- expresss-4.15.5/examples/static-files目錄里執行nodejs index.js
- 使用POC測試(web監聽了5678端口,默認3000)如下圖

3. 漏洞分析
Express依賴Send組件,Send組件0.11.0-0.15.6版本pipe()函數中,如圖:

Send模塊通過normalize('.' + sep + path)標準化路徑path后,并沒有賦值給path,而是僅僅判斷了下是否存在目錄跳轉字符。如果我們能繞過目錄跳轉字符的判斷,就能把目錄跳轉字符帶入545行的join(root, path)函數中,跳轉到我們想要跳轉到的目錄中,這是Send模塊的一個bug,目前已經修復。
再來看Node.js,Node.js 8.5.0對path.js文件中的normalizeStringPosix函數進行了修改,使其能夠對路徑做到如下的標準化:
assert.strictEqual(path.posix.normalize('bar/foo../..'), 'bar');
新的修改帶來了問題,通過單步調試我們發現,可以通過foo../../和目錄跳轉字符一起注入到路徑中,foo../../可以把變量isAboveRoot設置為false(代碼161行),并且在代碼135行把自己刪掉;變量isAboveRoot為false的情況下,可以在foo../../兩邊設置同樣數量的跳轉字符,讓他們同樣在代碼135行把自己刪除,這樣就可以構造出一個帶有跳轉字符,但是通過normalizeStringPosix函數標準化后又會全部自動移除的payload,這個payload配合上面提到的Send模塊bug就能夠成功的返回一個我們想要的物理路徑,最后在Send模塊中讀取并返回文件。normalizeStringPosix函數如下圖:

4. 參考鏈接
- september-2017-path-validation
- path: fix normalize on directories with two dots
- path: fix normalize paths ending with two dots
- perf: improve path validation speed
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/439/
暫無評論