[译]Node.js平安清单

媒介

平安性,老是一个不可无视的题目。很多人都认可这点,然则却很少有人真的认真地看待它。所以我们列出了这个清单,让你在将你的运用布置到临盆环境来给万万用户运用之前,做一个平安搜检。

以下列出的平安项,大多都具有普适性,适用于除了Node.js外的种种语言和框架。然则,个中也包括一些用Node.js写的小东西。

设置治理

平安性相干的HTTP头

以下是一些平安性相干的HTTP头,你的站点应当设置它们:

  • Strict-Transport-Security:强迫运用平安衔接(SSL/TLS之上的HTTPS)来衔接到效劳器。

  • X-Frame-Options:供应关于“点击挟制”的庇护。

  • X-XSS-Protection:开启大多当代浏览器内建的关于跨站剧本进击(XSS)的过滤功用。

  • X-Content-Type-Options: 防备浏览器运用MIME-sniffing来肯定相应的范例,转而运用明白的content-type来肯定。

  • Content-Security-Policy:防备遭到跨站剧本进击以及其他跨站注入进击。

Node.js中,这些都能够经由过程运用Helmet模块轻松设置终了:

var express = require('express');  
var helmet = require('helmet');

var app = express();

app.use(helmet());  

Helmet在Koa中也能运用:koa-helmet

固然,在很多的架构中,这些头会在Web效劳器(Apache,nginx)的设置中设置,而不是在运用的代码中。假如是经由过程nginx设置,设置文件会类似于以下例子:

# 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设置

假如你想疾速确认你的网站是不是都设置这些HTTP头,你能够经由过程这个网站在线搜检:http://cyh.herokuapp.com/cyh

客户端的敏感数据

当布置前端运用时,确保不要在代码中暴露如密钥如许的敏感数据,这将能够被一切人看到。

当今并没有什么自动化检测它们的要领,然则照样有一些手腕能够用来削减不小心将敏感数据暴露在客户端的几率:

  • 运用pull request更新代码

  • 建立起code review机制

身份认证

关于暴力破解的庇护

暴力破解即体系地枚举一切能够的效果,并一一尝试,来找到准确答案。在web运用中,用户上岸就迥殊合适它发挥。

你能够经由过程限定用户的衔接频次来防备这类的进击。在Node.js中,你能够运用ratelimiter包。

var email = req.body.email;  
var limit = new Limiter({ id: email, db: db });

limit.get(function(err, limit) {

});

固然,你能够将它封装成一个中间件以供你的运用运用。ExpressKoa都已有现成的不错的中间件:

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);  

这里我们所做的,就是限定了在一段给定时候内,用户能够尝试上岸的次数 — 这削减用户暗码被暴力破解的风险。以上例子中的选项都是能够依据你的现实情形所转变的,所以不要简朴的复制粘贴它们。。

假如你想要测试你的效劳在这些场景下的表现,你能够运用hydra

Session治理

关于cookie的平安运用,其重要性是显而易见的。迥殊是关于动态的web运用,在如HTTP如许的无状况协定的之上,它们须要运用cookie来保持状况。

Cookie标示

以下是一个每一个cookie能够设置的属性的列表,以及它们的寄义:

  • secure – 这个属性通知浏览器,仅在要求是经由过程HTTPS传输时,才通报cookie。

  • HttpOnly – 设置这个属性将制止javascript剧本获取到这个cookie,这能够用来协助防备跨站剧本进击。

Cookie域

  • domain – 这个属性用来比较要求URL中效劳端的域名。假如域名婚配胜利,或这是其子域名,则继承搜检path属性。

  • path – 除了域名,cookie可用的URL途径也能够被指定。当域名和途径都婚配时,cookie才会随要求发送。

  • expires – 这个属性用来设置耐久化的cookie,当设置了它以后,cookie在指定的时候抵达之前都不会逾期。

Node.js中,你能够运用cookies包来轻松建立cookie。然则,它是较底层的。在建立运用时,你能够更像运用它的一些封装,如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-session模块的文档)

