前端知识笔记 - 安全

前端知识笔记 - 安全

本文章总结 https://github.com/thedaviddias/Front-End-Checklist
内部,非原创性内容。javascript

https

  1. 尽可能使用 Https,我的网站可以使用 Let's Encrypt
  2. 使用 Strict-Transport-Security 返回头。解决的问题是https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet
  • 使用书签或手动输入网址访问 http 网址
  • https 页面中不经意使用了 https 的资源(连接、内容等)
  • 中间攻击人让用户信任证书,设置返回头后,浏览器不接受不受信任的证书

设置方式以下:
max-age 表示在该有效时间内应该使用 https 访问,includeSubDomains 表示该域名的全部子域名适用于该策略,preload 表示预加载时不会使用 http 连接。
三个参数必须都设置才更安全。
示例:php

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Secure Server Design 安全服务设计

地址:https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheetcss

  1. 在任意地方使用 TLS 或其余更强的加密服务 (Use TLS or Other Strong Transport Everywhere)
    内部网络也可被黑客攻击到,登陆页必须使用 HTTPS,不然表单和 session 都有被盗取的可能
    不支持 TLS 的服务 SEO 权重会下降前端

  2. 涉及安全的页面必须使用 TLS(Do Not Provide Non-TLS Pages for Secure Content)java

  3. TLS 下不要混用非 TLS 内容(Do Not Mix TLS and Non-TLS Content)
    非 TLS 内容可被篡改nginx

  4. cookie 使用 secure 标识( Use "Secure" Cookie Flag)
    设置 httpOnly 能够禁止页面访问该 cookie,设置 secure 能够设置 cookie 只在 https 下传输git

  5. 敏感数据不使用 URL 传输(Keep Sensitive Data Out of the URL)
    URL 中不能传输数据,即便使用了 HTTPS。有两种可能泄漏:
  • URL 会被浏览器缓存,也就是该电脑上其余人能够看到该解码后的数据
  • 页面上点击其余网站,其余网站会取到 referral 字段,从而泄漏
  1. 不要缓存敏感数据(Prevent Caching of Sensitive Data)
    TLS 只能保证传输安全,客户端和代理部分泄漏数据是没法避免的,因此须要设置敏感数据不缓存
Cache-Control: no-cache, no-store"
"Expires: 0"
  1. 使用 Strict-Transport-Security (Use HTTP Strict Transport Security)
    确保用户不会访问 HTTP 页面github

  2. Pinning 技术(Use Public Key Pinning)
    地址: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinningweb

这一部分主要是讲使用双向验证的方式来解决掉中间人攻击的问题。简单来讲就是客户端存储服务端的 public key,
经过验证服务端下发的公钥和当前存储的公钥是否相同,或者 hash 值是否相同。这种方式可使用自签发证书,不须要使用 ca 签发的证书。
在客户端中使用该技术比较多, web 端一样可使用:ajax

Public-Key-Pins: max-age=2592000;
pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=";
report-uri="http://example.com/pkp-report"

设置 key 的 hash 值,在指定的过时时间以前,服务端使用的 public key hash 不会变化,不然不该该信任。

