FavoriteLoading
0

JXBrowser JavaScript-Java bridge 中的RCE漏洞

我近期正在研究如何使用JXBrowser來實現一套試驗性的掃描技術。當我在使用JXBrowser庫的過程中,我突然想到,是否可以通過調用不同的類來攻擊JXBrowser客戶端,并通過一個Web頁面來實現遠程代碼執行呢?
安全客百科-JxBrowser
JxBrowser是一款采用Java語言開發的瀏覽器組件。JxBrowser能在Windows、Linux、Mac OS X (Intel和PPC-based)平臺上將Mozilla Firefox瀏覽器完美地整合到Java AWT/Swing應用程序里。該庫程序使用Gecko設計引擎來轉換HTML文檔。因而保證了它能與許多Internet標準(如HTML 4、CSS、XML、JavaScript以及其它)兼容。

漏洞利用技術分析
我編寫的JavaScript代碼(Java Bridge)大致如下:
browser.addScriptContextListener(new ScriptContextAdapter() {
@Override
public void onScriptContextCreated(ScriptContextEvent event) {
Browser browser = event.getBrowser();
JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty("someObj", new someJavaClass());
}
});
上面這段示例代碼是從JXBrowser網站上摘錄下來的。大致來說,這段代碼向瀏覽器實例中插入了一個腳本,然后獲取到了window對象,并將其轉換成了一個Java JSValue對象。接下來,代碼在window對象中設置了“someObj”,然后將這個Java對象傳遞給JavaScript window對象,這樣就設置好了我們的bridge(Java橋接模式)了!根據開發文檔的描述,我們在這里只能使用公共類。當我們創建好了一個bridge之后,我們在與其交互的過程中還需要使用一些JavaScript腳本。
setTimeout(function f(){
if(window.someObj && typeof window.someObj.javaFunction === 'function') {
window.someObj.javaFunction("Called Java function from JavaScript");
} else {
setTimeout(f,0);
}
},0);
我在這里設置了超時(setTimeout),它可以檢測我們是否已經獲取到了這個“someObj”。如果沒有檢測到這個對象的話,代碼會不斷調用這個方法,直到檢測到了這個對象為止。一開始,我曾嘗試使用getRuntime()方法來查看我是否可以獲取到一個runtime對象的實例,并運行calc(計算器)。。我所使用的調用代碼如下所示:

window.someObj.getClass().forName('java.lang.Runtime').getRuntime();
但是,我得到了以下的錯誤返回信息:

Neither public field nor method named 'getRuntime' exists in the java.lang.Class Java object(Java對象java.lang.Class中不存在公共域或getRuntime方法)
難道是因為我們無法在這里調用getRuntime方法么?于是乎,我打算用更簡單的方法來嘗試一下,代碼如下所示:

window.someObj.getClass().getSuperclass().getName();
這一次,我們的代碼似乎成功運行了。接下來,我開始嘗試枚舉出所有可用的方法。代碼和運行結果如下所示:
methods = window.someObj.getClass().getSuperclass().getMethods();
for(i=0;i
console.log(methods[i].getName());
}
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
大家可以看到,我成功地枚舉出了所有的方法。接下來,我打算嘗試使用一下ProcessBuilder,看看會發生什么。但是,當我每一次嘗試調用構造器的時候,代碼都崩潰了。根據報錯信息來看,似乎構造器需要一個Java數組來作為輸入。這也就意味著,我得想辦法創建一個用來保存字符串的Java數組,然后將其傳遞給ProcessBuilder的構造器。
window.someObj.getClass().forName("java.lang.ProcessBuilder").newInstance("open","-a Calculator");
//Failed
window.someObj.getClass().forName("java.lang.ProcessBuilder").newInstance(["open","-a Calculator"]);
//Failed too
別著急,我們暫時先不管這個問題,先讓我們創建另一個對象來證明這個漏洞的存在。我通過下面這段代碼成功地創建了一個java.net.Socket類的實例。代碼如下所示:

window.someObj.getClass().forName("java.net.Socket").newInstance();
但是,當我嘗試調用這個對象的時候,我再一次遇到了問題,這一次系統返回的錯誤信息告訴我“參數類型發生錯誤”。雖然我現在可以創建socket對象,但是我卻無法使用它們。由于我無法向該對象傳遞任何的參數,所以這個對象對于我來說暫時沒有任何的意義,因為它根本無法使用。接下來,我又嘗試去創建并使用java.io.File類的對象,但是我又失敗了。我感覺現在已經走投無路了,我雖然可以創建出這些對象,但是每當這些函數需要我提供參數的時候,我都無法提供正確類型的參數值。不僅newInstance方法無法正常工作,而且其他的調用方法也無法正確運行。
柳暗花明又一村
我需要幫助,我非常迫切地需要Java大神的幫助!幸運的是,如果你在Portswigger這樣的地方工作的話,你就會發現你永遠不是實驗室里最聰明的那個人。在我“走投無路”的時候,我便打算向Mike和Patrick尋求幫助。我把我現在遇到的問題向他們解釋了一遍:我需要創建一個Java數組,然后將這個數組作為參數傳遞給函數方法。接下來,我們的工作重點就放在了如何在bridge中創建數組對象。
Mike認為,也許可以使用一個arraylist來實現我們的目標,因為我們可以通過toArray()這個簡單的方法來將arraylist轉換為一個數組(array)對象。

分頁閱讀: 1 2
【聲明】:8090安全小組門戶(http://www.jvwkvg.tw)登載此文出于傳遞更多信息之目的,并不代表本站贊同其觀點和對其真實性負責,僅適于網絡安全技術愛好者學習研究使用,學習中請遵循國家相關法律法規。如有問題請聯系我們,聯系郵箱[email protected],我們會在最短的時間內進行處理。