当前位置: 首页 > 后端技术 > Node.js

【翻译】Nodejs应用安全备忘录

时间:2023-04-03 12:22:23 Node.js

我的博客http://www.wjs.photo/,有兴趣的可以看看,基于NodeJs框架的ThinkJs本文翻译自www.risingstack.com,不是逐字翻译,如有错误请指出,谢谢。应用程序的安全性就像一头大象突然出现在你的房间里。这么明显,但是写代码的同学还是会忽略。他们也认为应用程序安全非常重要,但很少有时间认真对待它,毕竟我们有那么多错误要修复(傻笑)。所以我们整理了一份NodeJs应用安全备忘录,帮助大家在部署和启动NodeJs应用时进行安全检查。当然,这些项目大部分都是通用的,适用于所有语言和框架,而不仅仅是Node.js。但是这篇文章还专门涉及到一些Node.js工具。有兴趣的同学也可以看看我介绍Node.js安全的博客。配置管理(ConfigurationManagement)HTTP安全头Strict-Transport-Security:强制通过(HTTPoverSSL/TLS)连接服务器X-Frame-Options:提供防止点击劫持攻击X-XSS-Protection:启用浏览器内置-在跨站点脚本(XSS)过滤器中X-Content-Type-Options:防止浏览器从声明的内容类型中嗅探MIME响应Content-Security-Policy:防止各种攻击,包括跨站点脚本和其他跨站点注入在Express中,我们可以使用helmet轻松设置这些标头:varexpress=require('express');varhelmet=require('头盔');varapp=express();app.use(头盔());当然也可以用在koa框架中:入口的headers不仅可以放在代码中,还可以配置在web服务器(Apache、nginx)中,这样就省去了改程序代码#nginx.confadd_headerX-Frame-OptionsSAMEORIGIN;add_headerX-Content-Type-Optionsnosniff;add_headerX-XSS-Protection"1;mode=block";add_headerContent-Security-Policy"default-src'self'";nginx服务器配置也可以参考:在客户端部署敏感数据的前端应用时,保证secretAPI不会对外公开,??公开的API任何人都可以访问。虽然没有很好的自动检测方法,但有两点可以缓解。意外暴露敏感数据风险1.检查使用过的请求2.定期代码审查认证BruteForceProtection(蛮力保护)暴力破解(也称穷举法),就是逐一计算密码直到找到真实密码,然后登录Web应用程序。为了防止应用程序被暴力破解攻击,应用程序应该有密码容错机制。在NodeJs中,你可以使用:ratelimitervarlimit=newLimiter({id:email,db:db});限制。得到(函数(错误,限制){});当然,你也可以把它包装成一个中间件,放在应用程序中。Express框架和Koa框架都有强大的中间件。在koa框架中,它可能看起来像这样:varratelimit=require('koa-ratelimit');varredis=require('redis');varkoa=require('koa');varapp=koa();varemailBasedRatelimit=ratelimit({db:redis.createClient(),duration:60000,max:10,id:function(context){returncontext.body.email;}});varipBasedRatelimit=ratelimit({db:redis.createClient(),duration:60000,max:10,id:function(context){returncontext.ip;}});app.post('/login',ipBasedRatelimit,emailBasedRatelimit,handleLogin);我们在这里所做的是限制用户在给定时间内(60000毫秒)可以犯错的次数(10次),以便我们的程序可以减轻被暴力破解的风险。但是,这些配置必须针对给定的应用程序,不要直接复制和粘贴它们。不能低估会话管理和安全使用cookie的重要性:尤其是在动态Web应用程序中,它需要在整个无状态协议(如HTTP)中维护状态。Cookie的属性列表:secure-当此属性设置为true时,它??告诉浏览器仅在通过HTTPS发送请求时才发送cookie。HttpOnly——如果在cookie中设置该属性,则cookie信息将不会被程序(JS脚本、Applets等)读取,可有效用于防止跨站脚本攻击,如限制cookie的范围cookie域——此属性是比较中请求的URL服务器的域。如果域匹配,或者它是子域,则接下来将检查路径属性。path--除了Domain,cookie有效期可以指定URL路径。如果域名和路径匹配,则cookie将与请求一起发送。expires--该属性用于设置cookie的过期时间,因为cookie要到超过设置的日期才会过期在NodeJs中,可以很方便的创建cookie,通过cookies或者cookie-sessionvarcookieSession=require('cookie-会议');varexpress=require('快递');varapp=express();app.use(cookieSession({name:'session',keys:[process.env.COOKIE_KEY1,process.env.COOKIE_KEY2]}));app.use(function(req,res,next){varn=req.session.views||0;req.session.views=n++;res.end(n+'views');});app.listen(3000);(此示例取自cookie的会话模块文档)。CSRF(Cross-siterequestforgery)跨站请求伪造是一种劫持用户在当前登录的web应用程序上执行非自己操作的攻击方式。Fabi看到在NodeJs中对伪造请求的响应可以缓解这种攻击,可以使用[csrf](https://www.npmjs.com/package...block,因为这个比较底层,还有不同的框架对其进行封装是的,这个例子是csurf模块,用于路由中的CSRF保护明文中间件,你需要做的是:varcookieParser=require('cookie-parser');varcsrf=require('csurf');varbodyParser=require('body-parser');varexpress=require('express');//设置路由中间件varcsrfProtection=csrf({cookie:true});varparseForm=bodyParser.urlencoded({extended:false});//创建expressappvarapp=express();//我们需要这个,因为csrfProtection中的“cookie”为真app.use(cookieParser());app.get('/form',csrfProtection,function(req,res){//将csrfToken传递给视图res.render('send',{csrfToken:req.csrfToken()});});app.post('/process',parseForm,csrfProtection,function(req,res){res.send('正在处理数据');});然后在视图层:最喜欢的颜色:提交(本例取自csurf模块文档)数据验证XSS有两种相似但不同类型的攻击防御。一种是反射型XSS,一种是存储型XSS。反射式跨站脚本通过注入发送带有恶意脚本代码参数的URL。打开URL地址时,特有的恶意代码参数被HTML解析执行。存储跨站脚本是指恶意脚本代码存储在被攻击的数据库中。当其他用户正常浏览网页时,该站点从数据库中读取非法用户存储的非法数据,执行恶意脚本代码。要防御此类攻击,请确保过滤或清理用户输入。SQL注入SQL注入是注入用户输入的部分或完整的SQL查询。它可以读取敏感信息。selecttitle,authorfrombookswhereid=$id在这个示例代码中,如果用户输入的参数$id是2还是1=1?,则查询变为:selecttitle,authorfrombookswhereid=2or1=1防止此类攻击的最简单方法是使用参数化查询或准备语句。SqlMap是一种开源渗透测试工具,可自动执行检测和利用SQL注入漏洞以及接管数据库服务器的过程。使用此工具测试应用程序是否存在SQL注入漏洞。命令注入命令注入是一种攻击者将系统命令发送到远程Web服务器以运行的技术。使用这种方法,攻击者甚至可能获得系统的密码。在实际开发中,如果你有这样一个URL:https://example.com/downloads?file=user1.txt它可以变成:https://example.com/downloads?file=%3Bcat%20/etc/passwd%3B在此示例中变为分号,因此可以运行多个系统命令。要防御此类攻击,请确保始终过滤或清理用户输入。另外,在Node.js中,我们可以这样检测:child_process.exec('ls',function(err,data){console.log(data);});child_process.exec创建子线程调用执行/bin/sh,所以是bash的解释,不是程序启动。当用户输入传递给此方法时,它将被执行并显示目录中的所有文件。攻击者注入了一个新命令。为了防止被攻击,可以使用child_process.execFile安全传输SSL版本、算法、密钥长度。由于HTTP是一种明文协议,如果通过SSL/TLS隧道,则称为HTTPS进行保护。如今,高端密码很普遍,服务器配置错误可用于强制执行弱密码——或者在最坏的情况下不加密。您必须测试:密码、密钥和重新协商的配置是否正确?证书有效期可以使用工具nmap和sslyze轻松扫描查看证书信息nmap--scriptssl-cert,ssl-enum-ciphers-p443,465,993,995www.example.com使用sslyze可以测试SSL/TLS漏洞。/sslyze.py--regularexample.com:443HSTS作为配置管理的一部分,我们简要地使用这个-Strict-Transport-Security标头来加强安全性(HTTP/TLSoverSSL)连接到服务器。以下面的例子来自Twitter:strict-transport-security:max-age=631138519这里的max-age定义为浏览器自动将所有HTTP请求转换为HTTPS的秒数。它的测试非常简单:curl-s-D-https://twitter.com/|grep-i严格拒绝服务帐户锁定帐户锁定是一种减少暴力攻击的方法。这意味着如果该帐户多次登录失败,该帐户将被锁定一段时间(最初可以是一两分钟,然后可以成倍增加)。这可以保护应用程序免受攻击。正则表达式大多数正则表达式会导致攻击者的破解工作缓慢且效率低下。这些正则表达式被称为邪恶的正则表达式:与重复组重叠重复旋转在重复组内([a-zA-Z]+)*,(a+)+or(a|a?)+是作为简单输入的所有弱正则表达式喜欢啊啊啊啊啊啊啊啊啊啊!将导致重新计算。每增加一个a,时间就会加倍。在NodeJs中,如果要检查正则表达式,可以safe-regex$nodesafe.js'(beep|boop)*'true$nodesafe.js'(a+){10}'false错误处理错误码,堆栈跟踪不同错误情况的应用程序可能会泄露有关底层基础设施的敏感细节,例如:X-Powered-By:Express。堆栈跟踪本身不被视为漏洞,但它们通常是吸引攻击者的信息。提供调试信息并产生错误操作的结果被认为是不好的做法。应该记录下来,而不是显示给用户。NPMNPM有很多包供大家使用,但这是有代价的:你应该仔细检查你的应用程序需要什么。也许在您使用之后它可能包含重要的安全问题。NodeSecurityPlatform但幸运的是,有一个很棒的工具——NodeSecurityPlatform,它可以检查使用的模块是否存在已知漏洞。npminsp-g#审计shrinkwrapnspaudit-shrinkwrap#或package.jsonnspaudit-package你也可以使用requireSafe。SnykSnykSnykSnyk类似于TheNodeSecurityPlatform,但他的目的是提供一个工具,不仅可以检测,还可以修复代码库中与安全相关的问题。更多信息可以看看snyk.io自己的博客http://www.wjs.photo/,有兴趣的可以看看,基于NodeJs框架ThinkJs