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); |