文章总结: 本文深入分析Fastjson高版本利用机制,解析checkAutoType与ClassLoader策略,阐述利用WebappClassLoader加载docbase恶意类的方法。针对1.2.83限制,提出通过目录穿越写入jre/lib替换懒加载jar包的绕过思路,并优化commons-io兼容性,整合为自动化利用链工具。 综合评分: 87 文章分类: 漏洞分析,代码审计,WEB安全,渗透测试
java安全最严厉的父亲-fastjson 高版本利用
原创
Unam4
亿人安全
2026年1月13日 18:02 北京
原文首发在:奇安信攻防社区
链接:https://forum.butian.net/share/4715
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/
https://flowerwind.github.io/2025/02/28/%E5%88%86%E4%BA%AB%E4%B8%80%E6%AC%A1%E7%BB%84%E5%90%88%E6%BC%8F%E6%B4%9E%E6%8C%96%E6%8E%98%E6%8B%BF%E4%B8%8B%E7%9B%AE%E6%A0%87/
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:亿人安全 Unam4《java安全最严厉的父亲-fastjson 高版本利用》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论