WEB安全

WEB安全

XSS 攻击

什么是XSS攻击?

Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者经过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。php

为了区分CSS,改成XSS。html

XSS 的本质是:恶意代码未通过滤,与网站正常的代码混在一块儿;浏览器没法分辨哪些脚本是可信的,致使恶意脚本被执行。前端

XSS分类

根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。数据库

类型 存储区 插入点
存储型 XSS 后端数据库 HTML
反射型 XSS URL HTML
DOM 型 XSS 后端数据库/前端存储/URL 前端 JavaScript

存储区:恶意代码存放的位置。后端

插入点:由谁取得恶意代码,并插入到网页上。浏览器

存储型XSS

这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。安全

反射型XSS

反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。bash

反射型 XSS 漏洞常见于经过 URL 传递参数的功能,如网站搜索、跳转等。服务器

因为须要用户主动打开恶意的 URL 才能生效,攻击者每每会结合多种手段诱导用户点击。cookie

POST 的内容也能够触发反射型 XSS,只不过其触发条件比较苛刻(须要构造表单提交页面,并引导用户点击),因此很是少见。

DOM型XSS

DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其余两种 XSS 都属于服务端的安全漏洞。

XSS预防

  • 攻击者提交恶意代码
  • 浏览器执行恶意代码

攻击者提交恶意代码

输入侧过滤可以在某些状况下解决特定的 XSS 问题,但会引入很大的不肯定性和乱码问题。在防范 XSS 攻击时应避免此类方法。

浏览器执行恶意代码

  • 防止 HTML 中出现注入
  • 防止 JavaScript 执行时,执行恶意代码

预防存储型和反射型 XSS 攻击

存储型和反射型 XSS 都是在服务端取出恶意代码后,插入到响应 HTML 里的,攻击者刻意编写的“数据”被内嵌到“代码”中,被浏览器所执行。

预防这两种漏洞,有两种常见作法:

1.改为纯前端渲染,把代码和数据分隔开。

2.对 HTML 作充分转义。

纯前端渲染

1.浏览器先加载一个静态 HTML,此 HTML 中不包含任何跟业务相关的数据。

2.而后浏览器执行 HTML 中的 JavaScript。

3.JavaScript 经过 Ajax 加载业务数据,调用 DOM API 更新到页面上。

在纯前端渲染中,咱们会明确的告诉浏览器:下面要设置的内容是文本(.innerText),仍是属性(.setAttribute),仍是样式(.style)等等。浏览器不会被轻易的被欺骗,执行预期外的代码了。

转义HTML

若是拼接 HTML 是必要的,就须要采用合适的转义库,对 HTML 模板各处插入点进行充分的转义。

经常使用的模板引擎,如 doT.js、ejs、FreeMarker 等,对于 HTML 转义一般只有一个规则,就是把 & < > " ' / 这几个字符转义掉,确实能起到必定的 XSS 防御做用,但并不完善:

XSS 安全漏洞 简单转义是否有防御做用
HTML 标签文字内容
HTML 属性值
CSS 内联样式
内联 JavaScript
内联 JSON
跳转连接

预防 DOM 型 XSS 攻击

DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码自己不够严谨,把不可信的数据看成代码执行了。

在使用 .innerHTML、.outerHTML、document.write() 时要特别当心,不要把不可信的数据做为 HTML 插到页面上,而应尽可能使用 .textContent、.setAttribute() 等。

若是用 Vue/React 技术栈,而且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 阶段避免 innerHTML、outerHTML 的 XSS 隐患。

DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等, 标签的 href 属性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串做为代码运行。若是不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免。

其余防御措施

Content Security Policy

禁止加载外域代码,防止复杂的攻击逻辑。

禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。

禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。

禁止未受权的脚本执行(新特性,Google Map 移动版在使用)。

合理使用上报能够及时发现 XSS,利于尽快修复问题。
复制代码

输入内容长度控制

对于不受信任的输入,都应该限定一个合理的长度。虽然没法彻底防止 XSS 发生,但能够增长 XSS 攻击的难度

其余安全措施

HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也没法窃取此 Cookie。

验证码:防止脚本冒充用户提交危险操做。

XSS攻击总结

  • 利用模板引擎:开启模板引擎自带的 HTML 转义功能
  • 避免内联事件
  • 避免拼接 HTML
  • 主动检测和发现

CSRF攻击

什么是CSRF攻击?

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕事后台的用户验证,达到冒充用户对被攻击的网站执行某项操做的目的。

CSRF攻击的特色

  • 攻击通常发起在第三方网站,而不是被攻击的网站。被攻击的网站没法防止攻击发生
  • 攻击者利用受害者在被攻击网站的登陆凭证,冒充受害者提交操做,而不是直接窃取数据。
  • 整个过程攻击者并不能得到登陆凭证,只是冒用
  • 跨站请求能够用各类方式:图片URL、超连接、CORS、Form提交等等。部分请求方式能够直接嵌入在第三方论坛、文章中,难以进行追踪。