CSRF

跨站要求捏造(CSRF)是一种迫运用户在他们已登录的web运用中,实行一个并不是他们原意的操纵的进击手腕。这类进击常常用于那些会转变用户的状况的要求,一般它们并不盗取数据,因为进击者并不能看到相应的内容。

Node.js中,你能够运用csrf模块来紧张这类进击。它同样是异常底层的,你能够更喜好运用如csurf如许的Express中间件。

在路由层,能够会有以下代码:

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');
});

在展现层,你须要运用CSRF token

<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

以下是两品种似的,然则略有不同的进击体式格局,一种关于跨站剧本,而另一种则关于存储。

  • 非耐久化的XSS进击 在进击者向指定的URL的相应HTML中注入可实行的JavaScript代码时发作。

  • 耐久化的XSS进击 在运用存储未经过滤的用户输入时发作。用户输入的代码会在你的运用环境下实行。

为了防备这类进击,请确保你老是搜检并过滤了用户的输入内容。

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  

最简朴的防备要领则是运用参数化查询(parameterized queries)或预处理语句(prepared statements)。

假如你正在经由过程Node.js运用PostgreSQL。那末你能够运用node-postgres模块,来建立参数化查询:

var q = 'SELECT name FROM books WHERE id = $1';  
client.query(q, ['3'], function(err, result) {});  

敕令注入

进击者运用敕令注入来在长途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。现在高等别的加密体式格局已被广泛运用,然则,假如在效劳端缺少设置,也能够会致使效劳端运用初级别的加密,或不加密。

你须要测试:

  • 暗码,密钥和重协商(renegotiation)都已正当妥帖得设置终了。

  • 证书的正当性。

运用如nmapsslyze如许的东西能够使这项事情异常简朴。

搜检证书信息

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

运用sslyze来搜检SSL/TSL:

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

HSTS

在上文的设置治理章节我们已对其有了打仗 – Strict-Transport-Security头会强迫运用HTTPS来衔接效劳器。以下是一个Twitter的例子:

strict-transport-security:max-age=631138519  

这里的max-age定义了浏览器须要自动将一切HTTP要求转换成HTTPS的秒数。

关于它的测试是异常简朴的:

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

拒绝效劳

账号锁定

账号锁定用于紧张暴力破解带来的拒绝效劳方面的影响。实践中,它意味着,当用户尝试了频频上岸并失利后,将在厥后的一段内,制止他的上岸操纵。

能够运用之前提到的rate-limiter来阻挠这类进击。

正则表达式

这类进击主如果因为一些正则表达式,在极度情况下,会变得机能及其蹩脚。这些正则被称为恶魔正则(Evil Regexes):

  • 关于反复文本举行分组

  • 在反复的分组内又有反复内容

    ([a-zA-Z]+)*(a+)+(a|a?)+在如aaaaaaaaaaaaaaaaaaaaaaaa! 如许的输入眼前,都是软弱的。这会引发大批的盘算。更多概况能够参考ReDos

能够运用Node.js东西safe-regex这检测你的正则:

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

毛病处理

毛病码,客栈信息

一些毛病场景能够会致使运用泄漏底层的运用架构信息,如:like: X-Powered-By:Express

客栈信息能够自身自身并没有什么用,但它常常能泄漏一些进击者异常感兴趣的信息。将客栈信息返回出来是异常不好的实践。你须要将它们记录在日记中,而不是展现给用户。

NPM

更强的才能意味着更大的义务 – NPM有这很多能够现成运用的包,然则价值是:你须要搜检这些包自身是不是存在平安题目。

荣幸的是Node Security project(nsp)是一个异常棒的东西,来搜检你运用的模块是不是是易被一些已知的手腕进击的。

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

末了

这个清单重要依据OWASP保护的Web Application Security Testing Cheat Sheet所列。

原文链接

https://blog.risingstack.com/node-js-security-checklist/

    原文作者:菜菜蔡伟
    原文地址: https://segmentfault.com/a/1190000003860400
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