生产最佳实践:安全

概述

术语 “production” 指的是软件生命周期中的一个阶段,此时应用程序或 API 通常可供其最终用户或消费者使用。 相比之下,在 “development” 阶段,您仍在积极编写和测试代码,并且应用程序不对外开放。 相应的系统环境分别称为生产环境和开发环境。

开发和生产环境的设置通常不同,要求也大相径庭。 在开发中很好的东西在生产中可能是不可接受的。 例如,在开发环境中,您可能需要详细记录错误以进行调试,而同样的行为在生产环境中可能会成为安全问题。 在开发中,您无需担心可伸缩性、可靠性和性能,而这些问题在生产中变得至关重要。

注意: If you believe you have discovered a security vulnerability in Express, please see 安全政策和程序.

生产中 Express 应用程序的安全最佳实践包括:

不要使用已弃用或易受攻击的 Express 版本

不再维护 Express 2.x 和 3.x。 这些版本中的安全和性能问题不会得到修复。 不要使用它们! 如果您还没有移动到版本 4,请遵循 migration guide

还要确保您没有使用 安全更新页面 上列出的任何易受攻击的 Express 版本。 如果是,请更新到稳定版本之一,最好是最新版本。

使用 TLS

如果您的应用程序处理或传输敏感数据,请使用 传输层安全 (TLS) 来保护连接和数据。 该技术在数据从客户端发送到服务器之前对其进行加密,从而防止一些常见(且容易)的黑客攻击。 尽管 Ajax 和 POST 请求可能不明显并且在浏览器中看起来像 “hidden”,但它们的网络流量容易受到 packet sniffing中间人攻击 的攻击。

您可能熟悉安全套接字层 (SSL) 加密。 TLS 只是 SSL 的下一步。 换句话说,如果您以前使用过 SSL,请考虑升级到 TLS。 一般来说,我们推荐 Nginx 来处理 TLS。 有关在 Nginx(和其他服务器)上配置 TLS 的良好参考,请参阅 推荐的服务器配置 (Mozilla Wiki)

此外,获得免费 TLS 证书的便捷工具是 让我们加密,它是 互联网安全研究组 (ISRG) 提供的免费、自动化和开放的证书颁发机构 (CA)。

使用 Helmet

Helmet 可以通过适当设置 HTTP 标头来帮助保护您的应用程序免受一些众所周知的 Web 漏洞的侵害。

Helmet 是几个较小的中间件函数的集合,它们设置与安全相关的 HTTP 响应标头。 一些例子包括:

Helmet 包括其他几个中间件函数,您可以阅读 在其文档网站

像任何其他模块一样安装头盔:

$ npm install --save helmet

然后在您的代码中使用它:

// ...

const helmet = require('helmet')
app.use(helmet())

// ...

减少指纹

它可以帮助提供额外的安全层以减少服务器指纹识别。 虽然本身不是安全问题,但改善 Web 服务器整体状况的一种方法是采取措施降低对服务器上使用的软件进行指纹识别的能力。 服务器软件可以通过 kwirks 识别它们如何响应特定请求。

默认情况下,Express.js 发送 X-Powered-By 响应标头横幅。 这可以使用 app.disable() 方法禁用:

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

注意: Disabling the X-Powered-By header does not prevent a sophisticated attacker from determining that an app is running Express. It may discourage a casual exploit, but there are other ways to determine an app is running Express.

Express.js 还发送它自己的格式化 404 Not Found 消息和自己的格式化程序错误响应消息。 这些可以由 添加您自己的未找到处理程序编写自己的错误处理程序 更改:

// last app.use calls right before app.listen():

// custom 404
app.use((req, res, next) => {
  res.status(404).send("Sorry can't find that!")
})

// custom error handler
app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

为确保 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 中间件:

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

设置以下 cookie 选项以增强安全性:

下面是一个使用 cookie-session 中间件的例子:

const session = require('cookie-session')
const express = require('express')
const app = express()

const 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
  }
}))

防止针对授权的暴力攻击

确保登录端点受到保护,以使私人数据更加安全。

一种简单而强大的技术是使用两个指标来阻止授权尝试: 1. 第一个是同一用户名和 IP 地址连续尝试失败的次数。 1. 第二个是在很长一段时间内来自 IP 地址的失败尝试次数。 例如,如果某 IP 地址在一天内尝试 100 次失败,则阻止该 IP 地址。

rate-limiter-flexible 包提供了使这项技术简单快捷的工具。 你可以找到 文档中的暴力保护示例

确保您的依赖项是安全的

使用 npm 管理应用程序的依赖项非常强大且方便。 但是您使用的软件包可能包含严重的安全漏洞,这些漏洞也会影响您的应用程序。 您的应用程序的安全性仅与依赖项中的 “weakest link” 一样强。

Since npm@6、npm 自动审查每个安装请求。 你也可以使用 ‘npm audit’ 来分析你的依赖树。

$ npm audit

如果您想保持更安全,请考虑 Snyk

Snyk 提供 命令行工具Github 整合,用于根据 Snyk 的开源漏洞数据库 检查您的应用程序是否存在依赖项中的任何已知漏洞。 按如下方式安装 CLI:

$ npm install -g snyk
$ cd your-app

使用此命令测试您的应用程序是否存在漏洞:

$ snyk test

使用此命令打开一个向导,引导您完成应用更新或补丁以修复所发现漏洞的过程:

$ snyk wizard

避免其他已知漏洞

请留意可能影响 Express 或您的应用程序使用的其他模块的 Node 安全项目Snyk 公告。 总的来说,这些数据库是有关 Node 安全的知识和工具的极好资源。

最后,Express 应用程序 - 与任何其他网络应用程序一样 - 可能容易受到各种基于网络的攻击。 熟悉已知的 网络漏洞 并采取预防措施避免它们。

其他注意事项

以下是优秀的 Node.js 安全检查表 的一些进一步建议。 有关这些建议的所有详细信息,请参阅该博客文章: