如今,Web服务不断受到各种攻击。 因此,在项目生命周期的所有阶段都要牢记安全性。 该材料的作者(我们今天将其翻译发表
于此)在GitHub上维护了一个
存储库 ,其中包含约80条建议,以保护在Node.js平台上运行的应用程序的安全。 该材料基于许多安全性出版物,其中包含关于Node.js的二十多条建议和一些常规技巧。 此外,此材料涵盖了OWASP项目列表中的前10个漏洞。

1.使用lint的规则,旨在检查代码的安全性
推荐建议
在开发期间,请为
linter使用面向安全的插件,例如
eslint-plugin-security 。 这样,您可以在编写适当的代码时及早发现漏洞和安全问题。 这种方法有助于发现程序安全性的弱点。 其中包括
eval
命令的使用,子进程的调用,模块的导入以及与字符串文字不同的东西(例如,根据用户传输到服务器的数据形成的某个字符串)传输到相应的命令。
→
这是关于短绒规则的有用材料
亚当·鲍德温 (
Adam Baldwin )关于棉绒的说法如下:“棉绒不应该只是一种严格遵循有关所用空格数,分号和eval命令使用规则的工具。 ESLint为开发人员提供了一个强大的平台,可以检测并消除代码中的各种潜在危险模式。 例如,我们谈论的是正则表达式,检查用户输入等。 我相信,lint为关心安全问题的开发人员提供了一个值得关注的强大新工具。”
可能的问题
在开发过程中看似轻微的安全漏洞正在变成生产中的严重漏洞。 此外,如果所有项目开发人员在使用代码时未遵循统一的安全规则,则可能导致其中的漏洞,或者例如导致机密数据渗透到公共存储库中。
2.限制同时服务器请求的数量
推荐建议
DoS攻击在网络犯罪分子中非常流行;进行攻击相对容易。 您可以实施一个系统,以使用外部服务(例如云负载平衡器,云防火墙,nginx服务器)来限制对应用程序的请求数量,或者对于不重要的小型应用程序,可以使用中间件来限制请求数量,例如
快递费率-极限→
这是有关系统实施
的材料,用于限制对服务器的请求频率
可能的问题
没有提供用于限制同时请求数量的系统的应用程序可能会受到攻击,这将导致其失败。 这体现在以下事实中:此类应用程序的用户要么会难以使用它,要么根本无法与它进行交互。
3.从配置文件中删除机密信息或对其进行加密
推荐建议
切勿将敏感数据以纯文本格式存储在配置文件或代码中。 相反,请使用敏感的数据管理系统(例如Vault产品或Kubernetes / Docker Secrets系统),或使用环境变量来存储此类数据。 版本控制系统中存储的机密数据必须加密,必须采取措施安全存储和使用它们。 在这些措施中,包括动态密钥的使用,密码到期日期的使用,安全审核等。 在提交之前或在将其发送到存储库之前,请使用系统来验证代码,以防止将敏感数据意外发送到公共存储库。
→
这里是有关管理敏感数据的材料
可能的问题
即使将代码存储在封闭的存储库中,错误的一天也有可能将其公开发布。 此时,存储在其中的所有机密数据将成为公共领域。 结果,第三方使用代码对存储库的访问将无意间导致他们获得对与其关联的系统(数据库,API,服务等)的访问权。
4.防止代码注入漏洞
推荐建议
为了防止SQL / NoSQL注入和其他类似攻击,请始终使用ORM / ODM库或DBMS机制来进行数据清理,或支持命名或索引的参数化查询,并检查来自用户的内容。 切勿使用将某些值嵌入查询文本中的方法,仅使用模板JavaScript字符串或字符串连接,因为这种方法会使您的应用程序面临各种漏洞。 用于处理数据的Node.js的所有受人尊敬的库(例如
Sequelize ,
Knex和mongoose )都包含内置的保护措施,以防止
注入代码。
→
这是使用ORM / ODM库防止注入
的材料
可能的问题
在使用NoSQL数据库(例如MongoDB)时引入运算符会在查询中使用从用户接收到的未经验证和未清除的数据,从而导致攻击。 如果在使用SQL数据库时未使用数据清理系统或ORM库,则可能导致SQL注入攻击的可能性,从而在应用程序中造成巨大的安全漏洞。
5.通过明确设置异常终止流程的条件来避免DoS攻击
推荐建议
发生未处理的错误时,Node进程崩溃。 但是,在许多反映Node最佳实践的建议中,即使截获并处理了错误,也建议终止进程。 例如,Express会在发生任何异步错误时崩溃-除非将路由包装在
catch
表达式中。 这一事实为攻击者提供了非常诱人的机会。 他们发现,当某个请求到达时,进程崩溃了,就开始向其发送此类请求。 没有建议可以一举解决这个问题,但是,有些技巧可以缓解它。 因此,由于未处理的错误,在过程结束时,您需要通知管理员,并给此类通知以最高优先级。 有必要检查请求中涉及到的过程,并避免由于意外或有意地错误地形成请求而导致过程异常终止的情况。 所有路由都必须包装在
catch
表达式中,并且必须对系统进行配置,这样,如果请求是错误的原因,则该过程不会崩溃(与全局应用程序级别发生的情况相反)。
可能的问题
让我们分析以下情况。 有许多Node.js应用程序。 如果我们开始向其发送带有空JSON作为请求正文的POST请求,会发生什么情况? 这将导致其中许多应用程序崩溃。
现在,如果我们要扮演网络罪犯的角色,以防止应用程序崩溃,那么足以继续向他们发送类似的请求了。
6.配置HTTP响应标头以提高项目安全性
推荐建议
应用程序应使用面向安全性的HTTP标头,以防止攻击者诉诸于跨站点脚本(XSS),点击劫持等常见攻击技术。 使用
头盔等特殊模块可轻松自定义标题。
→
这是使用安全头的材料
可能的问题
如果不使用安全的HTTP标头,攻击者将能够对您的应用程序的用户进行攻击,从而导致巨大的漏洞。
7.连续自动地检查项目中是否存在易受攻击的依赖项
推荐建议
在NPM生态系统中,具有许多依赖性的项目非常普遍。 鉴于发现了新的漏洞,应始终控制依赖性。 使用
npm audit ,
nsp或
snyk之类的工具来检测,监视和修复易受攻击的依赖项。 将这些工具嵌入到您的持续集成系统中。 这将使您能够在脆弱的依赖项投入生产之前对其进行检测。
→
这里是关于项目依赖安全性的材料
可能的问题
攻击者可以确定项目中使用的Web框架,并对所有已知漏洞进行攻击。
8.尽量不要使用标准的Node.js加密模块进行密码处理,而应使用Bcrypt
推荐建议
密码或其他敏感数据(例如API密钥)必须通过使用“盐”(例如Bcrypt)的密码功能进行处理来存储。 出于安全和性能方面的考虑,值得使用完全类似的东西,而不是标准的Node.js
crypto
模块。
→
这是关于Bcrypt的资料
可能的问题
密码或某些机密数据在未采取适当措施保护它们的情况下很容易受到蛮力攻击和字典攻击,从而导致此类数据的泄露。
9.在发送给用户的HTML,JS和CSS数据中使用字符转义系统
推荐建议
如果某些数据是从不受信任的来源发送到用户的浏览器的,那么即使仅显示这些数据,这些数据也可以是可以执行的代码。 这通常称为跨站点脚本(XSS)。 您可以使用处理数据的特殊库来减少发生此类攻击的风险,使数据无法执行。 这称为编码或屏蔽数据。
→
这是关于屏蔽输出的材料
可能的问题
如果您不关心数据屏蔽,例如,攻击者可以在数据库中保存恶意的JavaScript代码,这些代码可以不更改地传输给客户端并启动。
10.检查传入服务器的JSON数据
推荐建议
控制传入请求的正文内容,检查它们是否与您期望在此类请求中看到的内容相对应。 如果请求看起来不符合预期,请快速停止处理。 为了避免为每个路由编写请求验证代码的耗时操作,可以使用轻量级JSON工具进行数据验证,例如
jsonschema或
joi 。
→
这是检查传入的JSON数据
的材料
可能的问题
如果服务器在没有彻底检查请求的情况下直接接受任何请求,则将大大增加应用程序的攻击面,并激发攻击者尝试查找导致系统“崩溃”的许多请求。
11.维护列入黑名单的JWT令牌
推荐建议
使用JWT令牌时(例如,如果您使用
Passport.js ),默认情况下,没有标准的机制来撤销已发布的令牌的系统访问特权。 即使您发现某个用户正在执行明显异常的操作,只要拥有有效的令牌,就无法通过令牌机制阻止其访问系统。 通过实施不受信任令牌的黑名单可以缓解此问题,该令牌的验证是在每个请求时执行的。
→
这是有关列入黑名单的JWT令牌
的材料
可能的问题
落入错误手中的令牌可能会被攻击者使用。 他将能够访问该应用程序并模拟普通用户-令牌的所有者。
12.限制登录尝试次数
推荐建议
在基于express的应用程序中,为了防止暴力攻击和字典攻击,值得使用适当的中间件,例如
express-brute 。 同样,您需要保护关键路由,例如
/admin
或
/login
。 保护应基于对查询属性(例如查询中使用的用户名)或其他标识符(例如查询主体参数)的分析。
→
这是限制登录尝试次数
的材料
可能的问题
如果该应用程序不限制登录尝试的次数,则攻击者可以自动向您的系统发送无限数量的登录请求,例如,尝试获取对特权帐户的访问权限。
13.以非root用户身份运行Node.js
推荐建议
一个极端常见的情况是Node.js以具有无限特权的root用户身份运行。 例如,这就是默认情况下如何在Docker容器中配置所有内容的方式。 建议您创建一个没有root特权的用户,或者将其嵌入Docker映像中,或者通过使用
-u username
标志调用容器来代表该用户启动该过程。
→
这是有关以非root用户身份启动Node.js
的材料
可能的问题
如果以root用户帐户运行Node.js,则能够在服务器上运行脚本的攻击者在本地计算机上获得无限可能。 假设它可以更改
iptable
设置并将流量重定向到其自己的计算机。
14.限制使用反向代理服务器或中间件在请求中传输的数据量
推荐建议
请求主体中的数据量越大,单线程服务器处理此类请求的难度就越大。 大型请求的使用使攻击者有机会向服务器充斥不必要的工作,而无需发送大量请求(即,不执行DoS / DDoS攻击)。 您可以通过限制某个边界系统(在防火墙或负载均衡器上)的传入请求的正文大小,或将
正文分析器表达设置为仅接收包含少量数据的数据包,来降低此类攻击的风险。
→
这是有关限制请求中传输的数据量的材料
可能的问题
如果您不限制请求中传输的数据量,则攻击者可以通过处理大型请求来加载应用程序。 目前,它将无法解决其设计任务。 这会导致性能下降,并使应用程序容易受到DoS攻击。
15.避免在JavaScript中使用eval函数
推荐建议
eval
函数之所以邪恶,是因为它允许您执行程序执行期间传递给它的任意JS代码。 而且,绝非仅此代码会降低应用程序速度。 此功能带来严重的安全风险,因为攻击者发送到服务器的恶意JS代码可能会进入其中。
另外,您应该避免使用
new Function
构造函数。
setTimeout
和
setInterval
函数无需传递动态生成的JS代码。
→
这是关于评估的内容
可能的问题
如果有人找到了以文本,
eval
函数或其他类似的JS引擎形式传输恶意JS代码的方法,则他将拥有对该页面的完全访问权限,以及使用JavaScript可以完成的所有操作。 此漏洞通常与XSS攻击相关。
16.不要用恶意正则表达式重载单线程Node.js应用程序
推荐建议
尽管很方便,但是正则表达式对JavaScript应用程序尤其是对Node.js平台构成了威胁。 用正则表达式处理来自用户的内容会给处理器带来巨大的负担。 例如,处理正则表达式的效率可能非常低,以至于检查十个字会阻塞事件循环几秒钟,并使处理器超负荷运行。 因此,最好使用第三方程序包来检查字符串数据,例如
validateator.js ,而不是编写自己的正则表达式。 您可以使用
safe-regex软件包来检测易受攻击的
regex模式。
→
这是反恶意软件正则表达式材料
可能的问题
编写不正确的正则表达式可能会受到特殊的DoS攻击,在此期间,事件循环被完全阻止。 例如,在2017年11月,人们发现热门
moment
套餐很容易受到此类攻击。
17.避免使用变量加载模块
推荐建议
基于可以基于用户数据来设置此参数的注意事项,避免导入其路径被指定为参数的文件。 该规则可以扩展为包括此处,并且通常包括对文件的访问(使用
fs.readFile()
),以及使用从用户处接收到的参数对其他任何重要资源的访问。 使用
eslint-plugin-security可以很早地检测到这种不安全的模式。
→
这是关于安全模块装载的材料
可能的问题
攻击者发送到服务器的数据可能处于负责导入某些文件的设置中,其中可能是先前已上传到服务器的恶意文件。 此数据还可以用于访问计算机上已经存在的系统文件。
18.在沙箱中运行不安全的代码
推荐建议
, (, ), «», . , (
cluster.fork()
), npm-, .
→
, , . — , , , .
19.
推荐建议
, , . , , , .
child_process.execFile
, , , , , .
→
,
, , , , .
20.
推荐建议
express, , . , , ,
Error
( ). , , , - , .
→
, , , , , , .
21. npm Yarn
推荐建议
, -, (MFA, multi-factor authentication). npm Yarn , . , , , . , . , , npm, .
, ?
eslint, .
22. ,
推荐建议
- . , — , - . , ,
X-Powered-By
, , . , ( , , Node.js express).
→
-
- . , , -, — . .
23.
, . — , Node.js.
,
OWASP .
- root- .
- ( SSH-).
- , , , . OWASP, .
- , . , .
- OAuth, OpenID, . Basic Authentication.
- . , ( — ), X , Y .
- — , — . , .
- , , . ( — GitHub, AWS, Jenkins, ).
总结
. , Node.js-.
亲爱的读者们! -, ?
