【译】Nodejs应用安全备忘录

本人的博客http://www.wjs.photo/,感兴趣的能够看看哦,基于NodeJs框架ThinkJs前端

本文翻译自 www.risingstack.com ,并不是逐字逐句的翻译,有错误的地方请指出,谢谢啦
应用程序的安全就像是你房间里忽然出现一只大象,那么明显,可是写代码的同窗仍是会忽略。也都认为应用程序的安全很是重要可是却不多有时间认真对待,毕竟咱们有那么多bug要改(坏笑)。因此咱们整理了一个NodeJs应用安全备忘录,以帮助你在部署启动NodeJs应用程序的时候进行安全检查。固然,这些项目大部分是通用的,适用于全部的语言和框架而不只仅是Node.js。可是本文具体还涉及到一些Node.js的工具。感兴趣的同窗也能够查看个人介绍Node.js的安全性的博客。node


配置管理(Configuration Management)

HTTP安全头部

Strict-Transport-Security:强制经过(SSL/TLS上的HTTP)链接到服务器
X-Frame-Options:提供阻止点击挟持攻击
X-XSS-Protection:启用浏览器内置的跨站点脚本(XSS)筛选器
X-Content-Type-Options:防止浏览器从MIME探查从声明内容类型的响应
Content-Security-Policy:防止各类攻击,包括跨站点脚本和其余跨网站注射
在Express中,咱们能够很容易用helmet来设置这些头部:nginx

var express = require('express'); 
var helmet = require('helmet');
var app = express();
app.use(helmet());

固然,在koa框架中也可使用:传送门
这些头部不仅是能够放在代码中,也能够配置在web服务器中(Apache、nginx),这样也就省了改动程序代码git

# nginx.conf
    add_header X-Frame-Options SAMEORIGIN; 
    add_header X-Content-Type-Options nosniff; 
    add_header X-XSS-Protection "1; mode=block"; 
    add_header Content-Security-Policy "default-src 'self'";

nginx服务器的配置也能够参考:这里github

客户端的敏感数据

在部署前端应用程序时要确保不会将秘密的API公开,公开的API会被任何人访问
虽然没有好的自动检查的方法,但有两个注意点能够减轻因为意外而暴露敏感数据的风险
1.检查使用的请求
2.常规的代码审查web

身份验证

Brute Force Protection(暴力攻击防御)

暴力破解(也称穷举法),即将密码进行逐个推算直到找到真正的密码,而后在web应用程序中登陆。
为了防止应用程序受到暴力破解的攻击,应用程序最好要有密码错误允许次数机制,在NodeJs中,你可使用:ratelimiter正则表达式

var limit = new Limiter({ id: email, db: db }); 
      limit.get(function(err, limit) { });

固然啦,你也能够将他包装成一个中间件,就能够放在应用程序中,不管是Express框架仍是Koa框都有厉害的中间件,在koa框架中,他多是这个样子:redis

var ratelimit = require('koa-ratelimit');  
  var redis = require('redis');  var koa = require('koa');  
  var app = koa(); 
  var emailBasedRatelimit = ratelimit({
  db: redis.createClient(),   
  duration: 60000,   
  max: 10,   
  id: function (context) {     
  return context.body.email;   
  } }); 
  var ipBasedRatelimit = ratelimit({
  db: redis.createClient(),   
  duration: 60000,   
  max: 10,   
  id: function (context) {     
   return context.ip;   
   } 
   }); 
   app.post('/login', ipBasedRatelimit, emailBasedRatelimit, handleLogin);

咱们在这里作的是有限的用户在给定的时间里(60000毫秒)能够出错多少次(10次),这样咱们的程序能够减轻被暴力破解的风险。不过这些配置必须为给定的应用,不要直接复制粘贴他们。算法

会话管理

安全使用Cookie的重要性不能被低估:尤为是在动态Web应用程序,这就须要保持整个无状态协议状态,如HTTP
Cookie的属性列表
secure —这个属性设置为true时是告诉浏览器若是正在经过HTTPS发送请求,只发送cookie。
HttpOnly—-若是Cookie中设置了这个属性,那么经过程序(JS脚本、Applet等)将没法读取到Cookie信息,能够有效的用来防止诸如跨站点脚本攻击
限制cookie的做用范围
Domain--这个属性是用来比较中被请求的URL服务器的域。若是域匹配,或者若是它是一个子域,则路径属性将下一个检查。
path--除了Domain,该Cookie有效期能够指定URL路径。若是域名和路径匹配,那么该cookie将被请求发送。
expires --这个属性是用来设置Cookie的到期时间,由于该cookie不会过时,直到超出设定的日期sql

在NodeJs中,能够很容易的建立cookie, 经过cookies或者cookie-session

var cookieSession = require('cookie-session');  
 var express = require('express'); var app = express(); 
 app.use(cookieSession({    name: 'session',   
 keys: [     process.env.COOKIE_KEY1,     process.env.COOKIE_KEY2   ] }));
 app.use(function (req, res, next) {    
     var n = req.session.views || 0;   
     req.session.views = n++;    
     res.end(n + ' views'); 
    }); 
 app.listen(3000);

(这个例子是取自cookie的会话模块文档)。

CSRF(跨站请求伪造)

