請立即停止使用 node-open 模組

codecolorist發表於2018-02-27

node-open 是一個 npm 包,可以使用系統預設關聯的方式開啟 uri 和本地檔案。從 commit 日誌和 npm 釋出時間來看,node-open 包似乎已經停止維護好幾年了:

  • https://www.npmjs.com/package/open
  • https://github.com/pwnall/node-open

另外作者的使用者名稱 pwnall 讓我一度誤認為是 pwnallthethings 的馬甲,居然還是位 Chrome 的開發成員。

pwnall

這個包的原始碼非常短,問題很明顯: 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

Dependents (1652)

雖然下載量和依賴量很大,但並不能說明這就是一個影響範圍很大的安全問題——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

相關文章