保護生產中 Node.js 應用程序安全的 15 項最佳實踐
在后端開發方面,Node.js 是開發人員最喜歡的技術之一。它的受歡迎程度不斷上升,現已成為在線攻擊的主要目標之一。這就是為什么保護 Node.js 免受漏洞和威脅至關重要。
在本指南中,您將看到為生產設計安全 Node.js 應用程序架構的 15 種最佳實踐。實施所有這些實踐,讓您的后端比以往任何時候都更安全!
為什么應該構建安全的 Node.js 應用程序?
構建安全的 Node.js 應用程序非常重要,至少有以下三個原因:
- 保護用戶數據:您的應用程序可能會處理敏感的用戶信息,如個人信息、登錄憑證、支付數據或機密的業務見解。如果不能保護這些數據,您可能會被隱私監管機構處以數百萬美元的罰款。通過實施強大的安全措施,您可以保護用戶數據并避免法律問題。
- 保護應用程序功能:安全漏洞可能會損害后端提供的功能。攻擊者可能會利用弱點來改變您的服務、操縱數據或注入惡意代碼。通過保護您的應用程序,您可以避免這種情況,并為您的用戶提供無縫的體驗。
- 維護聲譽:安全事件可能會嚴重損害您的聲譽并削弱對您服務的信任。客戶和用戶希望他們的數據得到安全處理,并且您的應用程序能夠按預期運行。違規可能會導致失去信任,但通過優先考慮安全性,您可以表明您對質量的承諾。
您可能認為安全問題并沒有那么普遍,遵循編碼和架構最佳實踐就足夠了,但事實并非如此。Node.js 的強大之處在于 NPM 環境,它提供了數百萬個庫。問題是大多數 NPM 包都存在一些安全漏洞。
換句話說,如果 Node.js 項目的依賴項不安全,那么它就不安全。考慮到使用外部庫的流行程度,這是令人擔憂的。根據 Snyk 開源安全狀況報告,平均一個 Node.js 項目在 79 個直接依賴項中存在 49 個漏洞。這一相關統計數據強調了保護 Node.js 應用程序的重要性。
讓 Node.js 應用程序更安全的 15 個最佳實踐
1.切勿使用 Root 權限運行 Node.js
不建議使用 root 權限運行 Node.js,因為這違反了最小權限原則。無論您的后端是在專用服務器還是 Docker 容器上,您都應該始終以非 root 用戶身份啟動它。
如果您使用 root 權限運行 Node.js,則項目或其依賴項中的任何漏洞都可能被利用來獲得對系統的未經授權的訪問。例如,攻擊者可以利用它們執行任意代碼、訪問敏感文件,甚至控制整個機器。因此,必須避免使用 Node.js 的 root 用戶。
這里的最佳實踐是創建一個專門的用戶來運行 Node.js。該用戶應僅具有啟動應用程序所需的權限。這樣,成功破壞您后端的攻擊者將被限制為該用戶的權限,從而限制了他們可能造成的潛在損害。
2.讓你的 NPM 庫保持最新
NPM 庫使構建功能齊全的 Node.js 后端變得更容易、更快捷。同時,它們還會給您的應用程序帶來安全風險。新的漏洞一直在被發現,維護人員的工作就是解決這些漏洞并發布軟件包的更新版本。這就是為什么您應該保持依賴項最新的原因。
為了確保您所依賴的 NPM 庫的安全,您可以使用 npm audit[1] 和 snyk[2] 。這些工具分析項目的依賴關系樹并提供對任何已知漏洞的見解。
這是運行 npm audit 的示例:
npm audit
...
found 4 vulnerabilities (2 low, 2 moderate)
run `npm audit fix` to fix them, or `npm audit` for details
此命令利用 GitHub Advisory 數據庫[3]并檢查您的 package.json 和 package-lock.json 是否存在已知安全問題。
此外,您可以使用 Snyk 檢查您對 Snyk 開源漏洞數據庫的依賴關系。安裝 snyk :
npm install -g snyk
在項目的根文件夾中,使用以下命令測試您的應用程序:
snyk test
要打開一個向導來引導您完成修補所發現的漏洞的過程,請運行:
snyk wizard
使用 snyk 并定期運行 npm audit 可幫助您在 NPM 庫中的安全問題成為問題之前識別并修復它們。請記住,應用程序的安全性取決于依賴項中最薄弱的環節。
3.避免使用默認的 Cookie 名稱
Node.js 應用程序使用的 cookie 名稱可能會無意中泄露您的后端所基于的技術堆棧。這是有價值的信息,您應該始終隱藏它,因為攻擊者可以再次使用它。通過了解您正在使用的框架,他們可以利用與其相關的特定弱點。
詳細而言,攻擊者往往將注意力集中在會話 cookie 的名稱上。通過使用 express-session[4] 中間件設置自定義會話 cookie 名稱來保護您的應用程序免受此類影響:
const express = require("express");
const session = require("express-session");
const app = express();
app.use(
session({
// set a custom name for the session cookie
name: "myCustomCookieName",
// a secure secret key for session encryption
secret: "mySecretKey",
})
);
4.設置安全 HTTP 標頭
Express 中默認的 HTTP 標頭不是很安全。我們使用在線 Security Headers 項目[5]檢查標頭安全性:
圖片
其中一些標頭包含不應公開的信息,如 X-Powered-By。還有一些則是缺失的,應該添加進來,以處理各種與安全相關的問題,包括防止跨站腳本 (XSS) 攻擊。
這就是 helmet[6] 發揮作用的地方!該庫負責根據安全標頭的建議設置最重要的安全標頭。使用方法如下:
const express = require("express");
const helmet = require("helmet");
const app = express();
// register the helmet middleware
// to set the security headers
app.use(helmet());
helmet() 中間件會自動刪除不安全的標頭并添加新的標頭,包括 X-XSS-Protection 、 X-Content-Type-Options 、 Strict-Transport-Security 和 X-Frame-Options。這些都是最佳實踐,有助于保護您的應用程序免受常見攻擊。
Node.js 應用程序設置的標頭現在將被視為安全:
圖片
5.實施速率限制
DDoS(分布式拒絕服務)和暴力破解是兩種最常見的 Web 攻擊。為了緩解它們,您可以實施速率限制。此技術涉及控制 Node.js 后端的傳入流量,防止惡意行為者用過多的請求淹沒您的服務器。
實施速率限制的最簡單方法是通過 rate-limiter-flexible[7] 庫。該依賴庫提供了一個可配置的中間件,用于限制在指定時間內來自同一 IP 地址或用戶的請求數量。
以下是如何使用它在 Node.js 中應用速率限制的示例:
const express = require("express");
const {
RateLimiterMemory,
} = require("rate-limiter-flexible");
const app = express();
const rateLimiter = new RateLimiterMemory({
points: 10, // 允許的最大請求數
duration: 1, // 時間范圍,以秒為單位
});
const rateLimiterMiddleware = (req, res, next) => {
rateLimiter
.consume(req.ip)
.then(() => {
// 請求被允許,繼續處理請求
next();
})
.catch(() => {
//超過請求限制,使用適當的錯誤消息進行響應
res.status(429).send("Too Many Requests");
});
};
app.use(rateLimiterMiddleware);
首先,初始化一個速率限制器實例,允許 1 秒內最多 10 個請求。然后,在自定義中間件中使用它來分析傳入請求的 IP。如果未超出速率限制,則請求將繼續。否則,請求將被阻止并且服務器返回 429 Too Many Requests 響應。
6.確保強大的身份驗證策略
為了保護您的 Node.js 應用程序免受利用用戶身份驗證的攻擊,您需要實施強身份驗證策略。首先,邀請用戶設置強密碼。此外,您還應該支持多重身份驗證[8] (MFA) 和單點登錄[9] (SSO)。MFA 通過要求用戶提供多種形式的身份驗證來增加額外的安全層,而 SSO 則簡化了身份驗證過程并降低了弱密碼或重復使用密碼的風險。
當需要對密碼進行散列存儲時,應首選 bcrypt[10] 等強大的加密函數,而不是 Node.js crypto 庫提供的方法。該軟件包提供了一種安全的密碼散列算法,大大增加了攻擊者破解密碼的難度。最后,如前所述,通過限制登錄失敗次數來減少暴力破解攻擊。
7.不要發送不必要的信息
無意中提供給攻擊者的任何信息都可能被用來對付你。因此,服務器響應只應包含調用者嚴格需要的內容。例如,避免直接向客戶端返回詳細的錯誤信息或堆棧跟蹤。取而代之的是,提供不透露具體實現細節的通用錯誤信息。最簡單的方法是在生產模式下運行 Node.js,設置 NODE_ENV=production env,否則 Express 會在錯誤響應中添加堆棧跟蹤。
同樣,您必須小心 API 響應中包含的數據。僅返回必要的數據字段,并避免暴露調用者未請求的敏感信息。這將最大限度地減少意外泄露機密或特權信息的風險。
8.監控你的后端
您在生產中的后端可能正在遭受攻擊,而您可能根本沒有意識到這一點。這就是監控 Node.js 應用程序至關重要的原因。通過將其連接到應用程序性能監控[11] (APM) 工具,您可以對其進行跟蹤,以發現安全問題并確保其整體健康。
幸運的是,有幾個可用于 Node.js 的 APM 庫和服務。其中最受歡迎的一些是 SigNoz[12]、Sentry[13]、Prometheus[14]、New Relic[15] 和 Elastic[16],它們提供了應用程序各個方面的信息,包括性能、錯誤率、資源使用情況和安全相關指標。特別是,它們可以實現實時數據收集和檢測可能表明安全漏洞的異常或可疑活動。其中一些還提供可維護性功能,以跟蹤 CI/CD 管道中的部署工作流程。
9.采用僅 HTTPS 的策略
通過確保只能通過 HTTPS 訪問后端,您將提高客戶端和 Node.js 服務器之間交換數據的機密性。HTTPS 建立一個加密通道,保護密碼、會話令牌和用戶數據等敏感信息免遭攔截。
作為此類政策的一部分,您還應該使用 HTTPS cookie。為此,請確保 Node.js 應用程序設置的任何 cookie 都標記為 secure 和 httpOnly:
res.cookie("myCookie", "cookieValue", {
// create an HTTPS cookie
secure: true,
httpOnly: true,
});
意外方或腳本將無法再訪問您的 cookie。此外,它們只能通過 HTTPS 連接傳輸。
10.驗證用戶輸入
每當用戶有機會輸入內容時,攻擊者就可以利用它向服務器發送惡意數據。因此,驗證用戶輸入對于確保 Node.js 應用程序的安全性和完整性至關重要。
11.使用安全檢查器
安全檢查器會分析您的代碼庫,以識別漏洞、不安全的代碼部分和最佳實踐違規行為。其中最流行的是 eslint-plugin-security[17] ,這是一組用于在 Node.js 中實施安全開發的 ESLint 規則。
通過將此類工具集成到您的開發工作流程中,您可以及早發現并解決安全問題。具體來說,它們可以降低編碼時將漏洞引入應用程序的風險。這些工具在集成到 CI/CD 管道中時特別有效。
12.防止 SQL 注入
SQL 注入是一種常見的安全漏洞,當攻擊者可以操縱傳遞到 SQL 查詢的輸入數據時就會發生這種漏洞。當將用戶輸入直接連接到 SQL 查詢中時,通常會發生這種情況。在這種情況下,攻擊者可以偽造旨在執行任意 SQL 代碼的特定輸入,從而導致未經授權的訪問和數據泄露。
有多種方法可以防止 Node.js 中的 SQL 注入。最流行的是:
- 使用準備好的語句或參數化查詢:這些技術涉及將 SQL 代碼與用戶輸入分離,防止其被解釋為查詢的一部分。
- 輸入清理:驗證用戶輸入以拒絕惡意數據,降低 SQL 注入攻擊的風險。
- 使用 ORM:像 Sequelize 這樣的 ORM 技術通常提供針對 SQL 注入的內置保護。
13.限制請求大小
Node.js 中的默認請求正文大小限制為 5 MB。為了保護您的后端免受惡意用戶試圖用數據淹沒您的服務器的 DDoS 攻擊,建議減少該限制。為此,您可以使用 body-parser[18] 庫并按如下方式配置它:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
// 將請求大小限制設置為1 MB
app.use(bodyParser.json({ limit: "1mb" }));
請根據您的具體要求調整該值。現在,正文大于 1 MB 的請求將立即被阻止,服務器將無法分配資源來處理這些請求。
14.通過自動化工具檢測漏洞
自動漏洞掃描工具(例如 SonarQube 或類似工具)是識別 Node.js 應用程序中安全問題的寶貴資源。這些工具對代碼庫、依賴項、配置和其他組件執行全面掃描,以識別安全漏洞。
以下是使用自動漏洞掃描器的一些主要好處:
- 早期檢測:在部署應用程序之前主動識別安全問題。
- 增加覆蓋范圍:對所有項目文件進行深度掃描,確保高安全覆蓋范圍。
- 持續監控:將它們集成到 CI/CD 管道中,以確保及時發現通過代碼更改引入的任何新漏洞。
15.讓漏洞報告更簡單
讓用戶和安全研究人員能夠報告 Node.js 后端中發現的漏洞是確保應用程序安全的另一個重要方面。這不僅應該是可能的,而且程序必須清晰且易于理解。
security.txt[19] 提議的標準是讓研究人員與您聯系的有效方法。這是一個放置在項目根目錄下的簡單文本文件,提供有關如何報告安全漏洞的信息。它遵循標準化格式,包括聯系方式、加密方法和披露指南。
以下是基本 security.txt 文件的示例:
Contact: email@example.com
Encryption: https://example.com/pgp-key.asc
Contact 指定應向其報告安全漏洞或問題的電子郵件地址。這些電子郵件可能包含關鍵信息,不應公開訪問。因此, Encryption 字段指示組織的 PGP 公鑰的位置,該公鑰可用于加密電子郵件內的消息。這種機制確保只有組織才能使用私鑰解密這些消息并讀取它們。
同樣,您也可以考慮在網站上添加“報告漏洞”頁面。
結論
在本指南中,我們討論了在生產中保護 Node.js 應用程序安全的方法。作為開發人員,我們有責任保護用戶數據、維護應用程序功能并保護我們的聲譽。
通過集成這些技術、方法和技巧,您可以創建更可靠的 Node.js 架構,降低風險并確保應用程序的安全性。
原文:https://semaphoreci.medium.com/best-practices-for-securing-node-js-applications-in-production-d24b7c4981d
最近文章
- RDB.js:適用于 Node.js 和 Typescript 的終極對象關系映射器
- 如何讓你的Node.js應用程序處理數百萬的API請求
- UI 設計通識:通過 60-30-10 規則增強美感
- NativeScript 與 Flutter:移動應用程序開發孰優孰劣?
- 我的過山車之旅:從0美元到3萬美元,然后再回到0美元
- 15個快速且易于實施的 SaaS 創意
- 將Flutter推向極限:你應該知道的44個性能提示
- Spaces SDK:專為實時協作功能開發設計的SDK
參考資料
[1]npm audit: https://docs.npmjs.com/cli/v9/commands/npm-auditnpm 審核:https://docs.npmjs.com/cli/v9/commands/npm-audit
[2]snyk: https://www.npmjs.com/package/snyk
[3]GitHub Advisory 數據庫: https://github.com/advisoriesGitHub 咨詢數據庫:https://github.com/advisories
[4]express-session: https://www.npmjs.com/package/express-session
[5]Security Headers 項目: https://securityheaders.com/安全標頭項目:https://securityheaders.com/
[6]helmet: https://www.npmjs.com/package/helmet
[7]rate-limiter-flexible: https://www.npmjs.com/package/rate-limiter-flexible
[8]多重身份驗證: https://en.wikipedia.org/wiki/Multi-factor_authentication多重身份驗證:https://en.wikipedia.org/wiki/Multi-factor_authentication
[9]單點登錄: https://en.wikipedia.org/wiki/Single_sign-on單點登錄:https://en.wikipedia.org/wiki/Single_sign-on
[10]bcrypt: https://www.npmjs.com/package/bcrypt
[11]應用程序性能監控: https://en.wikipedia.org/wiki/Application_performance_management應用程序性能監控:https://en.wikipedia.org/wiki/Application_performance_management
[12]SigNoz: https://github.com/SigNoz/signoz
[13]Sentry: https://github.com/getsentry/sentry-javascript
[14]Prometheus: https://github.com/prometheus/prometheus
[15]New Relic: https://github.com/newrelic/node-newrelic新遺跡:https://github.com/newrelic/node-newrelic
[16]Elastic: https://github.com/elastic/apm-agent-nodejs
[17]eslint-plugin-security: https://www.npmjs.com/package/eslint-plugin-security
[18]body-parser: https://www.npmjs.com/package/body-parser
[19]security.txt: https://en.wikipedia.org/wiki/Security.txt