node-open 是一個 npm 包,可以使用系統預設關聯的方式開啟 uri 和本地檔案。從 commit 日誌和 npm 釋出時間來看,node-open 包似乎已經停止維護好幾年了:
- https://www.npmjs.com/package/open
- https://github.com/pwnall/node-open
另外作者的使用者名稱 pwnall 讓我一度誤認為是 pwnallthethings 的馬甲,居然還是位 Chrome 的開發成員。
這個包的原始碼非常短,問題很明顯: https://github.com/pwnall/node-open/blob/master/lib/open.js#L58
var exec = require('child_process').exec
...
return exec(opener + ' "' + escape(target) + '"', callback);
...
function escape(s) {
return s.replace(/"/g, '\\\"');
}
複製程式碼
雖然用了所謂的 escape
函式把雙引號閉合了回去,但是這畢竟是 child_process.exec
,是支援 shell 語法的。例如在 mac 系統下即可在 url 中使用 反引號、\$()
、\${}
等特殊字元執行命令、獲取環境變數。真是一股濃濃的 Damn Vulnerable Web Application 風味,還是入門級的難度。使用 node-open 開啟外部不受信任的 url 等同於 php 裡直接拼接 system 的引數。
那麼他在真實環境中的影響有多大呢?
這是 2018 年 2 月 27 日的統計資料:
Stats
- 28,381 downloads in the last day
- 476,031 downloads in the last week
- 1,925,595 downloads in the last month
雖然下載量和依賴量很大,但並不能說明這就是一個影響範圍很大的安全問題——child_process 這個模組每一個 node 發行包都有,就直接搞個大新聞說 Node.js 不能用?
使用系統關聯工具開啟 url 的場景多適用於桌面應用,因此不大可能會使用這個模組。但有一些桌面工作流可能會出現使用 RPC 介面的情況。
Macaw 是一款所見即所得網頁編輯器,支援在瀏覽器中實時預覽(livereload):http://macaw.co/
在 Macaw.app/Contents/www/thirdparty/preview/index.js 中開啟了兩個伺服器:
// defaul ports for server and LR
var defaults = { livereload: 15729, port: 5353 };
複製程式碼
一個是 livereload 的 WebSocket,另一個是 JSON RPC 的服務。有一個支援傳入引數拼接後開啟瀏覽器的介面:
//open default browser
app.get('/openbrowser/:path/:file', function(req, res) {
var file = req.param('file');
var path = req.param('path');
var callback = function() {
open('http://localhost:'+app.get('port')+'/'+file);
};
setWatch(path, callback);
// return 200 OK
res.send(200);
});
複製程式碼
這裡的 file 引數由外部 HTTP 請求傳入,直接拼接到了 url 中。簡單地使用 shell 指令碼即可被執行:
import requests
requests.get('http://192.168.1.100:5353/openbrowser/aaa/`echo 1>${PWD}tmp${PWD}1`')
複製程式碼
安裝了這個編輯器的前端開發者萬萬沒想到,這個軟體居然就這樣成了一個赤裸裸的後門。
Macaw 對此問題的答覆是,由於這款軟體已經被 InVision 收購,1.6 將成為最終版本,不再修復 bug。
鑑於 node-open 這個顯而易見的問題和停止維護的狀態,請考慮使用替代方案。例如 opn:https://www.npmjs.com/package/opn