方法一:利用java.net.Inet [4 | 6]地址
很早之前有一个方法是使用java.net.InetAddress类,现在这个类已经列入黑名单。而在翻阅fastjson最新版源码(v1.2.67)时,发现两个类没有在黑名单中,于是可以构造了如下有效载荷,可以使fastjson进行DNS解析。下面以java.net.Inet4Address为例分析构造原理。
{“@type”:“java.net.Inet4Address”,“val”:“dnslog”}
{“@type”:“java.net.Inet6Address”,“val”:“dnslog”}
我们知道在fastjson在反序列化之前都会调用checkAutoType方法对类进行检查。通过调试发现,由于java.net.Inet4Address不在黑名单中,所以就算开启AutoType也是能过1处的检查。
fastjson的ParserConfig类自己维护了一个IdentityHashMap,在这个HashMap中的类会被认为是安全的。在2处可以在IdentityHashMap中可以获取到java.net.Inet4Address,所以clazz不为null,导致在3处就返回了。跳过了后续的未开启AutoType的黑名单检查。所以可以发现无论AutoType是否开启,都可以过checkAutoType的检查
//com.alibaba.fastjson.parser.ParserConfig#checkAutoType
public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features) {
...
Class clazz;
// 1.当打开了autoTypeSupport,类名又不在白名单时进行的黑名单检查
if (!internalWhite && (this.autoTypeSupport || expectClassFlag)) {
hash = h3;
for(mask = 3; mask < className.length(); ++mask) {
hash ^= (long)className.charAt(mask);
hash *= 1099511628211L;
....
if (Arrays.binarySearch(this.denyHashCodes, hash) >= 0 && TypeUtils.getClassFromMapping(typeName) == null && Arrays.binarySearch(this.acceptHashCodes, fullHash) < 0) {
throw new JSONException("autoType is not support. " + typeName);
}
}
}
clazz = TypeUtils.getClassFromMapping(typeName);
if (clazz == null) {
// 2. fastjson的ParserConfig类自己维护了一个IdentityHashMap在这个HashMap中的类会被认为是安全的,会直接被返回。
clazz = this.deserializers.findClass(typeName);
}
if (clazz == null) {
clazz = (Class)this.typeMapping.get(typeName);
}
if (internalWhite) {
clazz = TypeUtils.loadClass(typeName, this.defaultClassLoader, true);
}
if (clazz != null) {
if (expectClass != null && clazz != HashMap.class && !expectClass.isAssignableFrom(clazz)) {
throw new JSONException("type not match. " + typeName