跨站请求伪造一种挟持用户在当前已登陆的web应用程序上执行非本身操做的攻击方法,这种攻击专门针对更改请求,而不是窃取数据,由于攻击者也无法比见到伪造请求的响应
在NodeJs中要减轻这种攻击,可使用 [csrf] (https://www.npmjs.com/package...块,因为这个比较底层,也有不一样的框架包装好的,这个例子是csurf模块,用于CSRF保护明文中间件
在路由中,你须要作的是:

var cookieParser = require('cookie-parser');   
 var csrf = require('csurf');  
 var bodyParser = require('body-parser');         
 var express = require('express'); 
 // setup route middlewares 
 var csrfProtection = csrf({ cookie: true });  
 var parseForm = bodyParser.urlencoded({ extended: false }); 
 // create express app 
 var app = express(); 
 // we need this because "cookie" is true in csrfProtection  
 app.use(cookieParser()); 
 app.get('/form', csrfProtection, function(req, res) {  
 // pass the csrfToken to the view   
   res.render('send', { csrfToken: req.csrfToken() }); }); 
   app.post('/process', parseForm, csrfProtection, function(req, res) {    
     res.send('data is being processed');
    });

而后在视图层:

<form action="/process" method="POST">    
  <input type="hidden" name="_csrf" value="{{csrfToken}}">Favorite color: 
  <input type="text" name="favoriteColor">
  <button type="submit">Submit</button>
 </form>

(这个例子是取自csurf模块文档)。

数据验证

XSS有两个类似,但不一样类型的攻击防范。一个是跨站脚本的反射版本,另外一个是存储跨站脚本。
反射式跨站脚本,经过注入发送带有恶意脚本代码参数的URL,当URL地址被打开时,特有的恶意代码参数被HTML解析、执行。
存储跨站脚本,指的是恶意脚本代码被存储进被攻击的数据库,当其余用户正常浏览网页时,站点从数据库中读取了非法用户存入非法数据,恶意脚本代码被执行。
为了抵御这类攻击,确保你过滤或者清理用户输入

SQL注入

SQL注入是由用户输入部分或完整的SQL查询的注入。它能够读取敏感信息。

select title, author from books where id=$id

在这个实例代码中,参数$id若是用户输入的是2 or 1=1?,那查询变为以下:

select title, author from books where id=2 or 1=1

防范这类攻击的最简单的方法是使用参数化查询或准备好的语句
SqlMap是一个开源的渗透测试工具,它能够自动检测并利用SQL注入漏洞和接管数据库服务器的过程。使用此工具来测试SQL注入漏洞的应用程序。

命令注入

命令注入是由攻击者向远程的Web服务器上运行的系统命令的技术。用这种方法攻击者可能甚至获得的系统的密码。
在实际开发中,若是你有一个网址,如:

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进行保护。现在高档的密码一般使用,在服务器配置错误能够用来强制使用弱密码 - 或者在最坏的状况没有加密。
你必须测试:

  • 密码,钥匙和从新谈判的配置是否正确

  • 证书有效期

使用工具NMAPsslyze能够很容易扫描出来
检查证书信息

nmap --script ssl-cert,ssl-enum-ciphers -p 443,465,993,995 www.example.com

利用sslyze能够测试SSL / TLS的漏洞

./sslyze.py --regular example.com:443

HSTS

在配置管理的一部分,咱们使用这个briefly - Strict-Transport-Security 头强制执行安全(基于SSL的HTTP / TLS)链接到服务器上。就拿从Twitter下面的例子:

strict-transport-security:max-age=631138519

这里max-age定义为秒,浏览器自动将全部的HTTP请求转换为HTTPS的数量。
它的测试是很是简单的:

curl -s -D- https://twitter.com/ | grep -i Strict

拒绝服务

账户锁定

账户锁定是减小暴力攻击的方法。这就意味着,若是帐户屡次登陆失败,就让这个帐户在必定时间内(最初也能够是一两分钟,而后就能够成倍增长)锁定。
这能够保护应用程序不被攻击。

正则表达式

大多数正则表达式可能会致使攻击者的破解工做变得缓慢和低效。这些的正则表达式被称为邪恶的正则表达式:

  • 与重复分组

  • 里面的重复组

    • 重复

    • 轮换具备重叠

([a-zA-Z]+)*,(a+)+或者(a|a?)+是全部弱势的正则表达式做为一个简单的输入同样aaaaaaaaaaaaaaaaaaaaaaaa!会致使重计算。每增长一个a,时间就会翻倍。

在NodeJs中,若是要检查正则表达式,你能够safe-regex

$ node safe.js '(beep|boop)*' true  $ node safe.js '(a+){10}' false

错误处理

错误代码,堆栈跟踪

不一样的错误状况的应用程序可能会泄漏对底层基础架构的敏感细节,如:X-Powered-By:Express。
栈跟踪不被视为本身的漏洞,但他们每每多是吸引的攻击者的信息。提供了调试信息和产生错误操做的结果都被认为是很差的作法。应该用日志记录下来,而不是显示给用户。

NPM

NPM有不少包提供给你们使用,可是这也是有代价的:应该好好检查你须要为你的应用程序是什么。也许你使用以后可能含有重要的安全问题。

The Node Security Platform

不过幸运的是,有一个伟大的工具--The Node Security Platform,能够检查使用的模块为已知的漏洞。

npm i nsp -g  # either audit the shrinkwrap nsp audit-shrinkwrap  # or the package.json nsp audit-package

你还可使用requireSafe

SnykSnyk

SnykSnyk相似于The Node Security Platform,但他的目的是提供一种工具,不能只检测,只是在代码库修复安全相关的问题。
更多信息你能够看看snyk.io
本人的博客http://www.wjs.photo/,感兴趣的能够看看哦,基于NodeJs框架ThinkJs

相关文章
相关标签/搜索