在這里了解當今互聯(lián)網(wǎng)的最新動態(tài)
在這里了解當今
在做一個Bug bounty的項目時,我發(fā)現(xiàn)了一個網(wǎng)站,它有一個很有意思的功能:它能讓我使用一些用戶控制的表達式過濾數(shù)據(jù)。比如說,我可以輸入 book.proce > 100 表達式,使它只展示一些價格高于 $100 的書。直接輸入 true 可以列出所有的書,輸入 false 就會一本書都不顯示。所以我可以知道我使用的表達式是對是錯。
這個功能引起了我的注意,因此我嘗試著輸入更復雜的表達式,比如 (1+1).toString()==="2" (值為 true)和 (1+1).toString()===5 (值為 false)。這顯然是 JavaScript 代碼,因此我猜測這個表達式在 NodeJS server 中被作為參數(shù)傳給了一個類似 eval 的函數(shù)。到了這里,我感覺我快要發(fā)現(xiàn)一個遠程執(zhí)行漏洞了。然而,當我想要測試一個更加復雜的表達式時,它報錯了,提示我輸入的表達式非法。我猜測這應該不是 eval 函數(shù),而應該是一個 JavaScript 的沙箱。
沙箱都是再一個受控的環(huán)境中執(zhí)行非可信的代碼,而這一般都是很難確保不出問題的。大多數(shù)情況下,我們都能找到一些方法來繞過沙箱的保護機制。特別是對于像 JavaScript 這樣復雜,特性臃腫的語言,沙箱的漏洞可能會更多。這個問題吸引了我的注意,所以我決定花一些時間來打破這個沙箱的防護機制。我學習了 JavaScript 的一些內(nèi)部機制,用來發(fā)現(xiàn)和利用沙箱的 RCE 漏洞。
我首先要確定這個網(wǎng)站使用了什么庫來實現(xiàn)的沙箱,因為 NodeJS 中有幾十個類似的庫,在許多情況下,它們都存在一些漏洞。當然,也有可能這是一個開發(fā)人員自己寫的庫,但是我忽略了這種可能,因為單純的網(wǎng)站開發(fā)人員不太可能花大把的時間來做這種語言底層的事情。
最后,通過分析網(wǎng)站的錯誤日志,我推斷處它們應該使用的是 static-eval ,這是一個不太流行的庫(由 substack寫的,這個人再 NodeJS 社區(qū)中非常有名)。盡管它的文檔中寫了,它并不是被設(shè)計來作為沙箱的,但是我仍然十分確定他在這個網(wǎng)站中被用作了沙箱。
繞過 static-eval
static-eval的基本思想是使用 esprima 庫解析 JS 表達式并將其轉(zhuǎn)換為 AST(抽象語法樹)。static-eval 通過分析這個AST 對我輸入的表達式進行評估。如果發(fā)現(xiàn)一些奇怪的東西,函數(shù)就拋出異常,我的代碼就不會執(zhí)行。一開始,我有點灰心喪氣,因為我意識到沙箱對它所接受的表達式有很大的限制。我甚至不能在表達式中使用 for 或 while 語句,所以做一些需要迭代算法的事情是幾乎不可能的。無論如何,我堅持著繼續(xù)尋找漏洞。
一開始,我并沒有發(fā)現(xiàn)任何 bug,所以我查看了 static-eval 項目的 commits 和 pull requests 的所有記錄。 我發(fā)現(xiàn) pull requests #18 修復了兩個沙箱逃逸的 bug,而這正是我所尋找的。 我還發(fā)現(xiàn)了這個 pr 作者的博客,在這篇文章里,他深入分析了這個漏洞。同時,我在立即在這個網(wǎng)站中測試這個漏洞,然而,他們使用了一個新版本的 static-eval,這個版本的 static-eval 早就把這個漏洞補上了。我立即嘗試在我測試的網(wǎng)站中使用這種技術(shù),但不幸的是,他們使用的是更新的靜態(tài)評估版本,已經(jīng)修補了這個漏洞。但是,知道有人發(fā)現(xiàn)過這種漏洞,這讓我更加自信,所以我一直在尋找繞過它的新方法。
接下來,我深入分析了這兩個漏洞,以期望能夠為我找到新的漏洞尋找靈感。
第一個漏洞:
第一個漏洞使用了 function constructor 來生成惡意函數(shù)。
這種技術(shù)經(jīng)常用于繞過沙箱。例如,大多數(shù)通過繞過 angular.js 沙箱來獲得 XSS 的方法都使用一些有效載荷,它們最終都會訪問和調(diào)用 function constructor。下面的表達式用來演示漏洞,能夠打印系統(tǒng)環(huán)境變量(這應該是不被允許的,因為沙箱應該阻止它):


這是一個非常簡單的修復,但它的效果出奇的好。當然,function constructor 只在函數(shù)中可用。所以我無法訪問它。對象的 typeof 是不能被修改的,因此任何函數(shù)的 typeof 都將被設(shè)置為 function。
資訊列表