2021PlaidCTF - The False Promise
本文第一发布平台为安全客:https://www.anquanke.com/post/id/239995
题目分析
题目的diff文件如下:
1 | diff --git a/src/builtins/promise-jobs.tq b/src/builtins/promise-jobs.tq |
可以发现 patch 去除了某些检查,导致更容易进入if 分支并执行,很明显这是一个类型混淆的漏洞
patch后的完整一点的代码如下:
1 | [...] |
跟进到 src/builtins/promise-abstract-operations.tq 的 PerformPromiseThen 函数
1 | // https://tc39.es/ecma262/#sec-performpromisethen |
可以发现如果我们的 thenable 不是 JSPromise ,那么在 PerformPromiseThenImpl 的时候就会将 reaction 写入 promise.reactions_or_result 中,导致可能会改变传入的 thenable 的内容
题目给的 chromium 的 commit 为 ca01b9e37ff412d2693fdcdef75812ae0bbbd386 ,但是这是一个 v8 的洞,所以我们直接使用 v8 调更方便一些,v8 的版本是 9.2.44
我们编写如下代码进行测试:
1 | var thenable = [1.1,2.2,3.3,4.4] |
这里的
new Object()是为了进入PerformPromiseThenImpl的if (promise.Status() == PromiseState::kPending)分支
我们加一个断点断在 PerformPromiseThenImpl 的开头,首先进入 if (promise.Status() == PromiseState::kPending) 分支

此时部分寄存器的值的含义如下
1 | RAX 0x3dfb08088b1d <Promise map = 0x3dfb08243091> |
RAX 存放的是 p ,RDX 存放的是 thenable
走到 reaction 生成完毕


再走一步可以发现 promise.reactions_or_result = reaction 语句执行完毕,thenable 的 length 已经被修改为了 reaction


这样我们便获得了一个 OOB 的数组,那么我们接下来只需要按照普通的思路进行利用即可
EXP
由于是本地 V8 复现的所以就只在本地弹了个计算器,感兴趣话可以换个 shellcode 啥的就可以打远程了
1 | var buf = new ArrayBuffer(16); |
