Node.js的安全性最佳实践

作者 : IT 大叔 本文共4981个字,预计阅读时间需要13分钟 发布时间: 2020-09-4

由于如今有许多系统连接到Web(或者至少在某种程度上与Web进行通信/集成),因此公司越来越重视Web安全

当某些事件传出新闻时,Web安全通常会引起公众注意,例如,安全漏洞,黑客活动和/或窃取大公司(其中一些确实非常大)(例如Google,LinkedIn等)的数据。

除了我们大多数人可能都不喜欢的巨大参与者的娱乐圈世界之外,在您的系统上实现安全性不仅很重要,而且许多开发人员都大大低估甚至忘记了这一点。

设置,最佳实践,性能,测试和指标可能是您在日常编程过程中要考虑的事项。但是,不幸的是,对于安全性最佳实践而言,情况并不相同。

而且不是由于警告。如果您在GitHub的保护范围内从事开源领域的工作,那么您很可能会遇到一些有关脆弱依赖项的警报。代码社区平台在检测多种不同语言的成千上万个不同库中的漏洞方面正变得越来越好,也越来越担心。

如今,中小型企业更容易获得负担得起安全工具(或可能是整个平台)的安全工具,以帮助开发人员弥补其代码和应用程​​序中的空白。

Sign AppSignal现在也支持Node.js。我们增加了一系列集成,即支持更多现成的仪器。我们已经支持Next.js,PostgreSQL,Redis和Express,并且刚刚添加了Apollo。了解有关AppSignal for Node.js的更多信息

但是,无论您使用还是不使用这种安全平台,了解并了解您的应用程序可能遭受的安全威胁并通过简单(但功能强大)的最佳实践来与之抗争是本文的主要目标。

实际上,我们将选择Node.js作为分析豚鼠,但是这里的许多项目也与其他平台完全匹配。

作为参考,OWASP开放Web应用程序安全性项目)将指导我们完成一般而言针对Web应用程序的十大最关键的安全风险。它是根据对广泛成员名单的分析而建立的共识委员会。然后让我们在Node的帮助下面对现实。

注射攻击

Web应用程序最著名的威胁之一与攻击者是否可能向您的后端代码发送SQL片段有关。

当开发人员将重要的SQL语句直接连接到其数据库层时,通常会发生这种情况,如下所示:

// "id" comes directly from the request's params
db.query('select * from MyTable where id = ' + id);
   .then((users) => {
     // return the users into the response
   });

如果开发人员不对请求中到达的输入参数进行清理,那么攻击者可能会传递多个整数ID,例如可以检索敏感信息甚至将其删除的SQL指令(更不用说适当备份策略的重要性了) )。

大多数编程语言及其各自的ORM框架通常通过将输入参数化为查询语句来提供避免SQL注入的方法,这些查询语句在直接执行到数据库之前,将由您的语言库机制的内部逻辑进行验证。

在这种情况下,密切了解您的语言/框架以了解他们的工作方式非常重要。

例如,如果您使用Sequelize,那么一种简单的方法是:

const { QueryTypes } = require('sequelize');

await sequelize.query(
  'select * from MyTable where id = :p1',
  {
    replacements: { p1: id }, // id comes from the request's param
    type: QueryTypes.SELECT
  }
);

身份验证陷阱

身份验证通常是系统的一部分,需要引起很多关注,特别是如果您使用易于允许开发人员公开敏感用户信息的框架或工具。

OWASP认为此项目很关键。OAuth之类的标准(现在是其第二版,正在第三版上)正在不断发展,以尝试尽可能多地包含网络世界的许多不同现实。

根据项目的方案或公司决定自定义标准用法的方式,其实施可能会很棘手。

如果您的团队(和公司)有能力为您的项目增加Auth0Amazon Cognito以及市场上很多其他大型公司(因此也很成熟),那将是成功的一半。

当涉及到实施的OAuth2在Node.js的,有很多的标准,开放源码的选项,可以帮助你并不是从零开始。就像著名的node-oauth2-server模块一样。

