DOM 被劫持
文档对象模型(DOM)充当着 HTML 和 JavaScript 之间的接口,搭建起静态内容与动态交互之间的桥梁,对现代 Web 开发而言,DOM 的作用不可或缺。
然而,DOM 也有一个致命的陷阱 —— DOM 劫持。DOM 劫持是指当 HTML 元素与全局 JavaScript 变量或函数产生冲突时,可能会导致 Web 应用程序出现不可预期的行为,甚至产生潜在的安全漏洞。
今天就可大家一起来聊聊 DOM 劫持的问题。
DOM 劫持是怎么发生的?
每个 HTML 元素都可以有一个唯一的 id 或 name 属性,方便在 JavaScript 中引用特定的元素。例如,下面的 HTML 按钮具有一个值为 "myButton" 的 id 属性:
<button id="myButton">Click Me!</button>
我们可以在 JavaScript 代码中使用此 ID 来操作按钮,例如,当点击时改变其文本:
document.getElementById('myButton').onclick = function() {this.textContent = 'Clicked!';
};
如果 HTML 元素的 id 或 name 属性与全局 JavaScript 变量或函数冲突会发生什么呢?
当浏览器加载 HTML 页面时,它会自动为 HTML DOM 中的每个 id 和 name 属性创建全局 JavaScript 变量。如果我们有一个名为 “myButton” 的 HTML 元素,浏览器会创建一个全局 JavaScript 变量 myButton,引用该 HTML 元素。
现在,让我们考虑一个场景,其中我们声明了一个名为 myButton 的 JavaScript 函数:
function myButton() {// some code
}
但我们还有一个 id 或 name 为 “myButton” 的 HTML 元素。当页面加载时,浏览器的自动进程会引用 HTML 元素并覆盖 JavaScript 函数 myButton。
<button id="myButton">Click Me!</button>console.log(myButton); // This will log the HTML button element, not the function
这个过程叫做 DOM 劫持,它可能会引发不可预测的行为和安全漏洞。如果攻击者能控制这些属性,他们可能有能力向网页注入恶意代码,从而引发包括跨站脚本(XSS)在内的安全问题。
为了说明这一点,让我们考虑以下情景:
Enter your name: <input id="username" type="text">
<button onclick="greet()">Greet</button>function greet() {var username = document.getElementById('username').value;alert(`Hello ${username}`);
}
攻击者可以输入类似 <img id='alert' src=x onerror='alert(1)'> 的内容,创建一个 'id' 为 'alert' 的新 HTML 组件。该组件会破坏 JavaScript 中的正常 alert 功能。下次网站尝试使用此功能时,它将无法正常工作,甚至可能运行恶意代码。
我们想象现在有一个带有用户反馈功能的基本 Web 应用程序。用户输入自己的姓名和反馈消息,然后提交。页面显示反馈:
html:
<h2>Feedback Form</h2>
<form><label for="name">Name:</label><br><input type="text" id="name" name="name"><br><label for="feedback">Feedback:</label><br><textarea id="feedback" name="feedback"></textarea><br><input type="submit" value="Submit">
</form><div id="feedbackDisplay"></div>
JavaScript:
document.querySelector('form').onsubmit = function(event) {event.preventDefault();let name = document.getElementById('name').value;let feedback = document.getElementById('feedback').value;let feedbackElement = document.getElementById('feedbackDisplay');feedbackElement.innerHTML = `<p><b>${name}</b>: ${feedback}</p>`;
};
这段代码会获取用户的姓名和反馈,并将其显示在 FeedbackDisplay div 内的段落元素中。
攻击者可以通过在反馈表单中提交一段 HTML 来利用此代码。例如,如果他们在名称字段中输入以下代码并提交表单,则反馈显示区域就会被 Script 替换:
<script id="feedbackDisplay">window.location.href='http://conardli.top';</script>
当表单尝试显示下一条反馈时,就会执行脚本,将用户重定向到恶意网站。这是 DOM 劫持造成严重后果的一个例子 —— 攻击者可以控制用户的浏览器,从而窃取敏感数据或安装恶意软件。
缓解 DOM 劫持的安全编码实践
通过更深入地了解这些漏洞,我们可以继续采取一些最佳实践来减轻 DOM 劫持的风险。
正确定义变量和函数的作用域
DOM 劫持的最常见原因之一是滥用 JavaScript 中的全局作用域。
通过在特定的作用域范围内定义变量和函数,我们可以限制对该范围或任何嵌套范围的覆盖,并最大限度地减少潜在的冲突。
我们来用 JavaScript 的作用域规则并重构前面的示例来展示如何做到这一点:
(function() {// All variables and functions are now in this function's scopeconst form = document.querySelector('form');const feedbackElement = document.getElementById('feedbackDisplay');form.onsubmit = function(event) {event.preventDefault();const name = document.getElementById('name').value;const feedback = document.getElementById('feedback').value;// Sanitize user inputname = DOMPurify.sanitize(name);feedback = DOMPurify.sanitize(feedback);const newFeedback = document.createElement('p');newFeedback.textContent = `${name}: ${feedback}`;feedbackElement.appendChild(newFeedback);};
})();
首先我们使用了 DOMPurify 来对上述代码块中的用户输入进行清理。
在此版本的代码中,我们将所有内容都包含在立即调用函数表达式 (IIFE) 中,这会创建一个新作用域。form 和 FeedbackElement 变量以及分配给 onsubmit 事件处理程序的函数不在全局作用域内,因此它们不能被劫持。
使用唯一标识符
确保网页上的每个元素都有唯一的 id 可以降低无意中覆盖重要函数或变量的风险。另外,避免使用通用名称或可能与全局 JavaScript 对象或函数冲突的名称。
避免全局命名空间污染
保持全局命名空间干净是编写安全 JavaScript 的一个重要方面。全局作用域中的变量和函数越多,DOM劫持的风险就越大。使用 JavaScript 的函数作用域或 ES6 的块作用域来保留变量和函数。这是使用后者的示例:
let form = document.querySelector('form');let feedbackElement = document.getElementById('feedbackDisplay');form.onsubmit = function(event) {event.preventDefault();let name = document.getElementById('name').value;let feedback = document.getElementById('feedback').value;// Sanitize user inputname = DOMPurify.sanitize(name);feedback = DOMPurify.sanitize(feedback);let newFeedback = document.createElement('p');newFeedback.textContent = `${name}: ${feedback}`;feedbackElement.appendChild(newFeedback);};
在这段代码中,我们使用块(由 {} 定义)来创建新作用域。所有变量和函数现在都限制在该块中,并且不在全局作用域内。
正确使用 JavaScript 特性
现代 JavaScript 提供了一些有助于最大限度地缓解 DOM 劫持的风险。特别是 ES6 中引入的 let 和 const 关键字提供了对声明变量的更多控制。
在以前,我们使用 var 关键字声明 JavaScript 变量。var 有一些怪癖,其中之一是就它没有块作用域,只有函数作用域和全局作用域。这意味着用 var 声明的变量可以在声明它的块之外访问和覆盖。
另一方面,let 和 const 都具有块作用域,这意味着它们只能在声明它们的块内访问。这一特性通常使它们成为变量声明的更好选择,因为它限制了覆盖变量的可能性。
我们还可以使用 const 来声明常量 — 分配它们后我们无法更改的值。它们可以防止重要的变量被意外覆盖。
const form = document.querySelector('form');const feedbackElement = document.getElementById('feedbackDisplay');form.onsubmit = function(event) {event.preventDefault();const name = document.getElementById('name').value;const feedback = document.getElementById('feedback').value;// Sanitize user inputname = DOMPurify.sanitize(name);feedback = DOMPurify.sanitize(feedback);const newFeedback = document.createElement('p');newFeedback.textContent = `${name}: ${feedback}`;feedbackElement.appendChild(newFeedback);};
在此代码中,我们将所有 var 的使用替换为 const。我们将所有变量限制在声明它们的块中,并且常量不能被覆盖。
但是 ,使用 let 和 const 并不能完全消除 DOM 劫持的风险,但这种做法仍然是安全编码的一个关键方面。
使用 Devtools 发现潜在的 DOM 劫持风险
例如 Chrome 或 Firefox 中的浏览器开发者工具,也是探测 DOM 劫持漏洞的强大助手。
最简单的方法,我们直接打开 Devtools。
然后在控制台输入 window ,这里面包含了网站全局作用域下所有的全局变量和函数。
然后我们检查下是否有任何看起来不合适的变量,尤其是那些与 HTML 元素 id 或 name 同名的变量。
通过 Elements 选项卡,编辑页面的 HTML 来操控 DOM 并测试潜在的漏洞。例如,添加一个 id 与全局变量或函数相匹配的元素,看看是否会被覆写。
相关文章:
DOM 被劫持
文档对象模型(DOM)充当着 HTML 和 JavaScript 之间的接口,搭建起静态内容与动态交互之间的桥梁,对现代 Web 开发而言,DOM 的作用不可或缺。 然而,DOM 也有一个致命的陷阱 —— DOM 劫持。DOM 劫持是指当 H…...
PIG框架学习2——资源服务器的配置详解
一、前言 1、pig资源服务器的配置 Spring Security oauth2相关的依赖是在pigx-common-security模块中引入的,其他模块需要进行token鉴权的,需要在微服务中引入pigx-common-security模块的依赖,从而间接引入相关的Spring security oauth2依赖…...
vue+element ui实现图片上传并拖拽进行图片排序
用到的技术栈: vue2element Uivue-dragging 如何使用: 第一步: 安装 npm install awe-dnd --save第二步: 引入 main.js 文件 // 引入组件 import VueDND from awe-dnd // 添加至全局 Vue.use(VueDND)具体项目代码 <el-form-item label"封面…...
国产服务器 BIOS下组建RADI不同RAID卡-超详细
国产服务器 长城 组建Raid的方法 说明 大多数国产服务器通用型服务器进入BIOS的都是按DEL键。 9361RAID卡组建方法 在服务器启动过程中,按下DEL键进入BIOS界面。 进入设备管理器,选择AVAGO MegaRAID页签。 3. 进入RAID卡设备,选择Main Me…...
UE4 4.21-4.27使用编辑器蓝图EditorBlueprint方法
在UE4 4.21中,编辑器蓝图(Editor Blueprint)是一个强大的工具,允许开发者扩展和自定义Unreal编辑器的功能。通过编辑器蓝图,我们可以创建自定义的工具和功能,以优化开发流程。 本教程将指导您如何在UE4 4.…...
105、Zero-1-to-3: Zero-shot One Image to 3D Object
简介 官网 使用合成数据集来学习相对摄像机视点的控制,这允许在指定的摄像机变换下生成相同对象的新图像,用于从单个图像进行三维重建的任务。 实现流程 输入图像 x ∈ R H W 3 x \in \R^{H \times W \times 3} x∈RHW3,所需视点的相…...
scala 安装和创建项目
Scala,一种可随您扩展的编程语言:从小型脚本到大型多平台应用程序。Scala不是Java的扩展,但它完全可以与Java互操作。在编译时,Scala文件将转换为Java字节码并在JVM(Java虚拟机)上运行。Scala被设计成面向对…...
Python办公自动化 – 自动化文本翻译和Oracle数据库操作
Python办公自动化 – 自动化文本翻译和Oracle数据库操作 以下是往期的文章目录,需要可以查看哦。 Python办公自动化 – Excel和Word的操作运用 Python办公自动化 – Python发送电子邮件和Outlook的集成 Python办公自动化 – 对PDF文档和PPT文档的处理 Python办公自…...
如何在Win10电脑接收苹果手机日程提醒呢?
有很多小伙伴手机使用的是iPhone苹果手机,但办公电脑使用的win10系统的电脑,这时候如果想要在win10电脑上同步接收苹果手机上设置的日程提醒,该怎么操作呢?如何在win10电脑接收苹果手机日程提醒呢? 如果你设置的日程提…...
227.【2023年华为OD机试真题(C卷)】小明找位置(二分查找-JavaPythonC++JS实现)
🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-小明找位置二.解题思路三.题解代码Python题解代…...
【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》
【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》 写在最前面私钥加密与伪随机性 第二部分流加密与CPA多重加密 CPA安全加密方案CPA安全实验、预言机访问(oracle access) 操作模式伪随机函数PR…...
服务器带宽有什么用? 带宽不足怎么办?
服务器带宽是指服务器能够接收和传输数据的速率,通常以每秒传输的数据量来衡量。它是支持特定应用服务器网络和因特网(Internet)访问的单一网络线路,对网络速度、响应时间、应用程序处理速度等方面都有影响。 服务器带宽有什么作…...
Alphafold2蛋白质结构预测AI工作站配置推荐
AlphaFold2计算特点 蛋白质三维结构预测是一项计算量非常巨大的任务,科学家多年的探索研究,形成了X射线晶体学法、核磁共振法、冷冻电镜等。 2021年底,谷歌的DeepMind团队的采用人工智能方法的AlphaFold2算法在生物界引起了极大的轰动…...
如何让ArcGIS Pro启动显示空白页面
刚接触ArcGIS Pro的你是否会觉得在操作上有那么一些不习惯,从一开始软件启动就发现和ArcGIS差距很大:丰富的欢迎页面,加上默认加载的地图让你眼花缭乱,这里教你如何去掉这些繁杂的内容,还你一个干净的启动页面。 跳过…...
超市账单管理系统产品数据新增Servlet实现
超市账单管理系统产品数据新增Servlet实现 package com.test.controller; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import ja…...
计算机组成原理之计算机硬件发展和计算机系统的组成
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持,想组团高效学习… 想写博客但无从下手,急需…...
《JVM由浅入深学习【七】 2024-01-11》JVM由简入深学习提升分享
亲爱的读者们,欢迎来到本篇博客,这是JVM第七次分享,下面是七个JVM常用常面的分享,请笑纳 目录 1. 几个与JVM 内存相关的核心参数2.如何计算一个对象的大小3.堆为什么要分为新生代和老年代4.JVM堆的年轻代为什么要有两个 Survivor…...
Golang leetcode142 环形链表 暴力map 快慢指针法
文章目录 环形链表 leetcode142暴力遍历 map哈希记录快慢指针法 环形链表 leetcode142 该题目要求找到入环的第一个节点 我们可以通过map进行记录,没到新的节点查询是否经过原有节点 入环节点,上两个节点的next相同 若有入环节点,则一定能检…...
基于java,springboot的论旅游管理系统设计与实现
环境以及简介 基于java,springboot的论旅游管理系统设计与实现,Java项目,SpringBoot项目,含开发文档,源码,数据库以及ppt 源码下载 环境配置: 框架:springboot JDK版本:JDK1.8 服…...
掌握视频节奏,玩转剪辑艺术!,轻松调整视频播放速度与秒数的技巧大揭秘
你是否经常觉得视频播放得太快或太慢,无法满足你的观看需求?或者想要控制视频的长度,却不知道该如何下手?今天,我们将为你揭秘几种简单又实用的方法,让你轻松调整视频的播放速度和秒数! 首先&a…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
