Fastjson BasicDataSource攻击链简介

「声明: 文中涉及到的相关漏洞均为官方已经公开并修复的漏洞,涉及到的安全技术也仅用于企业安全建设和安全对抗研究。本文仅限业内技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。」

Fastjson BasicDataSource攻击链简介

简介

这条攻击链用到”org.apache.tomcat.dbcp.dbcp.BasicDataSource”、”org.apache.tomcat.dbcp.dbcp2.BasicDataSource”或其他什么等价类。比较老,只能用于Fastjson 1.2.24及更低版本。

Fastjson攻击链更多是用”com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl”和”com.sun.rowset.JdbcRowSetImpl”,后者能一直用到Fastjson 1.2.47。

本来太老的攻击链没打算深究,后来觉得其中用到的BCEL编码有点意思,就调试跟踪了一下。

95%的人几年前就学过这招,如果仍有兴趣,可直接看”简化版调用关系”和”小结”。

org.apache.tomcat.dbcp.dbcp.BasicDataSource攻击链

参[73],后面的PoC用到了如下库:

tomcat-dbcp-7.0.99.jar
dbcp-6.0.53.jar
tomcat-dbcp-9.0.20.jar
tomcat-juli-9.0.20.jar

FastjsonDeserialize2.java

EvilCode.java

EvilCode没必要写成这样,我是顺手挪用别处的代码,你完全可以精简之。

BCELEncode.java

Utility.encode()的输出不包含”$$BCEL$$”前缀,需要自己增加。

BCELDecode.java

BCELDecode与攻击链无关,仅仅是因为前面有个负责编码的,出于程序员的本能反应,顺手写个负责解码的,保持对称性。

Fastjson_BasicDataSource.json

driverClassName属性的值就是BCELEncode输出的内容。

有人喜欢在PoC中用代码构造上述json内容,我的习惯是将各组件按自己的理解拆分,以保持边界感。没有什么特别优势,每个人的学习习惯不同,莫来我处装X。

这两条命令都能得手。

调试FastjsonDeserialize2:

简化版调用关系

com.sun.org.apache.bcel.internal.util.ClassLoader加载class时检查class_name是否动用过BCEL编码,如果是,class_name就不只是类名,还包含类的字节码的BCEL编码。util.ClassLoader会从类名中析取字节码并加载之,这可真是骚操作,太邪恶了。

为什么FastjsonDeserialize未能得手

java \
-cp “fastjson-1.2.24.jar:tomcat-dbcp-7.0.99.jar:.” \
FastjsonDeserialize Fastjson_BasicDataSource.json

上述命令使用FastjsonDeserialize,未能得手,不抛异常,静默结束。

FastjsonDeserialize调的是:

FastjsonDeserialize2调的是:

调试后确认前者内部不会调用JSON.toJSON(),从而无法触发EvilCode.。这个例子说明,JSON.parseObject()的不同重载版本对攻击链的反应各不相同,不要笼而统之地说函数名,一定要精确描述测试时所用上下文。

1.2.25的修补方案

“org.apache.tomcat”、”com.sun.”打头的全进黑名单。

1.2.25至1.2.47的所有补丁绕过方案均无法用于BasicDataSource利用链,各有原因。

Fastjson_BasicDataSource_bad_0.json

原始意图是进行补丁绕过,但1.2.25未能得手。

从1.2.25开始有一个无法绕过的检查:

Fastjson_BasicDataSource_bad_1.json

原始意图是进行补丁绕过,但1.2.25未能得手。

Fastjson_BasicDataSource_bad_2.json

原始意图是进行补丁绕过,但1.2.25未能得手。

Fastjson_BasicDataSource_bad_3.json

原始意图是进行补丁绕过,但1.2.25未能得手。失败原因同前。

org.apache.tomcat.dbcp.dbcp2.BasicDataSource

BasicDataSource所在package变了一点点,攻击原理同前。

Fastjson_BasicDataSource2.json

通用性更好的PoC

前面各小节写完后,发现存于待读队列中的KINGX的大作[76],我应该先读他这篇的,又多走了不少弯路。文中有个小八卦,应该是TSRC在2017年捕获到在野利用,其中有一个通用性更好的PoC,攻防双方都很厉害,佩服。

Fastjson_BasicDataSource3.json

这是KINGX所说的通用性更好的PoC。

反序列化时首先得到一个JSONObject对象,然后将该JSONObject对象置于”JSON Key”的位置。Fastjson在反序列化时会对”JSON Key”自动调用JSON.toString()。JSONObject是Map的子类,执行toString()时会将当前对象转为字符串形式,会提取类中所有Field,自然会执行相应的getter、is等方法,以此调用:

