记一次fastjson升级产生的bug

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

记录一次fastjson产生的bug

由于fastjson采白名单的方法来防御反序列化满洞,导致当黑客不断发屈新的反序列化Gadgets类时,在autoType关闭的情况下仍然可能可以绕过黑白名单防御机制,造成远程命令执行漏洞。经研究,该漏洞利用门槛较低,可绕过autoType限制,风险影响较大。阿里云应急响应中心提醒fastjson用户尽快采取安全措施阻止漏洞攻击。

但是在升级的过程中,有一个项目出现了问题。出现的问题是,使用大写字母作为属性命名的javaBean,在使用这个方法时出问题。

1
2
java复制代码//parseObject(String text, Class<T> clazz) 
Input input = JSONObject.parseObject(request.getData().toJSONString(), Input.class);

上面的代码中,得出来的input为空。

在fastjson的DefaultJSONParser这个类中两个不同版本的fastjson处理选择了不同的方式。

1.2.12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
java复制代码public <T> T parseObject(Type type, Object fieldName) {
int token = this.lexer.token();
if (token == 8) {
this.lexer.nextToken();
return null;
} else {
if (token == 4) {
if (type == byte[].class) {
byte[] bytes = this.lexer.bytesValue();
this.lexer.nextToken();
return bytes;
}

if (type == char[].class) {
String strVal = this.lexer.stringVal();
this.lexer.nextToken();
return strVal.toCharArray();
}
}

ObjectDeserializer derializer = this.config.getDeserializer(type);

try {
//这里有所不同
return derializer.deserialze(this, type, fieldName);
} catch (JSONException var6) {
throw var6;
} catch (Throwable var7) {
throw new JSONException(var7.getMessage(), var7);
}
}
}

从调试中可以看到,1.2.12版本中属性赋值使用的是通过属性的set方法进行的。

clipboard.png

1.2.70版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
java复制代码public <T> T parseObject(Type type, Object fieldName) {
int token = this.lexer.token();
if (token == 8) {
this.lexer.nextToken();
return null;
} else {
if (token == 4) {
if (type == byte[].class) {
byte[] bytes = this.lexer.bytesValue();
this.lexer.nextToken();
return bytes;
}

if (type == char[].class) {
String strVal = this.lexer.stringVal();
this.lexer.nextToken();
return strVal.toCharArray();
}
}

ObjectDeserializer deserializer = this.config.getDeserializer(type);

try {
if (deserializer.getClass() == JavaBeanDeserializer.class) {
if (this.lexer.token() != 12 && this.lexer.token() != 14) {
throw new JSONException("syntax error,except start with { or [,but actually start with " + this.lexer.tokenName());
} else {
//更新后走了这里
return ((JavaBeanDeserializer)deserializer).deserialze(this, type, fieldName, 0);
}
} else {
//原来的版本走的是这里
return deserializer.deserialze(this, type, fieldName);
}
} catch (JSONException var6) {
throw var6;
} catch (Throwable var7) {
throw new JSONException(var7.getMessage(), var7);
}
}
}

而1.2.70却是通过这样的方式去解析的。

clipboard.png

最后经过查阅资料,发现可以使用@JSONField(name = "AAA001")这个注解来解决这个问题,在入参的类上进行标注,大写的入参也可以转换了。

1
2
java复制代码@JSONField(name = "AAA001)
private String AAA001; //属性1

同时有部分人因为使用lombok插件,导致@JSONField(name = "AAA001")标注在属性上依旧不起作用,此时可以通过显示声明属性的get方法来达成目的。

1
2
3
4
java复制代码    @JSONField(name = "AAA001")
public String getAAA001() {
return AAA001;
}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%