CSRF分类

GET类型的CSRF

<img src="http://bank.example/withdraw?amount=10000&for=hacker" > 
复制代码

Post类型的CSRF

<form action="http://bank.example/withdraw" method=POST>

    <input type="hidden" name="account" value="xiaoming" />

    <input type="hidden" name="amount" value="10000" />

    <input type="hidden" name="for" value="hacker" />

</form>

<script> document.forms[0].submit(); </script> 
复制代码

访问该页面,表单会自动提交。

连接类型的CSRF

连接类型的CSRF并不常见,比起其余两种用户打开页面就中招的状况,这种须要用户点击连接才会触发。这种类型一般是在论坛中发布的图片中嵌入恶意连接,或者以广告的形式诱导用户中招,攻击者一般会以比较夸张的词语诱骗用户点击,例如:

<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">

  重磅消息!!

  <a/>
复制代码

CSRF防范

  • 阻止不明外域访问
  1. 同源检测
  2. Samesite Cookie
  • 提交时要求附加本域才能获取的信息
  1. CSRF Token
  2. 双重Cookie验证

同源检测

既然CSRF大多来自第三方网站,那么咱们就直接禁止外域(或者不受信任的域名)对咱们发起请求。

* Origin Header

* Referer Header
复制代码
  • 使用Origin Header肯定来源域名
  • 使用Referer Header肯定来源域名

CSRF Token 的防御策略

  1. 将CSRF Token输出到页面

用户打开页面的时候,服务器给这个用户生成一Token,但不能放到cookie中,不然仍是会被攻击者冒用。因此要存在服务器的session中

  1. 页面提交的请求携带这个Token
  2. 服务器眼睁睁Token是否正确

分布式校验

大型网站,使用session存储CSRF Token会带来很大压力。并且如今都是分布式部署,一个用户发送的屡次HTTP请求可能不在一台服务器上,可能会获取不到session数据,所以分布式集群中CSRF Token存储在Redis之类的公共存储空间

使用Session存储,读取和验证Token会引发比较大的复杂度和性能问题。

ETP方式

这种方法的Token是一个计算出来的结果,而非随机生成的字符串。这样在校验时无需再去读取存储的Token,只用再次计算一次便可。

双重Cookie验证

那么另外一种防护措施是使用双重提交Cookie。利用CSRF攻击不能获取到用户Cookie的特色,咱们能够要求Ajax和表单请求携带一个Cookie中的值。

  1. 用户访问页面,注入一个cookie
  2. 在前端向后端发起请求,取出cookie,添加到url的参数中
  3. 后端接口验证

优势

  • 无需使用Session,适用面更广,易于实施。

  • Token储存于客户端中,不会给服务器带来压力。

  • 相对于Token,实施成本更低,能够在先后端统一拦截校验,而不须要一个个接口和页面添加。

缺点

  • Cookie中增长了额外的字段。

  • 若是有其余漏洞(例如XSS),攻击者能够注入Cookie,那么该防护方式失效。

  • 难以作到子域名的隔离。

  • 为了确保Cookie传输安全,采用这种防护方式的最好确保用整站HTTPS的方式,若是还没切HTTPS的使用这种方式也会有风险。

Samesite Cookie 属性

Samesite=Strict

这种称为严格模式,代表这个 Cookie 在任何状况下都不可能做为第三方 Cookie,绝无例外

Set-Cookie: foo=1; Samesite=Strict

Set-Cookie: bar=2; Samesite=Lax

Set-Cookie: baz=3
复制代码

咱们在 a.com 下发起对 b.com 的任意请求,foo 这个 Cookie 都不会被包含在 Cookie 请求头中,但 bar 会。举个实际的例子就是,假如淘宝网站用来识别用户登陆与否的 Cookie 被设置成了 Samesite=Strict,那么用户从百度搜索页面甚至天猫页面的连接点击进入淘宝后,淘宝都不会是登陆状态,由于淘宝的服务器不会接受到那个 Cookie,其它网站发起的对淘宝的任意请求都不会带上那个 Cookie。

Samesite=Lax

这种称为宽松模式,比 Strict 放宽了点限制:假如这个请求是这种请求(改变了当前页面或者打开了新页面)且同时是个GET请求,则这个Cookie能够做为第三方Cookie。

注意

另一个问题是Samesite的兼容性不是很好,现阶段除了重新版Chrome和Firefox支持之外,Safari以及iOS Safari都还不支持,现阶段看来暂时还不能普及。

并且,SamesiteCookie目前有一个致命的缺陷:不支持子域。例如,种在topic.a.com下的Cookie,并不能使用a.com下种植的SamesiteCookie。这就致使了当咱们网站有多个子域名时,不能使用SamesiteCookie在主域名存储用户登陆信息。每一个子域名都须要用户从新登陆一次。

仅用于我的整理,参考:

Web安全

相关文章
相关标签/搜索