CSDNfastjson到底做错了什么?为什么会被频繁爆出漏洞?( 三 )

L; , 形如Lcom.lang.Thread;


CSDNfastjson到底做错了什么?为什么会被频繁爆出漏洞?
本文插图
而黑白名单又是通过startWith检测的 , 那么黑客只要在自己想要使用的攻击类库前后加上L;就可以绕过黑白名单的检查了 , 也不耽误被fastjson正常加载 。 如Lcom.sun.rowset.JdbcRowSetImpl; , 会先通过白名单校验 , 然后fastjson在加载类的时候会去掉前后的L变成了com.sun.rowset.JdbcRowSetImpl 。 为了避免被攻击 , 在之后的 v1.2.42版本中 , 在进行黑白名单检测的时候 , fastjson先判断目标类的类名的前后是不是L; , 如果是的话 , 就截取掉前后的L;再进行黑白名单的校验 。 看似解决了问题 , 但是黑客发现了这个规则之后 , 就在攻击时在目标类前后双写LL;; , 这样再被截取之后还是可以绕过检测 。 如LLcom.sun.rowset.JdbcRowSetImpl;;魔高一尺 , 道高一丈 。 在 v1.2.43中 , fastjson这次在黑白名单判断之前 , 增加了一个是否以LL未开头的判断 , 如果目标类以LL开头 , 那么就直接抛异常 , 于是就又短暂的修复了这个漏洞 。 黑客在L;这里走不通了 , 于是想办法从其他地方下手 , 因为fastjson在加载类的时候 , 不只对L;这样的类进行特殊处理 , 还对[也被特殊处理了 。 同样的攻击手段 , 在目标类前面添加[ , v1.2.43以前的所有版本又沦陷了 。 于是 , 在 v1.2.44版本中 , fastjson的作者做了更加严格的要求 , 只要目标类以[开头或者以;结尾 , 都直接抛异常 。 也就解决了 v1.2.43及历史版本中发现的bug 。 在之后的几个版本中 , 黑客的主要的攻击方式就是绕过黑名单了 , 而fastjson也在不断的完善自己的黑名单 。 autoType不开启也能被攻击?但是好景不长 , 在升级到 v1.2.47 版本时 , 黑客再次找到了办法来攻击 。 而且这个攻击只有在autoType关闭的时候才生效 。 是不是很奇怪 , autoType不开启反而会被攻击 。 因为在fastjson中有一个全局缓存 , 在类加载的时候 , 如果autotype没开启 , 会先尝试从缓存中获取类 , 如果缓存中有 , 则直接返回 。 黑客正是利用这里机制进行了攻击 。 黑客先想办法把一个类加到缓存中 , 然后再次执行的时候就可以绕过黑白名单检测了 , 多么聪明的手段 。 首先想要把一个黑名单中的类加到缓存中 , 需要使用一个不在黑名单中的类 , 这个类就是java.lang.Classjava.lang.Class类对应的deserializer为MiscCodec , 反序列化时会取json串中的val值并加载这个val对应的类 。

CSDNfastjson到底做错了什么?为什么会被频繁爆出漏洞?
本文插图
如果fastjson cache为true , 就会缓存这个val对应的class到全局缓存中
如果再次加载val名称的类 , 并且autotype没开启 , 下一步就是会尝试从全局缓存中获取这个class , 进而进行攻击 。 所以 , 黑客只需要把攻击类伪装一下就行了 , 如下格式:{"@type": "java.lang.Class","val": "com.sun.rowset.JdbcRowSetImpl"}于是在 v1.2.48中 , fastjson修复了这个bug , 在MiscCodec中 , 处理Class类的地方 , 设置了fastjson cache为false , 这样攻击类就不会被缓存了 , 也就不会被获取到了 。 在之后的多个版本中 , 黑客与fastjson又继续一直都在绕过黑名单、添加黑名单中进行周旋 。 直到后来 , 黑客在 v1.2.68之前的版本中又发现了一个新的漏洞利用方式 。 利用异常进行攻击在fastjson中 ,如果 , @type 指定的类为 Throwable 的子类 , 那对应的反序列化处理类就会使用到 ThrowableDeserializer而在ThrowableDeserializer#deserialze的方法中 , 当有一个字段的key也是 @type时 , 就会把这个 value 当做类名 , 然后进行一次 checkAutoType 检测 。 并且指定了expectClass为Throwable.class , 但是在checkAutoType中 , 有这样一约定 , 那就是如果指定了expectClass, 那么也会通过校验 。


推荐阅读