天天看點

深入淺出記憶體馬(一)

深入淺出記憶體馬(一)

在Web安全領域,Webshell一直是一個非常重要且熱門的話題。在目前傳統安全領域,Webshell根據功能的不同分為三種類型,分别是:一句話木馬,小馬,大馬。而根據現在防火牆技術的更新疊代,随後出現了加密的木馬技術,比如:加密一句話。而我們今天要說的是一種新的無檔案的Webshell類型:記憶體馬。

傳統Webshell連接配接方式,都是先通過某種漏洞将惡意的腳本木馬檔案上傳,然後通過中國菜刀,或者蟻劍,冰蠍等Webshell管理軟體進行連結。

深入淺出記憶體馬(一)

這種方式目前仍然流行,但是由于近幾年防火牆,IDS,IPS,流量分析等各種安全裝置的普及和更新,這種連接配接方式非常容易被裝置捕獲攔截,而且由于檔案是明文存放在伺服器端,是以又很容易被防毒軟體所清除。在今天看來這種傳統連接配接方式顯然已經過時,于是乎,進化了一系列的加密一句話木馬,但是這種方式還是不能繞過有類似檔案監控的防毒軟體,于是乎進化了新一代的Webshell---》記憶體馬

記憶體馬是無檔案Webshell,什麼是無檔案webshell呢?簡單來說,就是伺服器上不會存在需要連結的webshell腳本檔案。那有的同學可能會問了?這種方式為什麼能連結呢?記憶體馬的原理就像是MVC架構,即通過路由通路控制器,我通過自身的了解,概述的說一下, 記憶體馬的原理就是在web元件或者應用程式中,注冊一層通路路由,通路者通過這層路由,來執行我們控制器中的代碼

目前分為兩種:

Servlet-API型

通過指令執行等方式動态注冊一個新的listener、filter或者servlet,進而實作指令執行等功能。特定架構、容器的記憶體馬原理與此類似,如spring的controller記憶體馬,tomcat的valve記憶體馬

filter型

servlet型

位元組碼增強型

通過java的instrumentation動态修改已有代碼,進而實作指令執行等功能。

spring類

攔截器

Controller型

我們以Java Web舉例,在Java Web中有三大元件分别是Servlet, Filter,Listener

Servlet 是運作在 Web 伺服器或應用伺服器上的程式,它是作為來自 HTTP 用戶端的請求和 HTTP 伺服器上的資料庫或應用程式之間的中間層。它負責處理使用者的請求,并根據請求生成相應的傳回資訊提供給使用者。

Servlet程式是由WEB伺服器調用,web伺服器收到用戶端的Servlet通路請求後:

Web伺服器首先檢查是否已經裝載并建立了該Servlet的執行個體對象。如果是,則直接執行第4步,否則,執行第2步。

裝載并建立該Servlet的一個執行個體對象。

調用Servlet執行個體對象的init()方法。

建立一個用于封裝HTTP請求消息的HttpServletRequest對象和一個代表HTTP響應消息的HttpServletResponse對象,然後調用Servlet的service()方法并将請求和響應對象作為參數傳遞進去。

WEB應用程式被停止或重新啟動之前,Servlet引擎将解除安裝Servlet,并在解除安裝之前調用Servlet的destroy()方法。

Filter譯為過濾器。過濾器實際上就是對web資源進行攔截,做一些處理後再交給下一個過濾器或servlet處理,通常都是用來攔截request進行處理的,也可以對傳回的response進行攔截處理。

深入淺出記憶體馬(一)

web伺服器根據Filter在web.xml檔案中的注冊順序,決定先調用哪個Filter,當第一個Filter的doFilter方法被調用時,web伺服器會建立一個代表Filter鍊的FilterChain對象傳遞給該方法。在doFilter方法中,開發人員如果調用了FilterChain對象的doFilter方法,則web伺服器會檢查FilterChain對象中是否還有filter,如果有,則調用第2個filter,如果沒有,則調用目标資源。

生命周期

監聽器用于監聽Web應用中某些對象的建立、銷毀、增加,修改,删除等動作的發生,然後作出相應的響應處理。當監聽範圍的對象的狀态發生變化的時候,伺服器自動調用監聽器對象中的方法。常用于統計網站線上人數、系統加載時進行資訊初始化、統計網站的通路量等等。

