中的安全注意事项,以前获取的前端安全知识非常零散,大部分只是停留在阅读上,或者在实际项目中使用时了解不多。通过这次egg项目实践,让我有了更深刻的认识。egg在框架中内置了一个安全插件egg-security,它提供了默认的安全实践。HSTSHSTS指的是HttpStrictTransportSecurity,是响应头的信息,告诉浏览器当前资源只能通过HTTPS访问,不能通过HTTP访问。Http请求在明文传输过程中,信息可以被中介(通信运营商、代理、路由器厂商等)获取,可能造成数据泄露、请求劫持、内容篡改等场景:用户直接进入域namewww.baidu.com,不要输入http或者https,默认是http访问,http访问会给用户返回一个302重定向到https地址,后续访问都是https传输。那么http重定向到302的过程就可能被劫持和篡改。打开hsts,在站点的响应头中设置Strict-Transport-Security,浏览器就会把这个域名添加到hsts列表中,下次用户使用http访问这个网站时,浏览器会自动发送https请求(但是第一次访问还是http),而不是先发送http再重定向到https,避免了302重定向url被篡改,进一步提高了通信的安全性。以www.baidu.com为例进行测试分析。打开chrome://net-internals/#hsts,此时在deletedomain中输入www.baidu.com删除,然后在queryhsts中输入www.baidu.com,显示notfound证明Cache已被清除。直接在浏览器输入www.baidu.com,会看到先发送http请求然后302https重定向打开https的详细信息,可以看到StrictTransportSecurity响应头,max-age表示hsts有效期再次在浏览器中输入www.baidu.com,会看到和第一次请求不一样。这次是307重定向,也就是说浏览器做了一个内部转换,将http转为https。回到chrome://net-internals/#hsts,查询www.baidu.com可以看到浏览器缓存了百度的hsts。egg-security的防御文档说是默认开启的,但是看了源码发现默认是false,需要手动开启。//defaulthsts:{enable:false,maxAge:365*24*3600,includeSubdomains:false,//可以添加子域,保证所有子域都使用HTTPS访问。}CSRFCrossSiteRequestForgery,跨站域请求伪造,重点是伪造请求,CSRF攻击可以在受害者不知情的情况下,以受害者的名义向被攻击站点发送伪造的请求。最经典的例子就是受害人Bob在银行有一笔存款。通过向银行网站http://bank.example/withdraw?account=bob&amount=1000000&for=bob2发送请求,Bob可以将1,000,000的存款转入bob2的账户。通常,请求发送到网站后,服务器首先会验证请求是否来自合法的session,session的用户Bob是否已经成功登录。黑客想到了使用CSRF攻击方式。他先自己建了一个网站,在网站中加入如下代码:src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory”,然后通过广告等方式引诱,让Bob访问他的网站。当Bob访问网站时,上面的url会从Bob的浏览器发送到银行,这个请求会连同Bob浏览器中的cookie一起发送到银行服务器。大多数时候,请求失败是因为他要求Bob的身份验证信息。但是,如果Bob在那之后不久碰巧访问了他的银行,那么他的浏览器和银行网站之间的会话还没有过期,并且浏览器的cookie中包含Bob的身份验证信息,那么操作就成功了。这个操作看起来很神秘。其实我们在点击一些外部信息的时候,经常会有这个过程。比如我在juejin点击一个原链接跳转到sf:点击访问的时候会带上sf站点的cookie。如果攻击者将此链接更改为对用户造成安全风险的操作,如果sf不采取防范措施,csrf攻击就会成功。(另外可以看到图中referer的请求来源。)攻击原理黑客利用受害者的cookie来欺骗服务器的信任,但是cookie本身是没有办法获取的。预防方法:验证referer字段。从上图我们可以看出,在服务端可以获取到referer,所有对安全敏感的请求都添加了referer过滤拦截。问题:referer是由浏览器提供的。http虽然有协议规定,但各个浏览器在referer的实现上可能存在偏差,也不能保证浏览器本身没有安全漏洞。依靠第三方浏览器来保证安全理论上是不可靠的。一些旧的浏览器可以篡改referer。即使不能被篡改,如果用户担心referer会留下用户的访问源,也可以设置浏览器不记录referer信息。通过令牌值验证令牌的方法有很多种。其实就是获取服务器给的一个具体的值,在发送请求的时候带上这个值,服务器确认是自己下发的token。egg-security中csrf的防范:在默认配置下,egg-security会在cookie中设置token值,因为csrf攻击是伪造的请求,无法真正获取到cookie值,所以通过验证的请求才会真实发生.egg-security只使用csrf策略不保护get、head、options和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.jsmodule.exports={security:{csrf:{headerName:'x-csrf-token',//viaheader默认传递CSRFtoken的字段为x-csrf-tokenqueryName:'_csrf',//通过query传递CSRFtoken的默认字段为_csrfbodyName:'_csrf',//通过body传递CSRFtoken的默认字段is_csrf},},};//egg-securitycsrf.jsmodule.exports=options=>{returnfunctioncsrf(ctx,next){if(utils.checkIfIgnore(options,ctx)){returnnext();}}//在cookie中设置token值ctx.ensureCsrfSecret();//忽略请求:get、head、options和traceconstmethod=ctx.method;if(method==='GET'||method==='HEAD'||method==='OPTIONS'||method==='TRACE'){returnnext();}if(options.ignoreJSON&&typeis.is(ctx.get('content-type'),'json')){returnnext();}常量体=ctx.request.body||{};debug('%s%s,got%j',ctx.method,ctx.url,b欧迪);//判断token是否是预期的ctx.assertCsrf();返回下一个();};};如果刷新令牌cookie没有明确过期,则默认为会话。这个session的意义和sessionStorage的动作时间是不一样的。只要选项卡关闭,sessionStorage就不会保留数据,但默认的cookie过期值session只会在浏览器令牌关闭时失效并重新分配。所以需要在用户登录的时候刷新token,Egg提供了ctx.rotateCsrfSecret();重置csrfToken。CSPCSP(ContentSecurityPolicy)指定可信资源来源(可能的远程资源,如脚本、图片、iframe、ftons、styles等),以减少(注意这里是减少而不是消除)跨站脚本攻击。在egg-security中,默认情况下不启用csp。需要熟悉csp的policy配置。什么是内容安全策略(CSP)?为什么能抵抗XSS攻击//只允许本站资源csp:{enable:true,policy:{'default-src':'self'},}XSTCross-SiteTracing客户端通过httptrace向服务器请求,如果服务器根据处理过的trace请求,会在响应体中返回所有的请求头信息,包括httponlycookies。比如这里的cookie测试是httponly。正常情况下无法操作js,但是可以直接通过trace请求返回信息。Tracerequest:客户端发起一个请求,可能会经过多个proxy,gateway等,每个节点都可能修改原始的http请求。trace方法可以看到发送到服务器的请求头最后的样子。TRACE方法主要用于诊断。TRACE请求将在目标服务器上启动环回诊断。行程最后一站的服务器将使用它在响应正文中收到的原始请求消息反弹回TRACE响应。这允许客户端查看原始消息是否以及如何沿着所有中间HTTP应用程序的请求/响应链被破坏或修改。egg-security防御:当判断方法为trace或track时,会返回405(MethodNotAllowed)错误//defaultmethodnoallow:{enable:true}用户点击访问,如果参数是用户输入的,可能会导致构建恶意网站链接,诱导用户跳转,诱骗用户输入用户名和密码,因为是可信网站,用户信任它。为防止egg被两台服务器重定向,ctx.redirect(url)会在配置白名单验证通过后进行重定向。如果domainWhiteList为空,则不会像ctx.unsafeRedirect(url)检查一样执行。//defaultexports.security={domainWhiteList:[]}iframe钓鱼通过在被攻击网页中嵌入iframe来诱导用户点击危险网站,覆盖并影响网站的正常功能。PreventX-Frame-OptionsHTTP响应头用于向浏览器指示页面是否允许在、
