StrongLoop 提供的 Express 和 Node.js 訓練課程

這個翻譯StrongLoop / IBM提供.

相對於英文版說明文件,本文件可能已不合時宜。如需最新的更新,請參閱英文版說明文件

正式作業最佳作法:安全

概觀

正式作業」術語是指軟體生命週期中,應用程式或 API 通用於其一般使用者或消費者的階段。相對地,在「開發」階段,您仍在積極撰寫和測試程式碼,且應用程式尚未開放給外部存取。對應的系統環境分別稱為正式作業環境和開發環境。

開發環境和正式作業環境的設定方式通常不同,且其需求差異頗大。適合用於開發中的,在正式作業中不見得合用。舉例來說,在開發環境中,您可能希望詳細記載錯誤以便除錯,而相同的行為在正式作業環境中卻可能成為安全隱憂。在開發中,您不必擔心可調整性、可靠性和效能,但在正式作業中這些顧慮相形重要。

本文討論部署至正式作業之 Express 應用程式的一些安全最佳作法。

請勿使用已淘汰或有漏洞的 Express 版本

Express 2.x 和 3.x 不再維護。不會修正這些版本中的安全與效能問題。請勿使用它們!如果您尚未移至第 4 版,請遵循移轉手冊

另請確定您沒有使用「安全更新」頁面中列出的任何有漏洞的 Express 版本。若有使用,請更新為其中一個穩定版本,最好是最新版本。

使用 TLS

如果您的應用程式會處理或傳輸機密資料,請使用傳輸層安全 (TLS),來保護連線和資料的安全。此技術會在資料從用戶端傳送至伺服器之前,先將資料加密,因此可阻止一些常見(和容易)的駭客攻擊。雖然 Ajax 和 POST 要求不見得明顯可見,且在瀏覽器中似乎是「隱藏的」,其網路資料流量卻容易遭到封包探查中間人攻擊

您可能熟悉 Secure Socket Layer (SSL) 加密。TLS 就是 SSL 後繼的演進。換句話說,如果您之前使用 SSL,請考量升級至 TLS。一般而言,我們建議由 Nginx 來處理 TLS。如需有關在 Nginx(和其他伺服器)上配置 TLS 的適當參考資料,請參閱 Recommended Server Configurations (Mozilla Wiki)

此外,可方便您取得免費 TLS 憑證的工具是 Let’s Encrypt,這是一個免費的自動化開放憑證管理中心 (CA),由 Internet Security Research Group (ISRG) 提供。

使用 Helmet

Helmet 會適當設定 HTTP 標頭,有助於防範您的應用程式出現已知的 Web 漏洞。

Helmet 實際上只由 9 個小型中介軟體函數組成,這些函數會設定安全相關的 HTTP 標頭:

安裝 Helmet 等之類的其他任何模組:


$ npm install --save helmet

然後在您的程式碼中使用它:


...
var helmet = require('helmet');
app.use(helmet());
...

至少停用 X-Powered-By 標頭

如果您不想使用 Helmet,最起碼請停用 X-Powered-By 標頭。攻擊者可能使用這個標頭(依預設,會啟用),來偵測執行 Express 的應用程式,然後啟動特定目標的攻擊。

因此最佳作法是使用 app.disable() 方法來關閉標頭:


app.disable('x-powered-by');

如果您使用 helmet.js,自會為您處理此事。

為了確保 Cookie 不會開啟您的應用程式進行惡意探索,請勿使用預設階段作業 Cookie 名稱,並適當設定 Cookie 安全選項。

以下是兩個主要的中介軟體 Cookie 階段作業模組:

這兩個模組之間的主要差異是它們儲存 Cookie 階段作業資料的方式。express-session 中介軟體會將階段作業資料儲存在伺服器上; 它只將階段作業 ID(而非階段作業資料)儲存在 Cookie 本身中。依預設,它使用記憶體內儲存體,且並非設計成用於正式作業環境。在正式作業中,您需要設定可調式階段作業儲存庫; 請參閱相容的階段作業儲存庫清單。

相對地,cookie-session 中介軟體會實作以 Cookie 為基礎的儲存體:它會將整個階段作業序列化為 Cookie,而非只是一個階段作業金鑰。只有在階段作業資料相對較小,且易於編碼成基本值(而非物件)時,才使用此項。雖然瀏覽器對於每個 Cookie 理應可以支援至少 4096 個位元組,為了確保您不會超出限制,對於每一個網域,請勿超過 4093 個位元組大小。此外要留意的是,用戶端可以看見 Cookie 資料,因此,若有任何原因需要保護該資料的安全或加以遮蔽,最好選擇 express-session。

使用預設階段作業 Cookie 名稱可能開放您的應用程式遭受攻擊。引發的安全問題類似於 X-Powered-By:潛在的攻擊者可能用它來對伺服器進行指紋辨識,從而發動目標攻擊。

為了避免發生此問題,請使用通用 Cookie 名稱; 例如,使用 express-session 中介軟體:


var session = require('express-session');
app.set('trust proxy', 1) // trust first proxy
app.use( session({
   secret : 's3Cur3',
   name : 'sessionId',
  })
);

設定下列 Cookie 選項來加強安全:

下列範例使用 cookie-session 中介軟體:


var session = require('cookie-session');
var express = require('express');
var app = express();

var expiryDate = new Date( Date.now() + 60 * 60 * 1000 ); // 1 hour
app.use(session({
  name: 'session',
  keys: ['key1', 'key2'],
  cookie: { secure: true,
            httpOnly: true,
            domain: 'example.com',
            path: 'foo/bar',
            expires: expiryDate
          }
  })
);

確定您的相依關係是安全的

使用 npm 來管理您應用程式的相依關係,不但效用大又很方便。但是您使用的套件可能含有重大的安全漏洞,可能也會影響您的應用程式。在您的相依關係中,您應用程式的安全強度如同「最弱的環節」。

請使用下列兩種工具(任一或併用),以協助您確保您所用協力廠商套件的安全:nsprequireSafe。這兩個工具的功用大致相同。

nsp 是指令行工具,會檢查 Node Security Project 漏洞資料庫,以判斷您的應用程式所使用的套件是否含有已知的漏洞。請依如下所示來安裝它:


$ npm i nsp -g

使用這個指令來提交 npm-shrinkwrap.json 檔,以便向 nodesecurity.io 驗證:


$ nsp audit-shrinkwrap

使用這個指令來提交 package.json 檔,以便向 nodesecurity.io 驗證:


$ nsp audit-package

以下說明如何使用 requireSafe,來審核您的 Node 模組:


$ npm install -g requiresafe
$ cd your-app
$ requiresafe check

其他注意事項

以下是優異的 Node.js Security Checklist 所提供的進一步建議。如需這些建議的所有詳細資料,請參閱該部落格文章:

避免其他已知的漏洞

關注 Node Security Project 中有關可能影響您應用程式所用之 Express 或其他模組的公告。一般而言,Node Security Project 是一個絕佳的資源,它提供 Node 安全的相關知識和工具。

最後,如同其他任何的 Web 應用程式,Express 應用程式仍可能遭到各種 Web 型攻擊。請多加熟悉已知的 Web 漏洞,並採取預防措施,來避免這些攻擊。