淺談RASP技術攻防之實戰[程式碼實現篇]

凌天labs發表於2019-05-08

本篇主講RASP實現(簡易版),所有的環境可參考: 淺談RASP技術攻防之實戰[環境配置篇]

 

程式碼上傳GitHub地址:https://github.com/iiiusky/java_rasp_example

 

關於 ASM 中不同類不同方法之間的關係圖如下

簡易版RASP實現

建立入口類

在cn.org.javaweb.agent包下新建一個類。
內容如下:

 

建立Transform

然後我們再新建一個AgentTransform類,該類需要實現ClassFileTransformer的方法,內容如下:

 

build Agent配置

點選右上角的agent[clean,intall]進行build。

由上圖可見我們的包的位置為

 

 

將改包的位置記錄下來,然後點開tomcat配置(這邊沒有對idea如何配置tomcat進行講解,不會的可以自行百度|谷歌)

 

 

在VM options處填寫以下內容:

 

 

其中/Volumes/Data/code/work/JavawebAgent/agent/target/agent.jar的路徑為你在上一步編譯出來的agent的路徑,注意替換。

 

這時候我們在啟動tomcat,就可以看到我們在AgentTransform中寫的列印包名已經生效了,如下圖:

上圖紅框區域為tomcat啟動的時候載入的所有類名。然後我們開啟瀏覽器檢視web是否正常。

 


可以看到web也正常啟動了。

建立ClassVisitor類

然後我們新建一個TestClassVisitor類,需要繼承ClassVisitor類並且實現Opcodes類,程式碼如下

 

對ProcessBuilder(命令執行)類進行hook使用者執行的命令

≡≡ 使用transform對類名進行過濾

然後回到AgentTransform中,對transform方法的內容進行修改,transform方法程式碼如下:

 


簡單介紹一下程式碼塊內容

 

首先判斷類名是否包含ProcessBuilder,如果包含則使用ClassReader對位元組碼進行讀取,然後新建一個ClassWriter進行對ClassReader讀取的位元組碼進行拼接,然後在新建一個我們自定義的ClassVisitor對類的觸發事件進行hook,在然後呼叫classReader的accept方法,最後給classfileBuffer重新賦值修改後的位元組碼。

 

可能看起來比較繞,但是如果學會使用以後就比較好理解了。

≡≡ 建立測試環境

我們在tomcat中新建一個jsp,用來呼叫命令執行,程式碼如下:

 


可以看到就是一個簡單的執行命令的程式碼;下面我們對就此更改過的內容進行build,看一下會輸出點什麼。

biuld完成,啟動tomcat。

訪問

 


可以看到已經成功執行命令,我們回到idea裡面的控制檯看一下輸出了什麼。

通過上圖可以完整的看到一個執行命令所呼叫的所有呼叫鏈。

 

≡≡ 拿到使用者所執行的命令

接下來我們看看嘗試一下能否拿到所執行的命令
新建一個名為ProcessBuilderHook的類,然後在類中新建一個名字為start的靜態方法,完整程式碼如下:

 


這個方法幹啥用的我們一會在說,先看下面。

≡≡ 複寫visitMethod方法

開啟TestClassVisitor,對visitMethod方法進行更改。具體程式碼如下:

 


給大家解釋下新增加的程式碼,從if判斷開始

 

判斷傳入進來的方法名是否為start以及方法描述符是否為()Ljava/lang/Process;,如果是的話就新建一個AdviceAdapter方法,並且複寫visitCode方法,對其位元組碼進行修改,

 


拿到棧頂上的this

 


拿到this裡面的command

 


然後呼叫我們上面新建的ProcessBuilderHook類中的start方法,將上面拿到的this.command壓入我們方法。

 

ProcessBuilderHook類的作用就是讓這部分進行呼叫,然後轉移就可以轉入到我們的邏輯程式碼了。

 

我們再次編譯一下,然後啟動tomcat,訪問cmd.jsp看看.

≡≡ 測試hook使用者執行的命令引數是否拿到

訪問

 

 


可以看到已經將當前目錄下的內容列印了出來。
我們到idea中看看控制檯輸出了什麼。

 

可以看到我們輸入的命令

 


已經輸出出來了,到此為止,我們拿到了要執行的命令.

總結

對於拿到要執行的命令以後怎麼做,是需要攔截還是替換還是告警,這邊就需要大家自己去實現了。當然,如果要實現攔截功能,還需要注意要獲取當前請求中的的response,不然無法對response進行復寫,也無法對其進行攔截。這邊給大家提供一個思路,對應攔截功能,大家可以去hook請求相關的類,然後在危險hook點結合http請求上下文進行攔截請求。

 

對於其他攻擊點的攔截,可以參考百度開源的OpenRasp進行編寫hook點。

 

如需在Java中實現RASP技術,筆者建議好好了解一下ASM,這樣對以後JAVA的執行機制也會有一定的瞭解,方便以後除錯以及寫程式碼。

參考

https://rasp.baidu.com/doc/hacking/architect/hook.html#java-server
https://github.com/anbai-inc/javaweb-codereview
https://static.javadoc.io/org.ow2.asm/asm/5.2/org/objectweb/asm/ClassReader.html
http://www.blogjava.net/vanadies10/archive/2011/02/23/344899.html
http://www.blogjava.net/DLevin/archive/2014/06/25/414292.html

相關文章