Koa2项目安全加固建议--完整版
发布于 7 个月前 作者 18820227745 1982 次浏览 最后一次编辑是 4 个月前 来自 分享

2017 年 12 月 27 日 14:36:56

参考:

1.使用 TLS 加密数据的传输

如果传输的信息的敏感性较高,比如用户的个人信息或者安全秘钥信息的传递,请考虑使用 TLS 协议来加密数据传输。另外普通的 Ajax 请求和 Post 请求在不加密的情况下很容易被包嗅探工具扫描到,并且可能遭受中间人攻击等风险。

可能很多人对于传统的 SSL 加密比较熟悉,而 TLS 就是 SSL 的下一代安全加密产品。对于 web app 我们可以使用 Nginx 来配置 TLS 加密,具体的操作方法可参考如下的配置文件,该配置文件适用于几乎所有的现代浏览器(老式浏览器可能会对于一些算法的支持度不好):

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    # modern configuration. tweak to your needs.
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    resolver <IP DNS resolver>;

    ....
}

2.使用 koa-helmet 中间件

koa-helmet 可以帮助你的 app 抵御一些比较常见的安全 web 安全隐患,它其实是将 9 个安全中间件集中到了一起,做了合并,大部分都是对于 http header 的操作,下面我们就来看一下这几个模块:

* csp: 通过设置 Content-Security-Policy 来阻止 XSS 攻击和一些其他的跨站注入风险。

  • csp:“网页安全政策”(Content Security Policy,缩写 CSP),CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。
  • Content-Security-Policy:通过设置可以启用 csp
  • meta:通过网页的 meta 标签也可以开启 csp 功能
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
  • 使用
// Make sure you run "npm install helmet" to get the Helmet package.
var helmet = require("koa-helmet");

app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "maxcdn.bootstrapcdn.com"]
    }
  })
);

参考:Content Security Policy 入门教程

* hidePoweredBy: 删除了 header 中的 X-Powered-By 标签

  • X-Powered-By:包含站点服务器信息与程序信息及版本
  • 使用:默认已启用

* hpkp:通过增加 Public key Pinning 来阻止伪造证书导致的中间人攻击。

  • HPKP:技术给予我们主动选择信任 CA 的权利。它的工作原理是通过响应头或者 meta 标签告诉浏览器当前网站的证书指纹,以及过期时间等其它信息。未来一段时间内,浏览器再次访问这个网站必须验证证书链中的证书指纹,如果跟之前指定的值不匹配,即便证书本身是非法的,也必须断开连接。
  • 使用:
// Make sure you run "npm install helmet" to get the Helmet package.
var helmet = require('koa-helmet')

var ninetyDaysInSeconds = 7776000
app.use(helmet.hpkp({
  maxAge: ninetyDaysInSeconds,
  sha256s: ['AbCdEf123=', 'ZyXwVu456=']
}))

参考:HTTP Public Key Pinning 介绍 HTTP PUBLIC-KEY-PINNING EXPLAINED The what, why, and how of RFC 7469

* hsts: 设置 Strict-Transport-Security 来强制安全连接(http over SSL)到服务器(服务器需要支持 https)

  • HSTS: HSTS 的作用是强制客户端(如浏览器)使用 HTTPS 与服务器创建连接
  • 使用:默认已开启

参考:百度百科 HSTS

* ieNoOpen:为 ie8 设置 X-Download-Options

  • 原因:一些网络应用程序将提供不可信的 HTML 下载。默认情况下,IE 的某些版本将允许您在网站上下文中打开这些 HTML 文件,这意味着不可信的 HTML 页面可能会在页面的上下文中开始做坏事。
  • 使用:默认已开启

* noCache:设置 Cache-Control 关闭客户端缓存。

  • 使用:
// Make sure you run "npm install helmet" to get the Helmet package.
var helmet = require('koa-helmet')

app.use(helmet.noCache())