为完成攻击,必须调用上述函数。前面都是KINGX给的解释性说明,不关我事。

JSON.parse()、JSON.parseObject()有很多重载版本,其行为各不相同。网上有一些关于它们的小结,比如哪些getter会被调用。但我要说一句,这些小结你可以领会其大意,但绝不要当成真理,我看到的所有这类小结都不严谨,以偏概全,某些情况下会误导你。

不说各种重载版本JSON.parse()、JSON.parseObject()之间的区别,单说网上常提的”符合特定条件的getter会被调用”。参看:

那些所谓的特定条件都在这个函数中体现。建议看fastjson--sources.jar,如果用JD-GUI直接看fastjson-.jar,没有注释。参[33]。

在JavaBeanInfo.build()语境下,BasicDataSource.getConnection()不符合特定条件。而Fastjson_BasicDataSource3.json的写法增大了此getter被调用的可能性,这种写法不局限于BasicDataSource攻击链,诸君细品。

测试

与使用Fastjson_BasicDataSource.json时不同,上述两条命令均得手。

调试FastjsonDeserialize:

简化版调用关系

小结

BasicDataSource攻击链只能用于Fastjson 1.2.24及更低版本。

曾经用于JdbcRowSetImpl攻击链的1.2.25至1.2.47的所有补丁绕过方案均无法用于BasicDataSource攻击链,各有原因。

java.lang.Class.forName()有机会执行目标类静态代码块,jdb中可拦截some.<clinit>。

java.lang.ClassLoader.defineClass()并不会执行目标类静态代码块。

Class.forName0()中执行静态代码块时并不是通过ClassLoader.defineClass()触发的,native方法中另有触发点,触发点位于对defineClass()调用之后的某处。

com.sun.org.apache.bcel.internal.util.ClassLoader加载class时对类名有特殊流程,如果类名中包含”$$BCEL$$”子串,则判定此类名中还包含经BCEL编码过的类的字节码。此时util.ClassLoader会从特殊类名中解码还原出类的字节码并加载之,这个操作太邪恶。这是整个攻击过程中最有意思的部分,或许在别处用得上。

就BasicDataSource攻击链而言,可以不用静态代码块执行恶意代码,后面另有机会调用恶意类的无参构造函数,jdb中可拦截some.<init>。

“org.apache.tomcat.dbcp.dbcp2.BasicDataSource”亦可用于攻击。

参考资源

[32]

https://github.com/alibaba/fastjson

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.14/fastjson-1.2.14.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.24/fastjson-1.2.24.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.24/fastjson-1.2.24-sources.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.25/fastjson-1.2.25.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.25/fastjson-1.2.25-sources.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.42/fastjson-1.2.42.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.42/fastjson-1.2.42-sources.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.43/fastjson-1.2.43.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.43/fastjson-1.2.43-sources.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.45/fastjson-1.2.45.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.45/fastjson-1.2.45-sources.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.47/fastjson-1.2.47.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.47/fastjson-1.2.47-sources.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.48/fastjson-1.2.48.jar

https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.48/fastjson-1.2.48-sources.jar

[33] FastJson反序列化漏洞利用的三个细节TemplatesImpl利用链 – KINGX [2018-07-06]

https://mp.weixin.qq.com/s/C1Eo9wst9vAvF1jvoteFoA

https://paper.seebug.org/636/

[73]

https://repo1.maven.org/maven2/org/apache/tomcat/tomcat-dbcp/7.0.99/

https://repo1.maven.org/maven2/org/apache/tomcat/tomcat-dbcp/7.0.99/tomcat-dbcp-7.0.99.jar

https://repo1.maven.org/maven2/org/apache/tomcat/dbcp/6.0.53/

https://repo1.maven.org/maven2/org/apache/tomcat/dbcp/6.0.53/dbcp-6.0.53.jar

https://repo1.maven.org/maven2/org/apache/tomcat/tomcat-dbcp/9.0.20/

https://repo1.maven.org/maven2/org/apache/tomcat/tomcat-dbcp/9.0.20/tomcat-dbcp-9.0.20.jar

https://repo1.maven.org/maven2/org/apache/tomcat/tomcat-juli/9.0.20/

https://repo1.maven.org/maven2/org/apache/tomcat/tomcat-juli/9.0.20/tomcat-juli-9.0.20.jar

[76] Java动态类加载 当FastJson遇到内网 – KINGX [2019-12-31]

https://kingx.me/Exploit-FastJson-Without-Reverse-Connect.html

发表评论