之前写过一篇fastjson漏洞文章,但是当时在复现利用链的过程中一直没有弹出计算器,而且利用链的代码单步调试也没有给出来,这次我要通过底层代码把漏洞实现过程展现出来。
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:主机域名、虚拟空间、营销软件、网站建设、临河网站维护、网站推广。
上次不是没有弹出计算器吗,这次我先把可以弹出计算器的漏洞demo先讲解一下。
import java.util.Properties;
//创建一个普通类
public class Person {
private String name;
private int age;
private String sex;
private Properties properties;
public Person() {
System.out.println("构造方法");
}
//Setter Getter方法
public String getName() {
System.out.println("getName");
return name;
}
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
public int getAge() {
System.out.println("getAge");
return age;
}
public String getSex(){
System.out.println("getAddress");
return sex;
}
public Properties getProperties() throws Exception {
System.out.println("getProperties");
Runtime.getRuntime().exec("open -a /System/Applications/Calculator.app");
return properties;
}
}
import com.alibaba.fastjson.JSON;
public class Demo {
public static void main(String[] args){
String jsonstring ="{\"@type\":\"com.FastjsonDemo.Person\",\"age\":18,\"name\":\"lili\",\"address\":\"china\",\"properties\":{}}";
//JSON.parseObject() 方法将 jsonstring 字符串解析并转换为一个通用的 Object 对象
Object obj = JSON.parseObject(jsonstring, Object.class);
System.out.println(obj);
}
}
1687937316_649be124cc1a2eef0df3e.png!small
1687937342_649be13ef0c5cd18a34cb.png!small
public static T parseObject(String text, Class clazz) {
return parseObject(text, clazz);
}
1687937363_649be1531fc289d742fdc.png!small
public static T parseObject(String json, Class clazz, Feature... features) {
return parseObject(json, clazz, ParserConfig.global, (ParseProcess)null, DEFAULT_PARSER_FEATURE, features);
}
1687937388_649be16c9b766b3612ff6.png!small
1687937405_649be17d73e3f75a24438.png!small
public static T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature... features) {
//input为{"@type":"com.FastjsonDemo.Person","age":18,"name":"lili","address":"china","properties":{}}
if (input == null) {
return null;
} else {
//features为Feature[0]@497
if (features != null) {
Feature[] var6 = features;
//定义特性数组长度var7
int var7 = features.length;
for(int var8 = 0; var8 < var7; ++var8) {
//获取当前索引var8位置的特性对象,并将其复制给变量feature
Feature feature = var6[var8];
//使用按位或操作符(|=)将当前特性的掩码(feature.mask)与featureValues进行按位或运算,并将结果重新赋值给featureValues
featureValues |= feature.mask;
}
}
//创建一个DefaultJSONParser对象parser,用于解析JSON字符串。这个对象使用传入的输入字符串、配置对象config和特性值featureValues进行初始化。
DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
//处理解析过程中的处理器processor,此时processor为null
if (processor != null) {
if (processor instanceof ExtraTypeProvider) {
parser.getExtraTypeProviders().add((ExtraTypeProvider)processor);
}
if (processor instanceof ExtraProcessor) {
parser.getExtraProcessors().add((ExtraProcessor)processor);
}
if (processor instanceof FieldTypeResolver) {
parser.setFieldTypeResolver((FieldTypeResolver)processor);
}
}
//解析JSON字符串并得到解析结果对象
T value = parser.parseObject(clazz, (Object)null);
//处理解析结果中的后续任务
parser.handleResovleTask(value);
//关闭解析器
parser.close();
//返回解析结果对象
return value;
}
}
for(int var8 = 0; var8 < var7; ++var8) {
Feature feature = var6[var8];
featureValues |= feature.mask;
}
DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
1687937426_649be192bdf7d20aea2f2.png!small
if (processor != null) {...}
这里是使用解析器parser对JSON字符串进行解析,并将解析结果赋值给变量value。解析的目标类型由参数clazz指定,该方法返回了一个泛型类型T的对象。
T value = parser.parseObject(clazz, (Object)null);
1687937451_649be1ab335e64a288968.png!small
T value = parser.parseObject(clazz, (Object)null);
1687937468_649be1bcbd81d8fb44dfd.png!small
public T parseObject(Type type, Object fieldName) {
//获取当前JSON的token类型
int token = this.lexer.token();
if (token == 8) {//如果当前token是JSON的null值(8代表null)
this.lexer.nextToken();//跳过null值解析
return null;
} else {
if (token == 4) {//如果当前token是JSON的字符串值(4代表字符串)
if (type == byte[].class) {//判断期望类型是否为 'byte[]'
byte[] bytes = this.lexer.bytesValue();//如果是,获取字节数组值
this.lexer.nextToken();//跳过字符串值的解析
return bytes;//返回字节数组值
}
if (type == char[].class) {//判断其我想是否为 'char[]'
String strVal = this.lexer.stringVal();
this.lexer.nextToken();
return strVal.toCharArray();//将字符串转换为字符数组并返回
}
}
//以上都不满足,根据期望类型获取相应的'ObjectDeserializer',并使用它来解析
ObjectDeserializer derializer = this.config.getDeserializer(type);
try {
return derializer.deserialze(this, type, fieldName);//通过config(ParserConfig对象)获取相应类型的反序列化器,并调用deserialze方法进行解析。该方法会根据给定的JSON类型和字段名,将当前解析器作为参数,返回解析后的Java对象。
} catch (JSONException var6) {
throw var6;
} catch (Throwable var7) {
throw new JSONException(var7.getMessage(), var7);
}
}
}
1687937487_649be1cfdddaa35c28dae.png!small
1687937506_649be1e228bb9e77e936c.png!small
ObjectDeserializer derializer = this.config.getDeserializer(type);
1687937526_649be1f63d5dfc461fc30.png!small
1687937545_649be2098a637e5a484fe.png!small
1687937561_649be21924eec7e17bac3.png!small
1687937578_649be22a3181634b60767.png!small
1687937595_649be23befa5d3db58b9d.png!small
public Object parse(Object fieldName) {
JSONLexer lexer = this.lexer;
switch(lexer.token()) {
case 1:
case 5:
case 10:
case 11:
case 13:
case 15:
case 16:
case 17:
case 18:
case 19:
default:
throw new JSONException("syntax error, " + lexer.info());
case 2:
Number intValue = lexer.integerValue();
lexer.nextToken();
return intValue;
case 3:
Object value = lexer.decimalValue(lexer.isEnabled(Feature.UseBigDecimal));
lexer.nextToken();
return value;
case 4:
String stringLiteral = lexer.stringVal();
lexer.nextToken(16);
if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
try {
if (iso8601Lexer.scanISO8601DateIfMatch()) {
Date var11 = iso8601Lexer.getCalendar().getTime();
return var11;
}
} finally {
iso8601Lexer.close();
}
}
return stringLiteral;
case 6:
lexer.nextToken();
return Boolean.TRUE;
case 7:
lexer.nextToken();
return Boolean.FALSE;
case 8:
lexer.nextToken();
return null;
case 9:
lexer.nextToken(18);
if (lexer.token() != 18) {
throw new JSONException("syntax error");
}
lexer.nextToken(10);
this.accept(10);
long time = lexer.integerValue().longValue();
this.accept(2);
this.accept(11);
return new Date(time);
case 12:
JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));
return this.parseObject((Map)object, fieldName);
case 14:
JSONArray array = new JSONArray();
this.parseArray((Collection)array, (Object)fieldName);
if (lexer.isEnabled(Feature.UseObjectArray)) {
return array.toArray();
}
return array;
case 20:
if (lexer.isBlankInput()) {
return null;
}
throw new JSONException("unterminated json string, " + lexer.info());
case 21:
lexer.nextToken();
HashSet
case 12:
JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));
return this.parseObject((Map)object, fieldName);
1687937621_649be2557609d8bd6b304.png!small
1687937638_649be2661f477f3ae3cd3.png!small
1687937659_649be27b4ae64330f43f7.png!small
ObjectDeserializer deserializer = this.config.getDeserializer(clazz);
1687937707_649be2ab4ca2056ff197f.png!small
1687937723_649be2bbb78f3011e7864.png!small
1687937739_649be2cbbdacbf8317390.png!small
public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
return this.deserialze(parser, type, fieldName, 0);
}
public T deserialze(DefaultJSONParser parser, Type type, Object fieldName, int features) {
return this.deserialze(parser, type, fieldName, (Object)null, features);
}
1687937757_649be2ddc1bba19ba32ea.png!small
1687937783_649be2f7307263c3af1de.png!small
1687937809_649be311a31ab9eaef38f.png!small
1687937832_649be32871d8efdcca30f.png!small
1687937864_649be3489d454e94368c4.png!small
......
1687937882_649be35a80d859b7490fc.png!small
boolean match = this.parseField(parser, key, object, type, fieldValues);
public boolean parseField(DefaultJSONParser parser, String key, Object object, Type objectType, Map fieldValues) {
//创建了一个JSONLexer对象,并将其初始化为 'parser'对象的 'lexer'属性
JSONLexer lexer = parser.lexer;
//smartMatch方法用于根据提供的字段名key匹配对应的字段解析器
FieldDeserializer fieldDeserializer = this.smartMatch(key);
//创建一个mask的整型变量,并设置为 'Feature.SupportNonPublicField.mask'的值
int mask = Feature.SupportNonPublicField.mask;
if (fieldDeserializer == null && (parser.lexer.isEnabled(mask) || (this.beanInfo.parserFeatures & mask) != 0)) {
if (this.extraFieldDeserializers == null) {
ConcurrentHashMap extraFieldDeserializers = new ConcurrentHashMap(1, 0.75F, 1);
Field[] fields = this.clazz.getDeclaredFields();
Field[] var11 = fields;
int var12 = fields.length;
//遍历当前类声明的字段,对每个字段进行一下操作:(1)获取字段名并检查是否已存在对应的字段解析器;(2)检查字段的修饰符,判断是否为非公共字段和非静态字段;(3)如果满足条件,则将字段添加到extraFieldDeserializers中。
for(int var13 = 0; var13 < var12; ++var13) {
Field field = var11[var13];
String fieldName = field.getName();
if (this.getFieldDeserializer(fieldName) == null) {
int fieldModifiers = field.getModifiers();
if ((fieldModifiers & 16) == 0 && (fieldModifiers & 8) == 0) {
extraFieldDeserializers.put(fieldName, field);
}
}
}
this.extraFieldDeserializers = extraFieldDeserializers;
}
Object deserOrField = this.extraFieldDeserializers.get(key);
if (deserOrField != null) {
if (deserOrField instanceof FieldDeserializer) {
fieldDeserializer = (FieldDeserializer)deserOrField;
} else {
Field field = (Field)deserOrField;
field.setAccessible(true);
FieldInfo fieldInfo = new FieldInfo(key, field.getDeclaringClass(), field.getType(), field.getGenericType(), field, 0, 0, 0);
fieldDeserializer = new DefaultFieldDeserializer(parser.getConfig(), this.clazz, fieldInfo);
this.extraFieldDeserializers.put(key, fieldDeserializer);
}
}
}
//如果fieldDeserializer为空,继续判断:
if (fieldDeserializer == null) {//如果lexer未启用Feature.IgnoreNotMatch,抛出异常
if (!lexer.isEnabled(Feature.IgnoreNotMatch)) {
throw new JSONException("setter not found, class " + this.clazz.getName() + ", property " + key);
} else {//否则调用'parser.parseExtra(object,key)'方法,将额外的字段解析给 object
parser.parseExtra(object, key);
return false;//false表示未成功解析字段
}
} else {//filedDeserializer不为空,通过下列方法将解析器移到字段值的冒号位置,并解析字段值
lexer.nextTokenWithColon(((FieldDeserializer)fieldDeserializer).getFastMatchToken());
((FieldDeserializer)fieldDeserializer).parseField(parser, object, objectType, fieldValues);
return true;//返回true表示成功解析
}
}
1687937908_649be374d92b4791d8cc9.png!small
1687937927_649be3878876a960d1fb7.png!small
1687937955_649be3a3ca8f30bead06d.png!small
1687937974_649be3b66336d9ef07807.png!small
本文作者:ZavaSec, 转载请注明来自FreeBuf.COM
本文标题:深入Fastjson源码命令执行调试
当前URL:http://www.shufengxianlan.com/qtweb/news46/298346.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联