确保始终参考要添加到项目中的任何模块或框架的官方文档(无论是开源的还是付费的)。另外,在为身份验证流添加安全性时,切勿使用小型的最新开源项目(承担此类风险对于应用程序的重要组成部分而言过于重要)。

敏感数据暴露

定义什么是敏感数据很重要。根据项目的类型,它可能会有所不同。但是,无论应用程序的性质如何,例如信用卡和证件ID之类的东西始终会很敏感。

这些信息将如何传递到您的系统?加密了吗?没有?真?

在将“ 真正重要的 ”内容与其余的内容分开之后,是时候确定需要存储什么以及存储多长时间了。

您会惊讶于其中存储敏感信息以供进一步使用的应用程序,这些应用程序未经用户许可甚至更糟,这会让您感到惊讶。顺便说一句,这很容易违反数据隐私法则,这取决于应用程序运行所在的国家/地区(这是另一件事需要担心)。

让我们转到待办事项(又称必做)列表:

  • 加密您的敏感数据。忘记MD5,您的数据应该受到正确算法的严格保护。因此,选择Scrypt
  • 向用户警告您的应用程序如何处理敏感信息。您可以定期向他们发送解释性图表信息,并在登录时弹出一些有用的信息,是的,您的使用条款也必须说明这一点。
  • 进行HTTPS。期。如果您不喜欢,那么Google会不喜欢您。
  • 如果可以的话,请进一步做HSTS。它是一种策略机制,可增强您的Web安全性,以抵御著名的中间人攻击。

在Node应用程序中设置HSTS非常简单:

const hsts = require('hsts');

app.use(hsts({
  maxAge: 15552000  // 180 days in seconds
}));

您可以通过定义(例如,是否应包含子域)来微调设置:

app.use(hsts({
  maxAge: 15552000,
  includeSubDomains: false
}));

显然,您将需要hsts npm软件包。请确保参考其官方文档以获取更多信息。

旧的XML外部实体(XXE)

XXE攻击是通过探索较旧的XML处理器所具有的漏洞而发生的,这些漏洞使攻击者可以指定外部实体并将其发送给解析XML输入的应用程序。

如果解析器配置不正确,则攻击者可以访问敏感信息,机密数据(例如服务器中的密码)等。

作为示例,考虑一个基于XML的Web服务,该服务接收以下XML内容作为输入:

<?xml version="1.0" encoding="ISO-8859-1"?>
   <id>1</id>
   <name>attacker@email.com</name>
   ...
</xml>

乍一看,它看起来就像您到目前为止所看到的所有其他输入一样。但是,如果您托管在服务器上的应用未准备好应对攻击,则可以通过以下方式发送此类信息:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///c:/boot.ini" >]>
    <id>1</id>
    <name>attacker@email.com</name>
    ...
  <foo>&xxe;</foo>
</xml>

这将在响应中返回boot.ini文件的内容。

另一个很好的例子是您的应用程序是否处理上传文件。例如,如果将其限制为仅接受某些文件组,则可以接受基于XML的格式(如DOCX或著名的SVG图片图像),并且还可以进行恶意代码处理。

防止此类攻击的最简单方法是禁用库的解析功能。该节点的libxml NPM包,例如,提供了一系列的功能,以验证您的DTD,并帮助您保护免受这些攻击您的应用程序。

存取控制中断

此项主要与应用程序在用户对其不同区域(或URL)的权限方面的测试程度有关。

换句话说,如果假设您在应用程序上具有受限区域(例如,管理仪表板),并且没有适当角色的普通用户仍然可以访问它,那么您将具有访问漏洞。

它很容易纠正,不需要任何特定的解决方案,您可以使用已经使用的任何东西。唯一的注意是要注意正确实施它,并用适当的测试覆盖它,以确保也覆盖新的端点。

Node提供了很多库来帮助解决此问题,还提供了中间件来检查当前用户的权限,您也可以自己实现一个。

