Node.js 应用安全最佳实践

Node.js 应用安全最佳实践

Flying
2022-01-25 / 0 评论 / 113 阅读 / 正在检测是否收录...

Node.js 的优势之一是能够安装额外的模块,从安全的角度来看,这提供了更多打开后门的机会。此外,框架越流行,黑客尝试发现漏洞的机会就越大。因此,您应该始终认真对待 Node.js 的安全性。在这篇文章中,您将了解保护 Node.js 应用程序的 11 种最佳实践。

nodeja-app-security.webp

验证用户输入

让我们从最流行的攻击之一开始,SQL 注入。

-SQL注入
顾名思义,当黑客能够在您的数据库上执行 SQL 语句时,就会发生 SQL 注入攻击。当您不清理来自前端的输入时,这将成为可能。换句话说,如果您的 Node.js 后端从用户提供的数据中获取参数并将其直接用作 SQL 语句的一部分。例如:

connection.query('SELECT * FROM orders WHERE id = ' + id, function (error, results, fields) {
  if (error) throw error;
  // ...
});

上述查询存在 SQL 注入漏洞。为什么?因为 id 参数直接取自前端。攻击者不仅可以发送 id,还可以操纵请求并使用它发送 SQL 命令。攻击者可以发送 4564,而不是只发送 4564(订单的 id);删除表订单;Node.js 将 drop 您的数据库。

你如何避免这种情况?有几种方法,但基本思想是不要盲目地将参数从前端传递给数据库查询。相反,您需要验证或转义用户提供的值。如何做到这一点完全取决于您使用的数据库以及您喜欢的方式。Node.js 的一些数据库库会自动执行转义(例如 node-mysql 和 mongoose)。但您也可以使用更通用的库,如 Sequelizeknex

  • XSS 攻击

跨站点脚本 (XSS) 攻击的工作方式与 SQL 注入类似。不同之处在于,攻击者能够执行 JavaScript 代码,而不是发送恶意 SQL。原因和以前一样,不验证用户的输入。

app.get('/find_product', (req, res) => {
  ...
  if (products.length === 0) {
    return res.send('<p>No products found for "' + req.query.product + '"</p>');
  }
  ...
});

实现 HTTP 响应头

通过向应用程序添加额外的与安全相关的 HTTP 标头,可以避免许多不太常见的攻击。CORS 等最基本的机制将提高 API 的安全性,但请考虑使用像头盔这样的模块,它会添加更多标头以保护您的应用程序。Helmet 可以通过一行代码为您实现 11 种不同的基于标头的安全机制:

实施强认证

具有损坏、薄弱或不完整的身份验证机制被列为第二常见的漏洞。这可能是因为许多开发人员将身份验证视为“我们拥有它,所以我们很安全”。实际上,弱或不一致的身份验证很容易绕过。一种解决方案是使用现有的身份验证解决方案,如 Okta 或 OAuth。

如果您更喜欢坚持使用原生 Node.js 身份验证解决方案,您需要记住一些事情。创建密码时,不要使用 Node.js 内置的加密库;使用 BcryptScrypt。确保限制失败的登录尝试,并且不要告诉用户是用户名或密码不正确。相反,返回一个通用的“不正确的凭据”错误。您还需要适当的会话管理策略。并确保实施 2FA 身份验证。如果处理得当,它可以极大地提高应用程序的安全性。您可以使用 node-2faspeakeasy 等模块来完成。

避免暴露太多的错误

这里有几件事需要考虑。首先,不要让用户知道细节,即不要将完整的错误对象返回给客户端。它可以包含您不想公开的信息,例如路径、正在使用的另一个库,甚至可能是秘密。其次,使用 catch 子句包装路由,当请求触发错误时,不要让 Node.js 崩溃。这可以防止攻击者找到会使您的应用程序崩溃的恶意请求并一遍又一遍地发送它们,从而使您的应用程序不断崩溃。

说到用恶意请求淹没你的 Node.js 应用程序,不要直接将你的 Node.js 应用程序暴露在 Internet 上。在它前面使用一些组件,例如负载均衡器、云防火墙或网关,或者旧的好 nginx。这将允许您在 DoS 攻击攻击您的 Node.js 应用程序之前对其进行评级限制。

运行自动漏洞扫描

Node.js 生态系统包含许多可以安装的不同模块和库。在您的项目中使用其中很多是很常见的。这会产生安全问题;使用其他人编写的代码时,您不能 100% 确定它是安全的。为了解决这个问题,您应该经常运行自动漏洞扫描。它们可以帮助您找到具有已知漏洞的依赖项。您可以使用 npm audit 进行基本检查,但请考虑使用此处描述的工具之一。

即使在编写代码时也可以捕获常见的安全漏洞。通过使用 eslint-plugin-security 这样的 linter 插件。每次您使用不安全的代码实践(例如使用 eval 或非文字正则表达式)时,安全 linter 都会通知您。

避免数据泄露

假设您想要显示注册了某个活动的用户列表。您执行 SQL 查询以获取该特定事件的所有用户并将该数据发送到前端,然后过滤它以仅显示名字和姓氏。但是您不想显示的所有数据(如用户的出生日期、电话号码、电子邮件地址等)都可以通过浏览器开发者控制台轻松访问。这会导致数据泄露。

你如何解决它?只发送需要的数据。如果您只需要名字和姓氏,则只从数据库中检索那些。这创造了更多的工作,但这绝对是值得的。

设置日志记录和监控

您可能认为日志记录和监控虽然很重要,但与安全性并没有真正的关系,但事实并非如此。当然,目标是从一开始就确保系统安全,但实际上,它需要一个持续的过程。为此,您需要记录和监控。一些黑客可能有兴趣使您的应用程序不可用,您无需登录即可发现。但是一些黑客更愿意在更长的时间内保持不被发现。对于这种情况,监控日志和指标将帮助您发现问题所在。仅使用基本日志记录,您将无法获得足够的信息来了解奇怪的请求是来自您自己的应用程序、第三方 API 还是来自黑客。

避免配置文件中的泄密

从环境变量中导入机密是第一步,但这也不是一个完美的解决方案。要更加确信您的机密不易阅读,请使用 Vault 等机密管理解决方案。每当无法使用 Vault 时,请在存储秘密时对其进行加密,并确保定期轮换它们。许多 CI/CD 解决方案允许您安全地存储机密并安全地部署它们。

不要以 root 身份运行

在 Docker 和微服务的世界中,我们经常忘记 Node.js 是如何实际执行的。很容易启动一个 Docker 容器并假设它与主机隔离,因此它是安全的。但是使用 Docker 并不意味着以 root 身份运行 Node.js 不再是问题。将通过 XSS 攻击运行任何 JavaScript 代码的能力与以 root 身份运行的 Node.js 相结合,您最终将获得无限的黑客攻击能力。

总结

保护 Web 应用程序很重要,但紧迫的期限有时会阻止我们在任何给定阶段正确执行。这就是为什么在软件开发生命周期的每一步都考虑安全性很重要,从概念一直到生产。

参考链接

1

评论 (0)

取消