服务端证书相关

  1. 使用加密更强的 key 和安全存储(Use Strong Keys & Protect Them)
    目前安全最低位为 2048 位

  2. 使用包含当前必须域名的证书(Use a Certificate That Supports Required Domain Names)
    使用一致的域名或主机名,不要使用过时证书。有多域名,须要证书中指定多域名,即Subject Alternate Names (SANs)

  3. 使用正确的名称(Use Fully Qualified Names in Certificates)
    不要使用 localhost 或者 ip 或者 www 等

  4. 不要使用通配符证书(Do Not Use Wildcard Certificates)

  5. 不要使用 RFC 1918 地址(Do Not Use RFC 1918 Addresses in Certificates)
    好比:192.168/16, 172.16/12, and 10/8.

  6. 根据用户基数设计合适的证书认证方式(Use an Appropriate Certification Authority for the Application's User Base)
    内部应用可以使用内部证书,全部用户应该安装该证书,其余状况请使用公用证书服务商,他们的证书已经内置于当前应用中。
    不容许使用自签发证书

  7. 请提供全部须要的证书(Always Provide All Needed Certificates)
    证书必须可被回溯到信任的根证书。证书路径可有多级,因此须要证书提供到根证书以前的全部证书

  8. SHA1 证书已废弃(Be aware of and have a plan for the SHA-1 deprecation plan)

服务端协议和加密配置

  1. 仅支持强协议(Only Support Strong Protocols)
    尽可能提供支持 TLS 1.1 和 TLS 1.2 的

  2. 使用短暂密钥(Prefer Ephemeral Key Exchanges)

  3. 只支持强加密算法(Only Support Strong Cryptographic Ciphers)

  4. (Support TLS-PSK and TLS-SRP for Mutual Authentication)

  5. 只支持安全的从新协商(Only Support Secure Renegotiations)

  6. 禁用压缩(Disable Compression)

  7. 更新加密库(Update your Crypto Libraries)

客户端配置

web 服务是由浏览器进行认证的,不受应用控制。其余状况下须要进行配置:

  • 服务端应用以 TLS 方式链接其余的 web 服务或者交换数据。
  • 重客户端应用 TLS 链接服务器
    配置是否正确必定要验证

其余

  1. EV 证书(Extended Validation Certificates),目的是的费用是合法的实体,给用户更多的保证,注意,它自己不提供更好的加密方式,
    只是增长用户信心

  2. 客户端证书,也就是“双向 TLS”,即服务端一样须要验证客户端的身份,因为证书生成复杂,分发安全性,客户端配置,证书吊销和重发行,
    这类证书用法只在高价值的链接且用户量比较少的场景

  3. 证书和公钥的 pinning(Certificate and Public Key Pinning)。Pinning 是将 host(好比服务器)和认证内容(证书或者公钥),
    应用对已经存在的关系进行认证。意思是若是从服务端下载的证书和本地存在的证书不匹配,不创建链接。一般在 Hybrid 和Native 应用中使用。
    而 web 浏览器的应用没法实现。

最后后端服务也须要进行加密,包括内网服务。

Cross Site Request Forgery (CSRF)

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
简单翻译下:跨域请求伪造,一个恶意的网站、邮件、博客或者实时信息,经过浏览器针对信任的网站发起请求(用户已登陆状况下)。

须要保护的内容包括:

  • form 使用 POST
  • Ajax/Xhr 调用
    注意:不要使用 GET 请求执行状态改变操做,若是不得不,须要保护该方法。

CSRF 保护总结:建议使用基于 token 减小 CSRF 攻击。在高度敏感操做中,使用交互式保护,使用二次认证或者一次性 TOKEN。
深度防御参照后面

相关文章见:https://seclab.stanford.edu/websec/csrf/csrf.pdf

CSRF 推荐防御方式

主要方式:迁移 TOKEN 方式(Token Based Mitigation)

注:须要使用强加密或者 HMAC 方法,推荐使用 AES256-GCM 或者 SHA256/512 方式
严格的加密 KEY 轮换和 token 生命周期策略

  • 令牌同步模式(Synchronizer Token Pattern,STP),写操做须要添加安全的随机 token,该 token 能够放在 headers 或者参数中(ajax)、URL (GET),与服务端的 token 进行对比。该方案原本用于防止表单重复提交,由服务端进行是否存在和是否正确进行验证,开发者能够更好的验证用户的提交意图,从而避免 CSRF 攻击。注意的是: token 不能像 cookie 同样由浏览器自动发出,同时若是使用基于请求的 token 比基于用户 session 的 token 安全性更高,但可用性较低,可能形成正常访问失效的问题。不要使用 GET 请求进行敏感操做,在 referer 字段中会暴露 csrf token,
  • 令牌加密模式(Encryption based Token Pattern),即无状态模式。服务端基于用户 ID,时间戳,一次性数字使用惟一的 KEY 对 token 进行加密,返回给客户端,这种状况下重放攻击和修改攻击失效。主要用于无状态应用。
  • 令牌HMAC模式(HMAC Based Token Pattern),即便用HMAC(hash-based message authentication code,哈希运算消息认证码)加密方式。它与令牌加密模式相似,有两点不一样:1. 使用强 HMAC 函数而不是使用加密函数;2. 包括额外的字段"operation" 代表操做的目的。一样包含用户 ID,时间戳和 nouce,operation 字段

深度防御

  1. 验证标准 headers 中的 origin 字段(Verifying origin with standard headers)。

有两个步骤:1. 验证请求来源(source origin. 可经过 Origin/Referer header),2. 验证请求要去哪里(target origin)。之全部使用标准字段,是由于使用 javascript 的 XSS 攻击没法修改这两个字段(forbidden headers,只能由浏览器设置)。

  • 验证来源 origin。其中 Referer 在从 https 跳转至 http 中会丢失,但会保留 Origin 字段,同协议之间跳转会保留 Referer. 必定要强验证,如 site.com 和 site.com.attacker.com. 若是两个字段都不存在,建议 block 掉该请求,或者记录请求,后续确认后进行拦截。
  • 验证目标 origin。若是用户直接访问服务,可以使用 URL 验证目标 origin; 若是你的服务在代理后面,1. 设置服务为已知的 origin,若是存在多域,可考虑使用集中的配置,实例从中获取;2. 使用 host 请求头的值,若是位于 proxy 后面,host 值会变化。3. 使用 X-Forwarded-Host 的值,该值的上的是包括初始的请求 host,大多数 proxy 会将 Host 值传过来。

一般状况下验证 header 没有问题,但特殊状况下可能不存在该 headers。好比

  • IE11 在跨域信任区时不带 Origin 字段
  • 302 重定向跨域请求不带 Origin
  • 一些隐私状况下 Origin 会为 null
  • Origin 在跨域请求中所有携带,在同域时只包括 post/delete/put 方法。
  • Referer 也一样有问题,部分状况下会被省略,同时负载均衡、代理、嵌入式设置也会因隐私的缘由移除该字段。

    因此要使用验证须要先观察一段时间,而后将例外添加至代码中。该方式有两个问题:依赖于浏览器行为,须要更新规则,同时存在 XSS 攻击时,防范效果有限。

  1. 再次提交 cookie 策略(Double Submit Cookie)
    若是不方便使用 csrf token,可使用该方式,经过比较请求带的随机值和 cookie 中随机值是否相等来判断。该方式基于用户没法读取 cookie 或者修改该 cookie 值,在跨域状况下也会出现写 cookie 的状况,好比写 cookie 能够指定为父域,则该域下的 cookie 都不安全,或者中间人攻击将 https 转换为 http。因此使用该方式要保证子域都安全,且只接受 HTTPS 请求。该方式的另外一种变体是 header 中带有 加密的 token,请求中再带该 token。

  2. 同站 Cookie 属性(SameSite Cookie Attribute)
    由 google 提出,阻止浏览器跨域发送 cookie。设置以下:

Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict
Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax
浏览器全局生效,但要注意,该技术目前处于草案状态,实现的并不彻底。不推荐做为主要的防护方式
  1. 使用自定义请求头(Use of Custom Request Headers)
    自定义请求头则只限于同域,在跨域时须要服务端指定其余携带的 Headers。该方式可保护 ajax 请求,不能保护 form 请求,跨域 CORS 设置

  2. 用户交互式防护(User Interaction Based CSRF Defense)

    用户交互式会更为方便,好比使用
  • 二次认证(密码或者更强)
  • 一次性 token
  • 验证码

仅限于高度敏感的场景

  1. 登陆 SCRF(Login CSRF)

    登陆页面也会产生 CSRF 攻击,在用户已经登陆的状况下,防范方式是未登陆前产生一个pre-session(可以使用以上三种技术)

其余:三次提交验证,使用 content-type 的 pre-flight

Cross Site Scripting (XSS)

本文地址: https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

攻击方式: Strored, Reflected 和 DOM XSS。

Stored: 将注入攻击脚本存储在目标服务器上,好比数据库,消息论坛,访客日志,评论等,受害者从服务器获取存储的信息时获得了恶意脚本, 为 Type-I 攻击

Reflected: 反射攻击的脚本不在 web 服务器上,主要是在错误提示,搜索结果,或者其余返回信息有一部分输入。反射攻击在其余路由上,好比邮件或者其余网站,当用户点恶意连接,提交了钓鱼表单或者只是浏览了恶意站点,恶意代码会被带到受攻击的网站。Type-II 攻击

DOM XSS 会在后面讲到。

注意,请使用已经成熟的一些库来实现,避免遗漏。一般实现 rule2 和3 便可知足大部分状况的需求。

XSS 预防规则

  1. 不在未容许的位置插入不信任的数据(Never Insert Untrusted Data Except in Allowed Locations)
  2. 插入 HTML 片断前须要进行转义(HTML Escape Before Inserting Untrusted Data into HTML Element Content)
    ,包括一些执行的上下文,如 script,style,事件. 使用 16 进制的实体
  3. HTML 普通属性转义(Attribute Escape Before Inserting Untrusted Data into HTML Common Attributes),仅限于普通属性如w idth,name,value等,属性设置不能用于复杂属性如 href, src, style 或者其余事件处理 onmouseover。
  4. js 代码在插入js 数据值时转义(JavaScript Escape Before Inserting Untrusted Data into JavaScript Data Values), setInterval 等函数是没法转为可靠数据的。HTML 中的 JSON 字符串一样须要转义,使用 JSON.parse 而不是 eval
  5. css 转义并在插入style 属性值前严格验证(CSS Escape And Strictly Validate Before Inserting Untrusted Data into HTML Style Property Values), url,behavior,custom 不能使用。例如:
{ background-url : "javascript:alert(1)"; }  // and all other URLs
 { text-size: "expression(alert('XSS'))"; }   // only in IE
  1. 插入 URL 参数时对URL 进行转义 (URL Escape Before Inserting Untrusted Data into HTML URL Parameter Values)
  2. 使用专用库来过滤 HTML 标签(Sanitize HTML Markup with a Library Designed for the Job)
  3. 阻止基于 DOM 的 XSS 攻击(Prevent DOM-based XSS)

其余预防方式

  1. 使用 httpOnly 的 cookie,防止cookie 被读取
  2. 实现 Content Security Policy. 这是解决 XSS 攻击的一个好方式,即建立来源白名单,若是 javascript,css,image 等。
Content-Security-Policy: default-src: 'self'; script-src: 'self' static.domain.tld
  1. 使用自动转换模板系统(Use an Auto-Escaping Template System)
  2. 使用 X-XSS-Protection 返回头(Use the X-XSS-Protection Response Header)

总结请参考 https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

数据类型 上下文 样例 防护方式
String HTML Body <span>UNTRUSTED DATA</span> HTML 实体转义
String 安全的 HTML 属性 <input type="text" name="fname" value="UNTRUSTED DATA"> 1. 侵入式转换为 > 256 为&#xHH; 格式.
2. 只在安全白名单内的属性添加不信任的数据
3. 针对不安全的属性如 background,id , name 进行严格验证
String GET 参数 <a href="/site/search?value=UNTRUSTED DATA">clickme</a> 使用 %HH 格式对 GET 中参数进行转义
String src 或 href 中不受信任的 URL <a href="UNTRUSTED URL">clickme</a>
<iframe src="UNTRUSTED URL" />
1. 规范化输入
2. URL 验证
3. 安全 URL 核实
4. 只使用安全白名单内的 HTTP 或 HTTPS 地址,避免使用 JS 协议打开新窗口
5. 属性转义
String Css 值 <div style="width: UNTRUSTED DATA;">Selection</div> 1. 使用严格的结构验证
2. CSS 16进制转义
3. 设计良好的 CSS 特性
String javascript 变量 <script>var currentValue='UNTRUSTED DATA';</script>
<script>someFunction('UNTRUSTED DATA');</script>
1. 确保 js 变量使用引号起起来
2. js 16 进制转义
3. js Unicode 转义
4. 避免 \",\',\\的转义
HTML HTML Body <div>UNTRUSTED HTML</div> 对 HTML 的标签等进行验证
String DOM XSS <script>document.write("UNTRUSTED INPUT: " + document.location.hash);<script/> 参见 DOM 的 XSS 攻击

DOM XSS 防范

DOM XSS 和 stored reflected 攻击的主要区别在于应用中攻击注入的位置。 relected 和 stored 都是服务端注入,而 DOM 注入则是客户端注入。XSS 攻击老是在客户端执行的。本部分中HTML 等攻击都是由 Javascript 执行的,因此称为子上下文。

本部分摘自: https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet

防范规则

  1. 插入 HTML 子上下文未受信任的数据时时须要先对 HTML 转义而后是 JavaScript 转义(HTML Escape then JavaScript Escape Before Inserting Untrusted Data into HTML Subcontext within the Execution Context)
  2. 在为 HTML 属性插入不受信任的数据时须要进行 javascript 转义(JavaScript Escape Before Inserting Untrusted Data into HTML Attribute Subcontext within the Execution Context)
  3. 在向事件监听和 js 代码插入未知数据时必定要当心(Be Careful when Inserting Untrusted Data into the Event Handler and JavaScript code Subcontexts within an Execution Context)
  4. 对要插入的 CSS 属性值进行 JS 转义(JavaScript Escape Before Inserting Untrusted Data into the CSS Attribute Subcontext within the Execution Context)
  5. 对要插入的 URL 属性进行 URL 转义(URL Escape then JavaScript Escape Before Inserting Untrusted Data into URL Attribute Subcontext within the Execution Context)
  6. 添加 DOM 时使用安全的函数或方法(Populate the DOM using safe JavaScript functions or properties),好比使用 textContent
  7. 修复 DOM 跨域脚本攻击(Fixing DOM Cross-site Scripting Vulnerabilities)

XSS 攻击难防范是因为攻击面广且浏览器之间有差别。下面是推荐实践:

  1. 不受信任的数据应该只做为展现的文本
  2. 使用模板的时候老是对 js 代码进行转义并将数据限定在引号以内
  3. 使用 document.createElement("xx"), element.setAttribute(), element.appendChild 等来构建动态的界面
  4. 避免 InnerHtml 等 HTML 渲染方法使用不受信任的数据
  5. 避免使用隐式 eval 的函数, 好比 setTimeout等。转义的正确方式是服务转换外部的的数据,客户端只转义子上下文好比 dom 方法的数据。
  6. 限制未知数据在正确的操做下使用,即不要使意料以外的生效
  7. URL 转义时要注意字符集的问题
  8. 限制 object[x] 使用的范围
  9. 让代码运行在 es5 下或者沙盒内,增长 API 解码难度
  10. 不要使用 evel 来解析 JSON 对象

推荐的转义库:esapi, Apache Commons String Utils,Jtidy, 其余本身公司的实现
最后,innerText 在某些标签下仍旧可被执行,火狐也不支持该方法。

Content Type 选项

主要是为了阻止 Chrome 和 IE 对服务端返回的类型进行文本 mime 类型嗅探。
减小在上传或下载文件时因为用户设置其余名称会致使文件后缀变为其余类型,好比可执行文件。

即设置 X-Content-Type-Options
nosniff, 好比nginx

add_header X-Content-Type-Options "nosniff" always;

X-Frame-Options(XFO)

保护用户避免点击劫持, 主要指浮层或者连接篡改。该信息能够设置为 DENY(代表当前站点不能够被 iframe 嵌入) 或者 SAMEORIGIN(同一来源),ALLOW-FROM https://e.com 指定站点

nginx 设置:

add_header X-Frame-Options "SAMEORIGIN" always;

Content Security Policy

该属性表示网站内容如何载入且在哪里容许载入,也能够用于解决点击劫持的问题。
这个属性可设置内容比较多,解决一些 CSRF,XSS 问题。 CSP 设置决定哪些内容是属于白名单以内的。

Content-Security-Policy: script-src 'self'

参见:https://content-security-policy.com/
该属性可保护的内容包括:

default-src: 全部资源可容许的路径,主要是用于 fallback
script-src: 定义 script 可被执行的来源
object-src: 定义能够加载插件的的来源, 针对<object>, <embed> or <applet>
style-src: 定义css 来源
Img-src: 图片来源
media-src: 定义 video 和 audio 加载 来源
frame-src: 定义哪一个来源能够加载  frame
frame-ancestors: 可引用当前页面的配置,设置为 none 几乎等同于 X-Frame-Options: DENY
font-src: 定义宝体来源
connect-src: 哪一个来源能够加载  script 接口,针对的是 AJAX WEBSOCKET 和 EventSource
form-action: 哪一个来源能够用于加载form 元素
sandbox: 哪一个来源使用沙盒
script-none: script 元素加载哪一个形式的的脚本
plugin-types: 
reflected-xss: 
report-uri: 报告冲突的网址,即策略拦截的后上报地址

Content-Security-Policy: default-src https: 容许加载 https 任何域

Content-Security-Policy: default-src https://scotthelme.co.uk:443 限定了加载地址

Content-Security-Policy: default-src https://scotthelme.co.uk:* 可任意端口

none 阻止加载此类资源

self 只加载当前来源

unsafe-inline 容许使用行内的 js 和 css

unsafe-eval 容许使用 eval

CSP 包含的内容仍是比较多,使用的时候建议去阅读原文

相关文章
相关标签/搜索