主要由三部分構成:

事件源:被監聽的對象

監聽器:監聽的對象,事件源的變化會觸發監聽器的響應行為

響應行為:監聽器監聽到事件源的狀态變化時所執行的動作

在初始化時,需要将事件源和監聽器進行綁定,也就是注冊監聽器。

可以使用監聽器監聽用戶端的請求、服務端的操作等。通過監聽器,可以自動出發一些動作,比如監聽線上的使用者數量,統計網站通路量、網站通路監控等。

在 Tomcat 中,每個 Host 下可以有多個 Context (Context 是 Host 的子容器), 每個 Context 都代表一個具體的Web應用,都有一個唯一的路徑就相當于下圖中的 /shop /manager 這種,在一個 Context 下可以有着多個 Wrapper

Wrapper 主要負責管理 Servlet ,包括的 Servlet 的裝載、初始化、執行以及資源回收

深入淺出記憶體馬(一)

通過上面的介紹,我們已經大緻了解記憶體馬的背景知識,現在我們來講解Tomcat Filter類型的記憶體馬,看看這種流程是什麼樣子的?

建立filter

Web.xml配置

就是我們建立一個servlet和一個filter 通路路由都是為<code>/hello</code> 。看下結果:

深入淺出記憶體馬(一)

控制台輸出

深入淺出記憶體馬(一)

我們簡單調試一下

深入淺出記憶體馬(一)

對應Web.xml中的配置資訊,這種方式就是為靜态的添加filter的方式,filter實作分為靜态和動态,靜态就是上述中,普通配置在web.xml或者通過@注釋配置在類中的。

關于整個Filter的調用鍊 可以參考:https://mp.weixin.qq.com/s/YhiOHWnqXVqvLNH7XSxC9w, 這個不是我們主要講述的重點。

Filter調用鍊,可以引用寬位元組安全總結的一張圖來說明:

深入淺出記憶體馬(一)

我們調試一下filterChain.doFilter() 方法,啟動服務,然後通路<code>/hello</code>即可調試:

深入淺出記憶體馬(一)

繼續跟進,可以看到<code>doFilter()</code> 的具體處理過程是在<code>internalDoFilter()</code>

深入淺出記憶體馬(一)
深入淺出記憶體馬(一)

然後最後調用<code>service()</code>方法去調用這個filter裡面的内容

深入淺出記憶體馬(一)
深入淺出記憶體馬(一)

概述地說, <code>FilterChain.doFilter()</code> 方法将調用下一個 Filter.doFilter() 方法;最後一個 <code>Filter.doFilter()</code> 方法中調用的<code>FilterChain.doFilter()</code> 方法将調用目标 <code>Servlet.service()</code> 方法。

上面的描述總結下來就是如何在tomcat中動态的注入一條配置項和代碼,拿filter類型舉例子,那麼我們如何建立一個Filter類型的記憶體馬呢?

首先建立一個惡意Filter

利用 FilterDef 對 Filter 進行一個封裝

将 FilterDef 添加到 FilterDefs 和 FilterConfig

建立 FilterMap ,将我們的 Filter 和 urlpattern 相對應,存放到 filterMaps中(由于 Filter 生效會有一個先後順序,是以我們一般都是放在最前面,讓我們的 Filter 最先觸發)

每次請求createFilterChain都會依據此動态生成一個過濾鍊,而StandardContext又會一直保留到Tomcat生命周期結束,是以我們的記憶體馬就可以一直駐留下去,直到Tomcat重新開機。

好的 那我們首先來編寫一個filter的惡意類

運作效果:

深入淺出記憶體馬(一)

可以看到這個就是在tomcat中沒有任何shell檔案,但是在過濾器中執行了我們的代碼。

那麼真實情況下,我們不可能直接修改項目中Filter的源碼,因為就算修改了,想要生效也需要重新開機。是以我們需要動态的插入filter,那我們該如何操作呢?

最終代碼如下:

通路這個頁面

深入淺出記憶體馬(一)

最後直接通路任意Servlet路由都可以執行指令

深入淺出記憶體馬(一)

即使删除我們的注入檔案<code>filterdemo1.jsp</code>也是一樣可以執行,這樣就可以達到無檔案的Webshell管理方式了。