安全配置错误

在应用程序生命周期的早期阶段,通常会定义三个主要环境(开发阶段或阶段,质量保证和生产),并使设置保持相等。

这种类型的错误配置有时会持续很长时间而没有引起注意,并且可能导致严重攻击,因为考虑到大多数情况下,分阶段和QA配置受到的保护很弱,因此该应用程序容易受到攻击。

在谈论配置时,请确保将它们与所有类型的依赖项(数据库,外部集成,API,网关等)相关联。

定义明确,彼此独立且分开的设置至关重要。另外,请考虑将您的凭据(和敏感设置的数据)存储在项目文件之外的其他远程位置。

您公司的文化方面也可能在这里发生。例如,如果您使用Splunk或任何其他日志记录工具,请确保具有能够迫使开发人员不记录敏感数据的策略(以及检查方法),因为与存储相同数据的数据库相比,Splunk可以更轻松地访问数据。

这让我想起了在一家公司的一段时间,在该公司中,由于开发人员“无辜地”复制了公司的一个回购库以便在家学习,因此主数据库的密码被上到了公共GitHub回购库。别误会我的意思……我并不是说最大的错误是他的;它不是。

臭名昭著的XSS

XSS是一个臭名昭著的叛军。即使它疯狂地出名,每天的奔波也很容易使您忘记它。

这里的问题类似于SQL注入。您的Web应用程序中有一个端点,该端点可以接收请求并返回响应。没什么大不了的。但是,当您将请求数据与响应串联在一起而不进行消毒时,它就成为一个。

一个典型的例子是:

app.get('/users', (req, res) => {
  const user = db.getUserById(req.query.id);
  if (!user) {
    return res.send('<span>Sorry, the user "' + req.query.product + '" was not found!</span>');
  }
  ...
});

猜猜客户端发送带有以下id参数的请求时会发生什么:

<script>alert(Uh la la, it's me! XSS!!)</script>

目前,这只是一条无害的警报消息,但是我们都知道,攻击者将在其中放置更多的JavaScript代码。

只需通过添加新的中间件,Node 即可解决此问题的选项很多。选择一个,正确实施,然后继续。

不安全的反序列化

当应用程序从不受信任的来源接受可能被攻击者篡改的序列化对象时,就会发生这种破坏。

例如,想象一下,您的Node Web应用程序与客户端通信并在用户登录后返回,该序列化的对象将保留在cookie中,该cookie将作为用户的会话工作,并存储诸如用户ID和权限之类的数据。

例如,攻击者然后可以更改cookie对象并赋予自己管理员角色。

在这里弹出CSRF跨站请求伪造)之类的术语。基本上,服务器应用程序会生成一个令牌(称为CSRF令牌),并在每个请求中将其发送到客户端,以将其保存在表单的隐藏输入中。

每次提交表单时,它将一起发送令牌,服务器可以检查它是否已更改或不存在。如果发生这种情况,服务器将拒绝该请求。为了获得此令牌,攻击者必须使用JavaScript代码。但是,如果您的应用程序不支持CORS,则攻击者将束手无策,并且消除了威胁。

同样,Node有一些出色的中间件软件包可以为您提供帮助,例如最著名的csurf之一。在不到2分钟的时间内,您就可以安然无sound。

记录和监控不足

这个项目不言自明。之前我们已经讨论过Splunk,但这只是可用选项方面的冰山一角。

大量不同的工具(甚至可以集成和相互交谈)提供了完美的层,可以基于信息来增强系统的保护。

信息对于分析和检测应用程序可能的入侵和漏洞至关重要。您可以创建许多例程,这些例程根据系统的某些预定义行为执行。

日志说明您的应用程序内部正在发生的事情。因此,监控代表了一旦检测到任何错误都会发出的声音。

在这里,我们将不讨论特定的工具。这是一个开放的领域,您可以在其中找到许多出色的解决方案。

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » Node.js的安全性最佳实践

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论