之前获取前端安全方面的知识很是零碎且大多停留在看,又或者本身在实际项目中用到了其实也不太清楚。经过此次egg项目实践能更加深入的理解。egg在框架中内置了安全插件 egg-security, 提供了默认的安全实践。html
HSTS 指的是Http Strict Transport Security,是响应头的信息,它告诉浏览器只能经过HTTPS访问当前资源,而不是HTTP。前端
Http的请求明文传输过程当中,信息均可以被中间人(通讯运营商,代理,路由器厂商等)获取,可能形成数据泄漏,请求劫持,内容篡改等,web
场景:用户直接输入域名www.baidu.com,不输入http或者https,默认是http访问,http的访问会给用户返回一个302重定向到https的地址,后续的访问都是https传输。那么在这个http到302重定向的过程可能会被劫持篡改。chrome
开启hsts 在站点的响应头中设置Strict-Transport-Security,浏览器会将这个域名加入Hsts列表,下次用户早使用http访问这个网站,浏览器会自动发送https请求(但第一次访问仍是http),而不是先发送http再重定向到https,避免302重定向url被篡改,进一步提升通讯的安全性。json
以访问www.baidu.com为例子测试分析segmentfault
egg-security的防范 文档上说的是默认开启,可是看了下源码默认是false,须要手动开启。浏览器
// default
hsts: {
enable: false,
maxAge: 365 * 24 * 3600,
includeSubdomains: false, //能够添加子域名,保证全部子域名都使用 HTTPS 访问。
}
复制代码
Cross Site Request Forgery,跨站域请求伪造,重点在伪造的请求,CSRF 攻击能够在受害者绝不知情的状况下以受害者名义伪造请求发送给受攻击站点。缓存
最经典的例子安全
受害者 Bob 在银行有一笔存款,经过对银行的网站发送请求
http://bank.example/withdraw?account=bob&amount=1000000&for=bob2
可使 Bob 把 1000000 的存款转到 bob2 的帐号下。一般状况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,而且该 session 的用户 Bob 已经成功登录。黑客想到使用 CSRF 的攻击方式,他先本身作一个网站,在网站中放入以下代码:src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”
,而且经过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一块儿发向银行服务器。大多数状况下,该请求会失败,由于他要求 Bob 的认证信息。可是,若是 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 还没有过时,浏览器的 cookie 之中含有 Bob 的认证信息,操做成功。bash
这个操做看起来很玄乎,其实咱们常常点击一些外部信息的时候也会有这个过程,好比说我在juejin中点击一个原文连接跳转到sf:
点击访问时就会带上sf站点的cookie,假如攻击者将这个连接改成对用户有安全隐患的操做,sf又没有作防范的话,csrf攻击就成功了。(另外从图中的referer能够看到请求的来源。)
攻击原理 黑客经过借助受害者的cookie骗取服务器的信任,可是自己是没有办法获取cookie值的。
防范方法:
egg-security 中csrf的防范:
在默认配置下,egg-security会在cookie中设置token值,由于csrf攻击这是伪造请求,并不能实际获取cookie值,所以经过校验的请求才能实际发生。
egg-security只用csrf策略不保护get, head, options and trace四个方法,由于这四个方法被认为是安全的方法,不须要受到 CSRF 的保护,由于它们不会对应用程序进行更改,即便它们返回敏感信息,也会受到浏览器中的同源策略的保护。
在发送请求时egg-security会经过headerName/queryName/bodyName的字段去获取token值作校验,在 AJAX 请求的时候,能够从 Cookie 中取到 csrfToken(插件会把httponly设置为false让Js能够操做),放置到 query、body 或者 header 中发送给服务端。如:xhr.setRequestHeader('x-csrf-token', csrftoken);
// config/config.default.js
module.exports = {
security: {
csrf: {
headerName: 'x-csrf-token', // 经过 header 传递 CSRF token 的默认字段为 x-csrf-token
queryName: '_csrf', // 经过 query 传递 CSRF token 的默认字段为 _csrf
bodyName: '_csrf', // 经过 body 传递 CSRF token 的默认字段为 _csrf
},
},
};
复制代码
// egg-security csrf.js
module.exports = options => {
return function csrf(ctx, next) {
if (utils.checkIfIgnore(options, ctx)) {
return next();
}
// 在cookie中设置token值
ctx.ensureCsrfSecret();
// ignore requests: get, head, options and trace
const method = ctx.method;
if (method === 'GET' ||
method === 'HEAD' ||
method === 'OPTIONS' ||
method === 'TRACE') {
return next();
}
if (options.ignoreJSON && typeis.is(ctx.get('content-type'), 'json')) {
return next();
}
const body = ctx.request.body || {};
debug('%s %s, got %j', ctx.method, ctx.url, body);
// 判断token是否为预期
ctx.assertCsrf();
return next();
};
};
复制代码
刷新token cookie在设置时若是没有明确expires默认是session,这个session的意思跟sessionStorage的做用时间不同,sessionStorage只要关闭tab就不会保留数据,但cookie默认expires值session只有关闭浏览器token才会失效从新赋值。因此在用户登陆的时候须要刷新token,egg提供了ctx.rotateCsrfSecret();
从新设置csrfToken。
CSP(Content Security Policy)指定资源可信任来源(脚本、图片、iframe、fton、style等等可能的远程的资源),减小(注意这里是减小而不是消灭)跨站脚本攻击。 egg-security 中csp默认是不开启的,须要熟悉csp的policy配置Content Security Policy (CSP) 是什么?为何它能抵御 XSS 攻击
// 只容许本站资源
csp: {
enable: true,
policy: {
'default-src':'self'
},
}
复制代码
Cross-Site Tracing客户端经过http trace请求到服务器,服务器若是按照处理了trace请求会在response body中返回全部的请求头信息,包括httponly的cookie。
好比说这里的cookie test是httponly,正常来讲js是不能操做的,可是经过trace请求可以直接将这些信息返回。
Trace请求: 客户端发起一个请求可能要通过多个代理,网关等,每一个节点均可能修改原始的http请求,trace方法能够看到发到服务端是请求头最终的样子,TRACE 方法主要用于诊断。
TRACE 请求会在目的服务器端发起一个 环回 诊断。行程最后一站的服务器会弹回一条 TRACE 响应,并在响应主体中携带它收到的原始请求报文。这样客户端就能够查看在全部中间 HTTP 应用程序组成的请求 / 响应链上,原始报文是否,以及如何被毁坏或修改过。
egg-security的防范:判断方法为trace或者track时会返回405(Method Not Allowed)错误
// default
methodnoallow: {
enable: true
}
复制代码
URL钓鱼 网站中可能须要经过参数拼接成一个新的url让用户点击访问,若是参数是由用户输入的,可能会致使构形成一个恶意的网站连接,诱导用户跳转欺骗用户输入用户名密码,由于是信任的网站跳转的,用户比较信任。
防范 egg中由两种服务端跳转的方法,ctx.redirect(url)
会通过配置白名单的校验后再进行跳转,若是domainWhiteList 为空则与ctx.unsafeRedirect(url)
跳转同样不进行校验。 // default exports.security = { domainWhiteList: [] }
iframe钓鱼 经过内嵌 iframe 到被攻击的网页中能够诱导用户点击危险网站,遮盖影响网站的正常功能。
防范 X-Frame-Options HTTP 响应头是用来给浏览器 指示容许一个页面 能否在 , , 或者 中展示的标记。 egg-security提供了xframe的选项,默认是SAMEORIGIN,只容许同域把本页面看成 iframe 嵌入。
// default
xframe: {
enable: true,
// 'SAMEORIGIN', 'DENY' or 'ALLOW-FROM http://example.jp'
value: 'SAMEORIGIN',
}
复制代码