本人新博客www.wjs.photo,基于360的firekylin,感兴趣的可以看看哈

本文翻译自 www.risingstack.com ,并非逐字逐句的翻译,有错误的地方请指出,谢谢啦

应用程序的安全就像是你房间里突然出现一只大象,那么明显,但是写代码的同学还是会忽略。也都认为应用程序的安全非常重要但是却很少有时间认真对待,毕竟我们有那么多bug要改(坏笑)。所以我们整理了一个NodeJs应用安全备忘录,以帮助你在部署启动NodeJs应用程序的时候进行安全检查。当然,这些项目大部分是通用的,适用于所有的语言和框架而不仅仅是Node.js。但是本文具体还涉及到一些Node.js的工具。感兴趣的同学也可以查看我的介绍Node.js的安全性的博客。


配置管理(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来设置这些头部:

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

当然,在koa框架中也可以使用:传送门

这些头部不只是可以放在代码中,也可以配置在web服务器中(Apache、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服务器的配置也可以参考:这里

客户端的敏感数据

在部署前端应用程序时要确保不会将秘密的API公开,公开的API会被任何人访问

虽然没有好的自动检查的方法,但有两个注意点可以减轻由于意外而暴露敏感数据的风险

1.检查使用的请求

2.常规的代码审查

身份验证

Brute Force Protection(暴力攻击防护)

暴力破解(也称穷举法),即将密码进行逐个推算直到找到真正的密码,然后在web应用程序中登录。

为了防止应用程序受到暴力破解的攻击,应用程序最好要有密码错误容许次数机制,在NodeJs中,你可以使用:ratelimiter

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

当然啦,你也可以将他包装成一个中间件,就可以放在应用程序中,无论是Express框架还是Koa框都有厉害的中间件,在koa框架中,他可能是这个样子:

  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不会过期,直到超出设定的日期

在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/csrf)块,由于这个比较底层,也有不同的框架包装好的,这个例子是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

本人新博客www.wjs.photo,基于360的firekylin,感兴趣的可以看看哈

Nodejs应用安全备忘录的更多相关文章

  1. NodeJs之OS

    OS Node.js提供了一些基本的底层操作系统的模块OS. API var os = require('os'); console.log('[arch] 操作系统CPU架构'+os.arch()) ...

  2. NodeJs之Path

    Path模块 NodeJs提供的Path模块,使得我们可以对文件路径进行简单的操作. API var path = require('path'); var path_str = '\\Users\\ ...

  3. NodeJs之调试

    关于调试 当我们只专注于前端的时候,我们习惯性F12,这会给我们带来安全与舒心的感觉. 但是当我们使用NodeJs来开发后台的时候,我想噩梦来了. 但是也别泰国担心,NodeJs的调试是很不方便!这是 ...

  4. NodeJs在Linux下使用的各种问题

    环境:ubuntu16.04 ubuntu中安装NodeJs 通过apt-get命令安装后发现只能使用nodejs,而没有node命令 如果想避免这种情况请看下面连接的这种安装方式: 拓展见:Linu ...

  5. NodeJs之child_process

    一.child_process child_process是NodeJs的重要模块.帮助我们创建多进程任务,更好的利用了计算机的多核性能. 当然也支持线程间的通信. 二.child_process的几 ...

  6. nodejs进阶(6)—连接MySQL数据库

    1. 建库连库 连接MySQL数据库需要安装支持 npm install mysql 我们需要提前安装按mysql sever端 建一个数据库mydb1 mysql> CREATE DATABA ...

  7. 图片访问实时处理的实现(nodejs和php)

    我在访问时光网.网易云音乐等网站时,发现将它们页面中的一些图片URL修改一下就可以得到不同尺寸的图片,于是思考了其实现方案,我的思路是:URL Rewrite + 实时处理 + 缓存,对用户请求的UR ...

  8. nodejs进阶(4)—读取图片到页面

    我们先实现从指定路径读取图片然后输出到页面的功能. 先准备一张图片imgs/dog.jpg. file.js里面继续添加readImg方法,在这里注意读写的时候都需要声明'binary'.(file. ...

  9. nodejs进阶(3)—路由处理

    1. url.parse(url)解析 该方法将一个URL字符串转换成对象并返回. url.parse(urlStr, [parseQueryString], [slashesDenoteHost]) ...

随机推荐

  1. Node.js连接MySQL数据库及构造JSON的正确姿势

    做一下整理,以前也很随意的引入包链接数据库,后来发现常常连接出问题,异常退出,后来使用在网上一个方法解决问题,网址由于书签丢失,抱歉不能引用了.再有就是简单的模块化下,使得目录合理点,再有就是说明一下 ...

  2. 安装Visual Studio 2010 - 初学者系列 - 学习者系列文章

    本文讲述如何安装Visual Studio 2010开发工具. 首先,通过下列地址获取Visual Studio 2010的副本 1.开始页面 2.欢迎页 3.这里选择 自定义 ,选择安装路径 4.这 ...

  3. Android仿微信气泡聊天界面设计

    微信的气泡聊天是仿iPhone自带短信而设计出来的,不过感觉还不错可以尝试一下仿着微信的气泡聊天做一个Demo,给大家分享一下!效果图如下: 气泡聊天最终要的是素材,要用到9.png文件的素材,这样气 ...

  4. Vijos:P1001谁拿了最多奖学金

    描述 某校的惯例是在每学期的期末考试之后发放奖学金.发放的奖学金共有五种,获取的条件各自不同: 1) 院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以 ...

  5. SQL练习1关于插入删除,修改,单表查询

    --创建数据库create database studentsDB --创建表create table student( id int primary key, stuid char(10), stu ...

  6. 排序算法学习,python实现

    原创博文,转载请注明出处 利用周六周末的时间把几种基本的排序方法用python实现了一下,废话少说,直接上代码. 本文不注重基础知识的讲解,只做大致的描述,大家如果不清楚概念,自行查找资料. 直接插入 ...

  7. MacVim小试

    Mac OS X使用之——新年第一天弘法寺许愿,MacVim小试 分类: Vi/Vim Mac OS X2013-01-01 22:08 3371人阅读 评论(0) 收藏 举报   目录(?)[+] ...

  8. Day1:T3 bfs T4 树形DP

    T3:BFS 回看了一下Day1的T3...感觉裸裸的BFS,自己当时居然没有看出来... 同时用上升和下降两种状态bfs即可 这一题还要注意一个细节的地方,就是题目要求的是求往返的最优解 k=min ...

  9. poj3984迷宫问题

    一个5 × 5的二维数组,表示一个迷宫.其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线. 很简单的一道题,迷宫问题,一般都选择两种优先搜索 ...

  10. 图解Javascript之Function

    好东西分享给大家,但要尊重事实!!!因此特别说明:本图非我本人亲自所作,乃我大天朝网友所绘制.个人感觉此图,覆盖全面,细节考虑甚周全,因此分享给大家,同时在此特别感谢网友的无私分享!