《Aquasec翻译计划05:Node.js安全实践指南》

发表时间: 2023-10-28 19:12

【应用安全词条】

Node.js是一个用于在服务器端执行JavaScript代码的开源开发平台。详细了解Node.js安全最佳实践。

什么是Node.js?

Node.js(Node)是用于在服务器端执行JavaScript代码的开源开发平台。Node适用于需要从浏览器到服务器建立持久连接的应用程序,通常用于实时应用程序,如聊天、新闻提要和网络推送通知。

Node.js旨在运行在专用HTTP服务器上,并一次性使用单个线程和单个进程。基于Node平台编写的代码不遵循接收、处理、发送、等待、接收的传统模型。相反,Node会连续处理传入的请求,在没有等待响应的情况下依次发出小请求。

这与主流模型有所不同,主流模型运行更大的、更复杂的进程,并并发运行多个线程,每个线程都在等待适当的响应之后再继续执行。

最常见的Node.js安全攻击和漏洞

代码注入 编写安全应用程序是开发人员的主要责任。但是,在使用开源包时,不能完全保证代码库的安全性。代码注入是指攻击者将代码注入系统并强制应用程序例程执行它的任何攻击。攻击者利用处理不当和不受信任的数据来深入了解您的代码库。

这种安全风险的一个常见原因是输入和输出数据验证不当。SQL注入是在软件开发中最常遇到的一种重复代码注入攻击。在这里,攻击者使用恶意SQL代码来操纵后台数据库,并访问通常不可见的敏感信息。

默认Cookie名称

Cookie帮助网站或Web应用程序识别特定的用户,因为任何针对Web应用程序的操作都会作为cookie存储在底层基础设施中。电子商务网站中的购物车是最常见的cookies示例。Cookie会记住您在网站上选择的项目,当您转到结账页面时,购物车将显示这些项目。

然而,问题在于开发人员选择了默认的cookie名称而不是根据需要自定义它们。由于攻击者知道默认的cookie名称,因此他们可能会基于此信息毫不费力地攻击和访问用户输入。

暴力破解攻击

暴力破解攻击是您在任何Node.js安全清单中都会发现的最常发生的攻击或风险之一。攻击者生成随机密码,并尝试在Web应用程序的登录端点上实现它们以访问关键信息。暴力破解就是生成数百万种组合,直到找到正确的Web应用程序密码为止。为了防止暴力破解攻击,您需要加强Node.js应用程序的身份验证机制。此外,您也可以限制来自同一IP的登录尝试次数,以应对此类高风险情况,并使用bcrypt.js保护存储在数据库中的密码。

跨站脚本(XSS)攻击

跨站脚本攻击是在处理Node.js Web应用程序开发时需要应对的关键威胁。跨站脚本(XSS)允许攻击者向Web应用程序注入缺少主机名返回DNS的输入验证引起的客户端脚本,其中包括调整后的JavaScript代码。

攻击者可以使用XSS向最终用户发送恶意脚本,而最终用户的浏览器无法确定代码库的信任度。结果,默认情况下他们会执行它,攻击者可以访问任何饼干、会话令牌或其他敏感信息。这些脚本还可以重写任何HTML页面的内容,从而使XSS变得非常致命。

跨站伪造请求(CSRF)

CSRF是一种会话劫持形式,其中攻击者强迫真实用户在其已身份验证的应用程序上执行恶意操作。在CSRF攻击中,攻击者劫持真实用户的会话,从而绕过针对非用户的安全部分。

CSRF攻击者的首要目的是使用社会工程技术(如发送消息或电子邮件)更改应用程序的状态。 CSRF攻击会对Node.js应用程序造成重大损害,因为它迫使用户更改其电子邮件地址并转账。对于管理员级别的用户来说,CSRF攻击也会破坏整个Web应用程序的安全性,必须加以缓解。

利用和恶意软件包

曾发生多起涉及Node.js JavaScript平台包管理器(NPM)托管的供应链妥协事件,其中要么直接被破坏以分发恶意软件,要么只是模仿流行合法软件包创建。

通过破坏开发人员使用的流行软件包,可以直接大规模放大恶意代码的传播。可以通过利用混淆的依赖关系、窃取弱凭据、利用漏洞访问目标代码或使用开发人员废弃的软件包名称来完成这一点。

Node.js安全最佳实践 实施强大的身份验证

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

如果您希望坚持使用本地Node.js身份验证解决方案,则需要注意几件事。创建密码时,请不要使用Node.js内置加密库;使用Bcrypt或Scrypt。确保限制失败的登录尝试,并且不要告诉用户是用户名还是密码错误。相反,返回通用的“凭据错误”错误。还需要适当会话管理策略。并且一定要实施双因素身份验证。如果正确执行,它可以大大提高应用程序的安全性。您可以使用像node-2fa或speakeasy这样的模块来实现。

避免揭示太多错误

下一个要注意的问题是错误处理。这里有一些注意事项。首先,不要让客户知道详细信息,即不要将完整的错误对象返回给客户端。它可以包含您不想公开的信息,如路径、正在使用的另一个库,甚至可能是秘密。其次,使用catch子句包裹路由,并在引发错误的请求时不要让Node.js崩溃。这样可以防止攻击者找到会导致应用程序崩溃的恶意请求,并反复发送它们,使应用程序不断崩溃。

说到用恶意请求淹没Node.js应用程序,不要直接将其暴露给Internet。使用负载均衡器、云防火墙或nginx等前段组件。这样可以在到达Node.js应用程序之前限制DoS攻击。

使用捕获代码中漏洞的安全代码美化工器

代码美化工作者可以帮助开发人员在编译前识别各种代码问题。它们可以检测最常见的问题,并强制开发人员遵循最佳做法。

这些代码美化工作者有自己的规则,开发人员可以根据需求自定义。因此,在使用它们之前,开发人员必须启用有关安全漏洞检测的相关规则

服务器端日志记录和监控

使用一个好的日志记录库可以让开发人员获得更强大的功能来排查和监视活动。另一方面,日志记录不需要的日志或过多日志会影响应用程序的性能并消耗更多资源。因此,在生产环境中部署应用程序时,只应使用合理的日志记录级别。

结构化的日志消息对于人类和机器容易理解和阅读是很重要的。模糊的日志消息会导致开发人员之间产生误解。

以下示例说明了如何编写描述性日志消息。

错误描述:服务失败,无法工作

正确描述:由于磁盘空间不足,应用工作者服务失败,请确保有足够的磁盘空间并重新启动应用工作者服务。

此外,确保日志记录机制捕获所有相关信息很重要,包括IP地址、用户名、执行的操作等。

在应用程序日志中捕获或存储敏感信息不推荐。这是对PCI、GDPR等主要应用程序合规要求的违规行为。然而,在需要记录此类信息的情况下,建议在收集和写入日志之前对敏感信息进行掩码处理。