XSS 攻击:深入剖析“暗藏在网页中的脚本“与防御之道
XSS (Cross-Site Scripting),即跨站脚本攻击,是 Web 安全领域中最常见也最具危害性的漏洞之一。攻击者通过巧妙的手段将恶意的 JavaScript、HTML 或其他脚本代码注入到正常的 Web 页面中。当其他用户浏览这些被注入了恶意脚本的页面时,这些脚本就会在用户的浏览器中执行,从而可能导致一系列严重后果,如 Cookie 窃取、会话劫持、钓鱼欺骗、键盘记录、网页篡改,甚至控制用户的浏览器行为。
一、XSS 攻击的"家族成员":三种主要类型
XSS 攻击根据恶意脚本的注入方式和触发时机的不同,主要可以分为以下三种类型:
1. 存储型 XSS (Stored XSS / Persistent XSS):潜伏的毒药
存储型 XSS 是最具破坏力的一种 XSS 类型。攻击者将包含恶意脚本的数据提交给 Web 应用,而 Web 应用未经过充分过滤或编码就将这些数据存储到服务器端(例如,存储在数据库、文件系统、消息队列等)。当其他用户访问某个包含了这些被污染数据的页面时,服务器会将恶意脚本原封不动地(或未充分处理地)发送给用户的浏览器,导致恶意脚本在用户的浏览器上下文中执行。
攻击流程:
- 攻击者在一个允许用户输入内容的地方(如文章评论区、用户个人资料、论坛帖子、商品评价等)提交包含恶意 JavaScript 的内容。
例如,在评论中输入:<script>alert('XSS by Attacker: Your session cookie is ' + document.cookie)</script> - Web 应用后端未对该输入进行有效的过滤或编码,直接将其存储到数据库中。
- 当其他合法用户(受害者)浏览包含这条恶意评论的页面时,服务器从数据库中读取该评论内容,并将其嵌入到 HTML 页面中返回给用户的浏览器。
- 用户的浏览器解析 HTML 时,会执行嵌入的恶意 JavaScript 代码,此时弹窗显示用户的 Cookie,或者恶意脚本可能将 Cookie 发送到攻击者控制的服务器。
危害:由于恶意脚本被永久存储在服务器上,任何访问该受污染页面的用户都可能受到攻击,影响范围广,持续时间长。
2. 反射型 XSS (Reflected XSS / Non-Persistent XSS):一触即发的陷阱
反射型 XSS 的恶意脚本通常不会存储在服务器端,而是作为 HTTP 请求的一部分(例如,URL 参数、表单数据)发送给服务器。服务器在处理请求后,未经充分处理就直接将请求中包含的恶意脚本"反射"回用户的浏览器,并在当前页面中执行。
攻击流程:
- 攻击者构造一个包含恶意脚本的特制 URL。例如,一个搜索功能,其 URL 可能为 https://example.com/search?query=<script>alert('Reflected XSS: ' + document.domain)</script>。
- 攻击者通过各种手段(如社交工程、钓鱼邮件、恶意广告)诱导受害者点击这个特制的 URL。
- 受害者的浏览器向 example.com 发送请求,其中包含了恶意脚本作为 query 参数的值。
- 服务器端的搜索功能可能只是简单地将 query 参数的值直接嵌入到搜索结果页面中,例如:<div>您搜索的是:<script>alert('Reflected XSS: ' + document.domain)</script></div>。
- 用户的浏览器收到响应并解析 HTML 时,会执行这个被"反射"回来的恶意 JavaScript 代码。
危害:反射型 XSS 通常需要用户交互(如点击恶意链接)才能触发,其影响通常局限于点击了该链接的单个用户会话。但它常被用于钓鱼攻击和针对性攻击。
3. DOM 型 XSS (DOM-based XSS):客户端的暗流
DOM 型 XSS 是一种更为隐蔽的 XSS 类型,其特殊之处在于恶意脚本的注入和执行完全发生在客户端的浏览器中,不一定需要与服务器进行直接的数据交互来传递恶意代码。它通常是由于客户端 JavaScript 代码在修改页面 DOM (Document Object Model) 结构时,不安全地处理了来自用户可控数据源(如 URL 的 fragment 部分 document.location.hash、document.URL、document.referrer,或者通过 window.name、localStorage 等客户端存储)的数据而导致的。
攻击流程:
-
攻击者构造一个包含恶意脚本片段的 URL,通常利用 URL 的 fragment (锚点 # 之后的部分),因为 fragment 不会发送到服务器。
例如:https://example.com/page#default=<img src=x οnerrοr=alert('DOM-based_XSS')> -
网站的客户端 JavaScript 代码可能存在如下逻辑,它从 URL 的 fragment 中读取 default 参数的值,并将其直接写入到页面的某个 DOM 元素中:
// 不安全的客户端代码示例 var defaultTopic = window.location.hash.substring(window.location.hash.indexOf("default=") + 8); document.getElementById("topic").innerHTML = decodeURIComponent(defaultTopic);
-
受害者点击攻击者构造的恶意链接。
-
客户端 JavaScript 执行上述代码,从 #default=<img src=x οnerrοr=alert('DOM-based_XSS')> 中提取出恶意代码 <img src=x οnerrοr=alert('DOM-based_XSS')>,并通过 innerHTML 将其写入到 DOM 中。
-
浏览器在渲染更新后的 DOM 时,会解析并执行这个图片标签的 onerror 事件中的 JavaScript。
危害:DOM 型 XSS 的检测和防御相对更复杂,因为它发生在客户端,传统的服务器端输入过滤和输出编码可能无法完全覆盖。需要仔细审计客户端 JavaScript 代码。
二、XSS 攻击的防御之道:多层过滤,编码为王
防御 XSS 攻击的核心原则是"不信任任何用户输入",并对所有在页面上展示的用户数据进行恰当的处理。以下是主要的防御策略:
1. 输入验证与过滤 (Input Validation and Sanitization)
虽然不是防御 XSS 的根本手段,但作为第一道防线,对用户输入进行严格的验证和过滤仍然是必要的。
- 验证:检查输入数据的类型、格式、长度、范围是否符合预期。例如,年龄字段应该是数字,邮箱地址应符合特定格式。
- 过滤/净化 (Sanitization):移除或替换用户输入中的潜在危险字符或 HTML 标签。例如,可以将 < 替换为 <,或者使用白名单机制只允许特定的安全 HTML 标签和属性。
局限性:
- 很难穷尽所有可能的攻击向量和绕过技巧。
- 过度严格的过滤可能误伤正常的用户输入,影响用户体验。
- 不应作为唯一的防御手段,因为攻击者总能找到新的方式绕过过滤规则。
2. 输出编码/转义 (Output Encoding/Escaping) - 核心防御手段
这是防御 XSS 攻击最根本、最有效的方法。其核心思想是:当需要在 HTML 页面中展示来自用户的数据时,必须根据数据最终要插入的 HTML 上下文,对数据进行恰当的编码或转义,以确保浏览器将这些数据仅仅作为"纯文本数据"来显示,而不是作为"可执行的 HTML 或 JavaScript 代码"来解析和执行。
不同上下文的编码策略:
-
在 HTML 标签内容中输出数据 (Element Content):例如 <div>用户输入的内容</div>。
- 策略:进行 HTML 实体编码 (HTML Entity Encoding)。将特殊字符如 < 编码为 <,> 编码为 >,& 编码为 &," 编码为 ",' 编码为 ' (或 ')。
- 示例 (Java):使用 OWASP Java Encoder 或 Apache Commons Lang 的 StringEscapeUtils.escapeHtml4()。
-
在 HTML 属性值中输出数据 (HTML Attributes):例如 <input type="text" value="用户输入的内容">。
- 策略:同样进行 HTML 实体编码,但要确保属性值被引号(单引号或双引号)包围。对于未被引号包围的属性值,情况更复杂,应避免。
- 注意:避免将用户数据直接插入到事件处理器属性(如 onclick)、href 或 src 属性(特别是 javascript: 伪协议)中。如果必须这样做,需要更严格的上下文特定编码和验证。
-
在 JavaScript 代码块中输出数据 (Inside JavaScript Blocks):例如 <script>var username = "用户输入的内容";</script>。
- 策略:进行 JavaScript Unicode 转义或十六进制转义。确保所有非字母数字字符都被转义,以防止用户输入破坏 JavaScript 语法或注入新代码。
- 强烈建议:尽量避免将用户数据直接嵌入到 JavaScript 代码块中。更好的做法是将数据存储在 HTML 元素的 data-* 属性中(经过 HTML 实体编码),然后通过 JavaScript 安全地读取这些属性值。
- 如果必须在 JSON 上下文中使用,确保使用安全的 JSON 序列化库,并正确设置 <script> 标签的 type 属性(如 application/json),然后通过 JSON.parse() 解析。
-
在 CSS 样式中输出数据 (Inside CSS Blocks):例如 <style>body { background-image: url("用户输入的内容"); }</style>。
- 策略:进行 CSS 转义。CSS 中的 expression() 和某些 URL 上下文也可能导致 XSS。
- 强烈建议:尽量避免将用户数据直接嵌入到 CSS 样式中。如果必须,确保只允许安全的 CSS 属性和值。
-
在 URL 参数中输出数据 (Inside URLs):例如 <a href="/search?query=用户输入的内容">搜索</a>。
- 策略:进行 URL 编码 (Percent Encoding)。
关键原则:上下文是王道 (Context is King)。必须根据数据最终输出的位置选择正确的编码方式。许多现代 Web 框架和模板引擎内置了自动上下文感知的输出编码功能,应优先使用这些功能。
3. 内容安全策略 (CSP - Content Security Policy)
CSP 是一种强大的纵深防御机制,它允许网站管理员通过 HTTP 头部 Content-Security-Policy 来精确控制浏览器可以加载和执行哪些来源的资源(包括脚本、样式表、图片、字体、框架、媒体等)。
工作原理:
CSP 定义了一系列指令(如 script-src、style-src、img-src、default-src),每个指令可以指定允许加载相应类型资源的来源(如 self 表示同源、特定的域名、none 表示禁止等)。
如何帮助防御 XSS?
- 通过严格的 script-src 指令,可以禁止内联脚本 (inline script) 的执行(除非使用 nonce 或 hash 明确允许),并限制只能从可信的外部域加载脚本。这使得即使攻击者成功注入了脚本代码,浏览器也会因为 CSP 策略的限制而拒绝执行它。
- 例如,一个严格的 CSP 策略可能是:Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.trusted.com; object-src 'none';
实施CSP的挑战:
- 配置可能相对复杂,需要仔细规划和测试,以避免阻止正常的网站功能。
- 对于大型和老旧的应用,引入 CSP 可能需要较大的改动。
4. 设置 HttpOnly Cookie
虽然 HttpOnly 属性本身不直接阻止 XSS 攻击的发生,但它能有效地降低 XSS 攻击成功后的危害,特别是防止会话 Cookie 被恶意脚本窃取。
工作原理:
当一个 Cookie 被设置为 HttpOnly 时,它将不能通过客户端 JavaScript 的 document.cookie API 来访问。这个 Cookie 仍然会随着 HTTP 请求发送到服务器,但无法被页面内的脚本读取。
如何设置:
在服务器设置 Cookie 时,添加 HttpOnly 标志。
例如,在 Java Servlet 中:
Cookie cookie = new Cookie("sessionID", "xyz123");
cookie.setHttpOnly(true);
response.addCookie(cookie);
或者通过 HTTP 响应头 Set-Cookie: sessionID=xyz123; HttpOnly。
重要性:对于存储会话标识符等敏感信息的 Cookie,强烈建议始终启用 HttpOnly 属性。
5. 其他辅助措施
- 使用现代 Web 框架:许多现代 Web 框架(如 React, Angular, Vue.js, Django, Ruby on Rails, Spring MVC 等)都内置了针对 XSS 的防护机制,例如自动输出编码。合理使用这些框架提供的安全功能。
- 定期进行安全审计和代码审查:主动发现和修复 XSS 漏洞。
- 采用 Web 应用防火墙 (WAF):WAF 可以帮助识别和拦截已知的 XSS 攻击模式,但不能替代源代码层面的安全修复。
- 安全教育与培训:提高开发人员的安全意识和技能。
三、总结:XSS 防御是一场持续的战斗
XSS 攻击形式多样,层出不穷。防御 XSS 需要一个多层次、纵深防御的策略。
- 输入验证是第一道关卡。
- 基于上下文的输出编码/转义是核心和关键,必须严格执行。
- 内容安全策略 (CSP) 提供了强大的额外保护层。
- HttpOnly Cookie 能有效降低 Cookie 泄露的风险。
作为开发者,我们需要时刻保持警惕,理解不同类型 XSS 的攻击原理,掌握并运用正确的防御技术。只有这样,才能有效地保护我们的 Web 应用及其用户,免受 XSS 这种无处不在的脚本攻击的威胁。
相关文章:
XSS 攻击:深入剖析“暗藏在网页中的脚本“与防御之道
XSS (Cross-Site Scripting),即跨站脚本攻击,是 Web 安全领域中最常见也最具危害性的漏洞之一。攻击者通过巧妙的手段将恶意的 JavaScript、HTML 或其他脚本代码注入到正常的 Web 页面中。当其他用户浏览这些被注入了恶意脚本的页面时,这些脚…...

Scrapyd 详解:分布式爬虫部署与管理利器
Scrapyd 是 Scrapy 官方提供的爬虫部署与管理平台,支持分布式爬虫部署、定时任务调度、远程管理爬虫等功能。本文将深入讲解 Scrapyd 的核心功能、安装配置、爬虫部署流程、API 接口使用,以及如何结合 Scrapy-Redis 实现分布式爬虫管理。通过本文&#x…...
ai之pdf解析rapidOCR 的两种底层依赖PaddlePaddle 和ONNXRuntime
rapidocr_onnxruntime 与 rapidocr(通常指 rapidocr_paddle 或其他后端实现)的核心区别及使用推荐: 一、核心区别 特性rapidocr_onnxruntimerapidocr(以 rapidocr_paddle 为例)后端引擎基于 ONNXRuntime 推理框架&…...

驱动开发硬核特训 · 专题篇:Vivante GPU 与 DRM 图形显示体系全解析(i.MX8MP 平台实战)
视频教程请关注 B 站:“嵌入式Jerry”。 一、背景导读:GPU 与 DRM 到底谁负责“显示”? 在嵌入式 Linux 图形系统中,“画面怎么显示出来”的问题,表面看似简单,实则涉及多个内核子系统与用户态组件的协同&…...

C——猜数字游戏
前面我们已经学习了C语言常见概念,数据类型和变量以及分置于循环的内容,现在我们可以将这些内容结合起来写一个有趣的小游戏。下面正式开始我们今天的主题——猜数字游戏的实现。 猜数字游戏的要求: 1.电脑自动生成1~100的随机数。 2.玩家…...

C/C++实践(三)深入理解 C++ 三大特性之一:封装
一、封装的概念与核心思想 封装(Encencapsulation)是 C 面向对象编程(OOP)的三大核心特性之一,其本质是将数据(成员变量)和对数据的操作(成员函数)捆绑在一个逻辑单元&a…...
Filecoin存储管理:如何停止Lotus向特定存储路径写入新扇区数据
Filecoin存储管理:如何停止Lotus向特定存储路径写入新扇区数据 引言背景问题场景解决方案步骤1:修改sectorstore.json文件步骤2:重新加载存储配置步骤3:验证更改 技术原理替代方案最佳实践结论 引言 在Filecoin挖矿过程中&#x…...

1、RocketMQ 核心架构拆解
1. 为什么要使用消息队列? 消息队列(MQ)是分布式系统中不可或缺的中间件,主要解决系统间的解耦、异步和削峰填谷问题。 解耦:生产者和消费者通过消息队列通信,彼此无需直接依赖,极大提升系统灵…...

vue3 element-plus 输入框回车跳转页面问题处理
问题描述: 当页面搜索条件只有一个的情况下,输入框不管有没有值,回车后会跳转页面 解决办法,给表单添加 submit.prevent <el-form ref"ruleForm" :model"search" label-width"120px" class&qu…...
常见WEB漏洞----暴力破解
什么是暴力破解 暴力破解 (Brue Force) 是一种攻击方法 (穷举法),简称为“爆破”,黑客通过反复猜解和实验,旨在以暴力手段登入、访问目标主机获取服务,破坏系统安全,其属于 ATT&CK技术中的一种,常利用…...

快速入门深度学习系列(2)----损失函数、逻辑回归、向量化
针对深度学习入门新手目标不明确 知识体系杂乱的问题 拟开启快速入门深度学习系列文章的创作 旨在帮助大家快速的入门深度学习 写在前面: 本系列按照吴恩达系列课程顺序发布(说明一下为什么不直接看原笔记 因为内容太多 没有大量时间去阅读 所有作者需要一次梳理…...

[超详细,推荐!!!]前端性能优化策略详解
学习记录,部分内容版权归妙码学院 1.优化内容包括那些 其实前端的优化,整体粗略概括下来,白话之: 打开速度怎么变快再次打开速度怎么变快操作怎么才顺滑动画怎么保证流畅 2.性能优化 2.1首屏加载优化 在了解优化方法和策略之…...

数据提取之BeautifulSoup4快速使用
文章目录 一、前言二、概述2.1 安装2.2 初始化2.3 对象类型 三、遍历文档树3.1 子节点3.2 父节点3.3 兄弟节点3.4 前后节点3.5 节点内容3.5.1 文本内容3.5.2 属性值3.5.3 标签删除 四、搜索文档树4.1 find_all4.2 find4.3 CSS选择器4.4 更多 一、前言 官方文档:http…...

list类的详细讲解
【本节目标】 1. list的介绍及使用 2. list的深度剖析及模拟实现 3. list与vector的对比 1. list的介绍及使用 1.1 list的介绍 1. list 是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 2. list 的底层是双向链表结构&a…...

Linux系统下安装mongodb
1. 配置MongoDB的yum仓库 创建仓库文件 sudo vi /etc/yum.repos.d/mongodb-org.repo添加仓库配置 根据系统版本选择配置(以下示例为CentOS 7和CentOS 9的配置): CentOS 7(安装MongoDB 5.0/4.2等旧版本): In…...

kuka, fanuc, abb机器人和移动相机的标定
基础知识 : 一, 9点标定之固定相机标定: 图1: 固定位置相机拍照 因为相机和机器人的基坐标系是固定的, 所以在海康威视相机的9点标定功能栏中, 填上海康使用“圆查找”捕捉到的坐标值, 再将机器人显示的工具坐标系在基坐标系的实时位置pos_act值填入物理坐标X, Y中即可 图2:…...

Android Framework学习四:init进程实现
文章目录 init流程简介init源码执行顺序执行顺序 init进程的具体工作事项挂载文件系统设置 SELinuxSecondStageMaininit.rc启动zygote和serviceManager进程的重要性serviceManager工作原理 Framework学习之系列文章 init流程简介 下面图片主要围绕 Android 系统中init进程的运…...
Linux计划任务与进程
at 命令使用方法 at 命令可在指定时间执行任务,适用于一次性任务调度。以下是基本用法: 安装 atd 服务(如未安装) # Debian/Ubuntu sudo apt-get install at# CentOS/RHEL sudo yum install at启动服务 sudo systemctl start atd…...

Java引用RabbitMQ快速入门
这里写目录 Java发送消息给MQ消费者接收消息实现一个队列绑定多个消费者消息推送限制 Fanout交换机路由的作用Direct交换机使用案例 Topic交换机声明队列和交换机的方式MQ消息转换器业务改造生产者可靠性设置重连 系统可靠性 Java发送消息给MQ public void testSendMessage() t…...

用R语言+随机森林玩转遥感空间预测-基于R语言机器学习遥感数据处理与模型空间预测技术及实际项目案例分析
遥感数据具有高维度、非线性及空间异质性等特点,传统分析方法往往难以充分挖掘其信息价值。机器学习技术的引入为遥感数据处理与模型预测提供了新的解决方案,其中随机森林(Random Forest)以其优异的性能和灵活性成为研究者的首选工…...
【许可证】Open Source Licenses
长期更新 扩展:shield.io装饰 开源许可证(Open Source Licenses)有很多种,每种都有不同的授权和限制,适用于不同目的。 默认的ISC🟰MIT License是否可商用是否要求开源衍生项目是否必须署名是否有专利授权…...

Spring Boot 文件上传实现详解
在项目开发过程中,文件上传是极为常见的功能需求。对于熟悉 Spring MVC 文件上传操作的开发者而言,Spring Boot 中的文件上传与之原理基本相通,只是在依赖管理和配置方式上更为简化。接下来,将详细阐述 Spring Boot 项目中文件上传…...

查看单元测试覆盖率
文章目录 1、POM文件配置2、编写单元测试3、执行单元测试4、查看单元测试覆盖率 1、POM文件配置 pom文件配置jacoco插件 <!-- 生成JaCoCo覆盖率数据插件 --> <plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artif…...

基于SpringBoot的在线教育管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
交叉编译 opencv-4.10
编译说明 opencv 下包含很多模块,各个模块的作用可以参考Opencv—模块概览. 嵌入式考虑有限存储等因素会对模块进行裁剪,我这里主要保留图像拼接(stitching)图片编解码(imgcodecs)与特征点匹配(…...

C# 方法(方法重载)
本章内容: 方法的结构 方法体内部的代码执行 局部变量 局部常量 控制流 方法调用 返回值 返回语句和void方法 局部函数 参数 值参数 引用参数 引用类型作为值参数和引用参数 输出参数 参数数组 参数类型总结 方法重载 命名参数 可选参数 栈帧 递归 方法重载 一个类中可以有多个…...

3、食品包装控制系统 - /自动化与控制组件/food-packaging-control
76个工业组件库示例汇总 食品包装线控制系统 这是一个用于食品包装线控制系统的自定义组件,提供了食品包装生产线的可视化监控与控制界面。组件采用工业风格设计,包含生产流程控制、实时数据监控和逻辑编程三个主要功能区域。 功能特点 工业风格UI设…...

初始图形学(7)
上一章完成了相机类的实现,对之前所学的内容进行了封装与整理,现在要学习新的内容。 抗锯齿 我们放大之前渲染的图片,往往会发现我们渲染的图像边缘有尖锐的"阶梯"性质。这种阶梯状被称为"锯齿"。当真实的相机拍照时&a…...
Linux NVIDIA 显卡驱动安装指南(适用于 RHEL/CentOS)
📌 一、禁用 Nouveau 开源驱动 NVIDIA 闭源驱动与开源的 nouveau 驱动冲突,需先禁用: if [ ! -f /etc/modprobe.d/blacklist-nouveau.conf ]; thenecho -e "blacklist nouveau\noptions nouveau modeset0" | sudo tee /etc/modpr…...

线程的一些事(2)
在java中,线程的终止,是一种“软性”操作,必须要对应的线程配合,才能把终止落实下去 然而,系统原生的api其实还提供了,强制终止线程的操作,无论线程执行到哪,都能强行把这个线程干掉…...