java安全最严厉的父亲-fastjson 高版本利用
0x01 简介
主要还是看killer那个 ctf,然后以前实战也没怎么认真去打(坑太多了)。这次正好学习一下。
0x02 fastjson 加载
com.alibaba.fastjson.parser.ParserConfig#checkAutoType(java.lang.String, java.lang.Class<?>, int)

主要就是检查@type 指定的类

然后在判断时候在在反序化的map、缓存的map中,然后判断是不是白名单。

要是获取到就判断这些。不是期望类直接就包type not match。基本高版本要是不指定期望类,这一步就g了
0x03 写class后fastjson 加载机制(docbase)

如果我们利用cmonsio写入文件后, 这里都会获取不到,不再缓存 不是白名单,且这个classloader为null

这个时候就会调用classloader去获取这个class的流

这里清楚可以看到是sun.misc.Launcher$AppClassLoader


他的classpath路径jre的lib,jre下的class(默认没有)和项目的lib目录。
我们要是写文件在docbase目录下, 使用这个classloader是加载不到的。

最后来到这里
若果他是白名单类、jsonType,期望类的话。就会调用TypeUtils.loadClass(typeName, this.defaultClassLoader, cacheClass),要是这个类是白名单或者jsonType就会进行缓存
com.alibaba.fastjson.util.TypeUtils#loadClass(java.lang.String, java.lang.ClassLoader, boolean)

来到这里,这个defaulrclassloder是null,所以这里都是加载不到我们写入到docbase的类。

最后会来到这里。使用当前线程的classloader来加载

可以看到是webappclassloader


这里可以清楚看到docbase的目录。也就是说写入到docbase下的类要用webappclassloader才能加载到。

根据cache标志位,是否加入缓存。这cache就是前面提到的


最后又再次判断。
这也是为什么我写入到docbase后,要使用
{
"@type":"java.lang.Exception",
"@type":"org.example.Exception"
}
这种形式来加载,expectClassFlag这样为true,然后使用webappclassloaer加载。
0x04 fastjson 1.x 全版本饶过
再回到上面

如果我们获取到class的流,然后调用ClassReader读入,在字节信息中获取到jsonType信息,jsonType就会改为true。也就是完全可以写一个后门类,类打上@JSONType就行。

这样就能符合它的判断,jsontype标志位也变为true

最后加入缓存。这样1.2.83也能触发。
但是在cmonsio写文件下这种情况下没什么意义, 写docbase 继承期望类就能正常加载,不继承在过不了判断,无法使用webappclassload加载,也就获取不到类,写到jre/lib需要替换懒加载的jar包,毫无意义。
0x05 1.2.83 fastjson利用
在1.2.83的情况下,类名结尾为Exception或Error会直接返回null。
这个时候只能在sun.misc.Launcher$AppClassLoade来加载,也就是在jre下找利用,就是最经典的写懒加载jar包替换。
一般以chaset.jar、nashorn.jar,dnsns.jar 为主。
需要结合目录穿越写文件写到jre/lib目录。

一般在源码写上然后编译,这样不影响正常功能。
为了方便复现。这里只打包一个类

改成83 手动替换jar



0x06 commonsio 优化
org.apache.commons.io.input.CharSequenceInputStream
在commons-io 2.0-2.1上是没有的, 以及在高低版本上字节信息不同。c/cs


所以这里我套娃了一下,用org.apache.commons.io.input.CharSequenceReader的是配,这样io在2.0-2.7上都能利用。
再就是在不同系统os上,类随机到构造方法不同,导致写不了二进制数据。

io低版本会在linux随到decoder这个构造,不给decoder赋值,在解码流就会包空异常,

能利用的就是utf8,写不了二机制,只能利用ascii jar写入。实战千万别用,要是没打下目录,lib替换了影响服务。

随到这个就正常对charset赋值可以二进制数据。其余都没什么好说的了。
0x07 加入chains
不得不说,fastjson真是java安全绕不过的大山。为此我也加入到chains。支持1.2.68 ,1.2.75-1.2.80.
io 2.0-2.7写文件

在能写二进制的情况下直接选就行
不能写二进制的话,使用

进行上传你要写的文件。

然后根据情况选择payload。
rerference
https://su18.org/post/fastjson-1.2.68/