* noSniff: 设置 X-Content-Type-Options 阻止浏览器 MIME-sniffing。

  • 原因:if my server serves file.txt with a text/plain content-type, some browsers can still run that file with <script src=“file.txt”></script>. Many browsers will allow file.js to be run even if the content-type isn’t for JavaScript.
  • 使用:默认已开启

参考:[翻译] 危险的嗅探——IE 的 MIME 嗅探导致 XSS 攻击

* frameguard:设置 X-Frame-Options 阻止点击劫持风险

  • 点击劫持(clickjacking)是一种在网页中将恶意代码等隐藏在看似无害的内容(如按钮)之下,并诱使用户点击的手段
  • 使用:默认已开启

* xssFilter: 设置 X-XSS-Protection 启用

  • 目的:这个 header 主要是用来防止浏览器中的反射性 xss。现在,只有 IE,chrome 和 safari(webkit)支持这个 header。
  • 反射性 xss:主要是由于服务端接收到客户端的不安全输入,在客户端触发执行从而发起 Web 攻击。比如:在某购物网站搜索物品,搜索结果会显示搜索的关键词。搜索关键词填入<script>alert('handsome boy')</script>, 点击搜索。页面没有对关键词进行过滤,这段代码就会直接在页面上执行,弹出 alert。
  • 使用:默认已开启

参考:header 的安全配置指南

* koa-helmet功能默认启动表

module default?
contentSecurityPolicy for setting Content Security Policy x
dnsPrefetchControl controls browser DNS prefetching
frameguard to prevent clickjacking
hpkp for HTTP Public Key Pinning x
hsts for HTTP Strict Transport Security
ieNoOpen sets X-Download-Options for IE8+
noCache to disable client-side caching x
noSniff to keep clients from sniffing the MIME type
referrerPolicy to hide the Referer header x
xssFilter adds some small XSS protections

* 默认使用

const Koa = require('koa')
const helmet = require('koa-helmet')
const app = new Koa()

app.use(helmet())

app.use((ctx) => {
  ctx.body = 'Hello World'
})

app.listen(4000)

3.使用koa-limit中间件

* koa-limit: 可以限制用户的提交速度和查询速度,从而用来预防洪水攻击。

  • 洪水攻击: 常见的有DDoS(拒绝服务攻击),就是让你的服务器资源耗尽,无法提供正常的服务,间接地拒绝。

参考:百度百科洪水攻击

  • 使用:
var koa = require('koa');
var favicon = require('koa-favicon');
var limit = require('koa-limit');

var app = koa();
// If you are using reverse proxy on the front of node, like 'nginx', please set this 
// app.proxy = true; 
app.use(favicon());
//一个小时内限制用户访问不超过1000次
app.use(limit({
  limit: 1000,
  interval: 1000 * 60 * 60
}));

app.use(function *() {
  this.body = 'hello';
});

app.listen(7001);

  • 使用参数说明:

    • limit: limit request number, default is 1000.

    • interval: limit refresh interval in ms, default is one day.

    • token: prefix key, for isolate different koa-limit, default is koa-limit, if you want to use more than one

    • koa-limit in a project, you must set different token!!

    • store: can be set with a redis store, or other store with API in MemoryStore. default store is MemoryStore.

    • whiteList: all ips in whiteList won’t be limited.

    • blackList: all ips in blackList will 403.

    • message: forbidden message, defautl is ‘request frequency limited’.

4.使用koa-csrf中间件

* koa-csrf:在你的提交表单里增加一个独有的临时的令牌用于服务器端验证,从而保证提交数据的正确性,防止CSRF攻击。

  • CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
  • CSRF攻击理解:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。
  • 使用: koa2安装:
npm install --save koa-csrf@3.x

使用: 服务器端

import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
import session from 'koa-generic-session';
import convert from 'koa-convert';

const app = new Koa();

// set the session keys 
app.keys = [ 'a', 'b' ];

// add session support 
app.use(convert(session()));

// add body parsing 
app.use(bodyParser());

