固定链接 浅谈前端 XSS 攻击和防御

浅谈前端 XSS 攻击和防御

浅谈前端 XSS 攻击和防御

1. 概览

XSS: Cross-site Scripting

XSS 是一种 Web 应用中常见的安全漏洞。

XSS 允许攻击者在 Web 页面植入脚本,从而被其他用户看到。XSS 缺陷可能会被攻击者利用来获取基于同源策略的登录权限。

为了获取什么数据:

  • 用户敏感信息,cookies
  • 发送 HTTP 请求
  • 操作 dom 元素

后果:

  • Cookie 盗取。 获取 sessionID
    • TODO 获取 sessionID 能干啥?
  • keylogging(键盘监听)。将用户操作键盘的事件进行监听,获取登录密码或者银行密码等敏感信息。
  • phishing ( 网络欺诈 ) 。添加一个虚拟的登录 form,提交时到自己的 Server,从而获取用户的敏感信息。

小结:

  • 如果一个攻击者,访问你的网站,能够在其他用户的浏览器执行脚本,那么你的网站和其他用户的安全会受到攻击。

2. XSS 攻击

相关者:

  • the website
    • the website’s database
  • victim 普通用户
  • attacker
    • attacker’s server

场景示例:

这个示例中 attackers 的最终目标是窃取 victim 的 Cookie。

xss攻击示意图

XSS 类型:
* Persistent XSS ( 持久型 ) 恶意脚本被存储在 Website 的数据库中
* Reflected XSS ( 反射型 ) 当 victim 发请求时脚本才会被执行
* DOM-based XSS ( DOM 依赖型 ) 错误发生在客户端代码

反射型 XSS 攻击:

反射型攻击

反射型攻击,恶意字符串会作为 victim 到 Website 请求的一部分。

  • 反射型攻击如何实现

    反射型 XSS 攻击看起来似乎是无害的,因为它会要求 victim 主动将恶意代码发送至服务器,所以似乎没有方法攻击网站。有两种常用的方式使 victim 主动执行反射型攻击的恶意脚本。

    1. 钓鱼链接 -> 针对特定人群
    2. 钓鱼网站或者钓鱼广告 -> 无特定针对

DOM XSS:

DOM依赖型XSS

如何区分 DOM 依赖型攻击:

  • 在传统的 XSS,恶意代码是在页面加载时执行,会作为 server 传送时执行
  • DOM XSS 的恶意代码是在页面加载完毕后执行,将用户输入的不安全代码作为合法脚本去执行导致的。

为什么 DOM XSS 很重要:

  • 复杂应用使用客户端渲染
  • 客户端渲染时使用 xhr + js 渲染 DOM
  • 即使 sServer 安全,也不能保证客户端会免受攻击

对 server 不可见的 DOM XSS:

  • 对 URL 里面#后面的参数处理不当
  • 使用 Localstorage 的数据不当
  • 使用 IndexedDB 的数据不当

3. 防御 XSS

方法

  • 转码
  • 校验

这两种方法的共同点:

  • Context(上下文)。 安全处理需要根据页面不同位置的输入和不同。
  • Inbound/Outbound。 既可以在收到input的时候做转码(inbound),可也在页面插入时(outbound)再做转码。
  • Client/Server。 可以在服务器端,也可以在客户端做校验。视情况而定。

Input handling contexts

Context Example
HTML 元素内容 <div>userInput</div>
HTML 属性值 <input value="userInput">
URL Query 值 http://example.com/?parameter=userInput
css value color: userInput
Javascript value var name = “userInput”

为什么要区分这些情况

Application code <input value="inputCode">
Malicious string "><script>...</script><input value="
Resulting code <input value=""><script>...</script><input value="">

Inbound/Outbound

  • 需要区分各种输入情况
  • 有可能有多个 DOM 是一个数据源
    => 如果在获取数据时做处理 ( Inbound ) 不 UR 在显示时再转换数据(Outbound)应该作为主要防御方法。

在哪里做防御

  • Server
  • Client

Encoding 转码

Encoding 会使浏览器将脚本转换成 data 显示。如:<and> => <and>

=> :

在客户端转码

Context Method / property
HTML element content node.textContent = userInput
HTML attribute value element.setAttribute(attribute, userInput) or element[attribute] = userInput
url query window.encodeURIComponent(userInput)
CSS value element.style.property = userInput

局限性

=>:

编辑器,允许用户自定义 HTML,如果转码会有问题。 需要用 Validation 来处理。

Validation 校验

允许部分如 <em></em>, 过滤如 <script></script>
两种主要实践:

  • 分类策略(Classification strategy) 黑名单或者白名单方式区分
  • 校验结果(Validation outcome)

分类策略

  1. 黑名单
    • 复杂
      javascript:
      Javascript:
      javascript:
    • 需要持续更新
  2. 白名单
    • 简单
    • 持久

结果校验

  • Rejection 直接拒绝,对于不符合要求的输入直接过滤。
  • Sanitisation 清理,将不合理的部分去掉,保留符合要求的部分。

使用什么防护技术

  • 转码作为主要防线
  • 使用 Inbound 校验方式处理特殊的输入,如 HREF 里面的 JavaScript
  • 第三道防线,CSP

CSP

安全防护稍有不慎便会危害网站,Content Security Policy (CSP)可以减少风险。

CSP 约束了网站信任的来源,对于下面的情况进行约束:

  • 不被信任的来源。外部资源 ( JS, CSS ) 不会被加载
  • 行内资源。行内 JS 和 CSS 不会被执行。
  • Eval。 Eval不能被使用。
如何启用 CSP

特殊的 header:

CSP 语法

示意:

Directives:

  • connect-src
  • font-src
  • frame-src
  • img-src
  • media-src
  • object-src
  • script-src
  • style-src

Source=expression

  • 具体指定

  • none 不允许引用任何外部资源
  • self 只允许本域
  • unsafe-inline 允许行内资源
  • unsafe-eval 允许eval

注意: 只要 CSP 被使用,Inline 和 Eval 就被禁用,只有通过上面的指定才可允许被使用。

示例

总结

XSS 概览

如果对用户输入的处理不够安全,则 XSS 可以通过代码注入进行攻击,一次成功的 XSS 攻击允许攻击者在被攻击者的浏览器端执行有害的 JS 代码,这会危害网站和用户的利益。

XSS 攻击

常见的 XSS 攻击主要有三类:

  • 持久化攻击,特点是恶意代码来源为网站的数据库。
  • 反射型攻击的来源为受害者主动发起的请求。
  • 基于 DOM 的 XSS 攻击主要是由于客户端代码缺陷导致。

如何防御

最重要的防御方式需要对 Input 输入进行处理。

通常我们需要对用户的输入进行编码,在某些不适合进行编码的场合下,需要对输入进行校验,而根据不同的输入类型,需要选择不同的处理的方式。

想要对 XSS 攻击进行彻底防御,我们需要在客户端和服务器端都进行输入端的处理。

CSP 为我们的防御提供了额外的一层保障。

思维导图

思维导图


本文作者:冯白杨

相关链接:https://excess-xss.com/

您的留言将激励我们越做越好

用户评论(2)

  1. 匿名

    写的很好呀~

  2. 152*****694

    很有帮助,赞!