// add the CSRF middleware 
app.use(new CSRF({
 invalidSessionSecretMessage: 'Invalid session secret',
 invalidSessionSecretStatusCode: 403,
 invalidTokenMessage: 'Invalid CSRF token',
 invalidTokenStatusCode: 403,
 excludedMethods: [ 'GET', 'HEAD', 'OPTIONS' ],
 disableQuery: false
}));

// your middleware here (e.g. parse a form submit) 
app.use((ctx, next) => {

 if (![ 'GET', 'POST' ].includes(ctx.method))
   return next();

 if (ctx.method === 'GET') {
   ctx.body = ctx.csrf;
   return;
 }

 ctx.body = 'OK';

});

app.listen();

客户端表单新增_csrf项:

//pug模板
form(action='/register', method='POST')
  input(type='hidden', name='_csrf', value=csrf)
  input(type='email', name='email', placeholder='Email')
  input(type='password', name='password', placeholder='Password')
  button(type='submit') Register

参考:浅谈CSRF攻击方式

5.使用sqlmap工具

* sqlmap是一个开源的渗透测试工具,可以用来自动化的检测,利用SQL注入漏洞,获取数据库服务器的权限。它具有功能强大的检测引擎,针对各种不同类型数据库的渗透测试的功能选项,包括获取数据库中存储的数据,访问操作系统文件甚至可以通过外带数据连接的方式执行操作系统命令。

  • sqlmap支持的数据库有:MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase和SAP MaxDB
  • 检测注入:
    • 基本格式
sqlmap -u "http://www.vuln.cn/post.php?id=1"
默认使用level1检测全部数据库类型
sqlmap -u "http://www.vuln.cn/post.php?id=1"  --dbms mysql --level 3
指定数据库类型为mysql,级别为3(共5级,级别越高,检测越全面)

参考: Sqlmap使用教程【个人笔记精华整理】

6.确保依赖库的安全性

借助于社区提供的大量的依赖库,我们可以更加聚焦在自己的业务代码的编码上。对于依赖库我们一般通过npm来管理,非常方便,但是引入的包是否会给我们的应用引入新的安全风险呢?我们可能听说过的短板效应,描述的就是这种情况,当我们苦心积虑的去考虑了任何安全的风险后写出自己的业务代码。但是却忽视了引入的库的安全性,则之前所作出的努力可能都白费了。

我们可以使用如下的两个工具来管理第三方的依赖库的安全问题。nsprequireSafe,两个工具功能上大致相同。

nsp是一个命令行工具,通过一个node安全项目数据库来决定我们的应用所依赖的包是否具有安全风险。

  • 使用:
//nsp会提交package.json中的内容进行安全检查

$ npm i nsp -g
$ nsp check

// requiresafe的使用基本相似

$ npm install -g requiresafe
$ cd your-app
$ requiresafe check

7.确保前端引用的js库安全

  • Retire.js的目标是帮助用已知的漏洞检测模块版本的使用。在chrome浏览器的应用商店搜索Retire.js插件并安装。
  • 使用:安装好后用浏览器打开要测试的网页即可,点击插件即可进行检查。

retireJs.png

8.代码扫描工具SonarQube

  • Sonar是一个用于代码质量管理的开源平台,用于管理源代码的质量,可以从七个维度检测代码质量通过插件形式,可以支持包括java,C#,C/C++,PL/SQL,Cobol,JavaScrip,Groovy等等二十几种编程语言的代码质量管理与检测。
  • 安装:CentOS7.4上安装SonarQube
  • 使用:
    • 使用admin,admin用户名,密码登录到你搭建的服务器上
    • 分析一个新项目

2.png 4.png 6.png

4 回复

看了一下koa-limit, 死马写的吧好像,已经年久失修了。

而且为个人不建议在koa/express这类框架上面加限制,而是应该在nginx层加限制。

如果是使用nginx转发请求,那么koa-limit是失效的,甚至是累赘,因为是根据ip来作限制,nginx的转发ip总是本地id,一下子就能把限制打满。

如果要兼容这个,那么需要兼容X-Forward-Ip请求头

@axetroy 受教了,谢谢

回到顶部