- 类别:bytecode 别名:— 优先级:—
- 作者:ReaJason
- 依赖:无(产物为纯字节码,运行时依赖目标环境的 Jetty)
产出一段预写好的 Jetty 回显恶意类字节码:该类被目标 JVM 加载/实例化后,会从当前 Jetty 请求线程上下文中取出 HTTP 请求,读取指定 Header(默认 X-Authorization)作为命令执行,并把结果以明文写回响应,实现「无文件落地」的命令执行回显。是一个链尾字节码 sink(END)。
- 入口
tags:Bytecode、Echo、END——Bytecode表示本 gadget 的产物是字节码byte[];Echo标识其属于回显类载荷;END表示它是链的终点(sink),其后不再接任何 gadget。 - 衔接
nextTags:空 —— 作为终点不向后衔接。 excludes:无。
作为一段字节码 sink,它通常由上游的「字节码装载器」承接:即前一环需要能吃下 byte[] 并把它 defineClass/实例化,例如 BytecodeConvert 把字节码塞入 TemplatesImpl 再由某个 Java 反序列化跳板触发 newTransformer()。
本类逻辑极简,核心是「取一个模板类 + 回填 Header 字段 + 导出字节码」:
@GadgetTags(tags={"Bytecode", "Echo", "END"})
@GadgetAnnotation(name="生成 Jetty 命令执行明文回显的字节码", authors={"ReaJason"})
public class JettyEcho implements Gadget {
@Param(name="请求头 key", description="执行命令的 Header 头")
public String header = "X-Authorization";
public byte[] getObject() throws Exception {
JavassistHelper javassistHelper = new JavassistHelper(JettyEchoBytecode.class);
javassistHelper.modifyStringField("header", this.header);
return javassistHelper.getBytecode();
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
chain.doCreate(context);
return this.getObject();
}
}逐段解释:
- 模板类:真正的回显逻辑写死在
com.ar3h.chains.gadget.impl.bytecode.echo.template.JettyEchoBytecode中(一个预编译好的 Java 类)。JavassistHelper以该类为蓝本读入其原始字节码。 - 字段回填:
modifyStringField("header", this.header)通过 Javassist 直接改写模板类里header字段的常量初值,把用户配置的 Header 名(如X-Authorization)写进字节码,从而无需重新编译即可定制「读哪个请求头取命令」。 - 导出:
getBytecode()返回改写后的byte[],即最终注入目标的恶意类字节。 invoke:先chain.doCreate(context)触发内层(本例中链一般为空/收尾),再getObject()。注意本 gadget 只产出字节码,不负责让目标加载它——加载动作由上游装载器(如TemplatesImpl的defineTransletClasses)完成。
由于回显逻辑固定在模板类,本条目不涉及运行时反射构造,其安全语义完全取决于 JettyEchoBytecode 模板在被加载时会执行的操作(取 Jetty 请求线程的 request/response、读 Header、Runtime.exec 并写回响应)。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
header |
请求头 key | 恶意类从该 Header 读取待执行命令 | X-Authorization |
任意字符串 |
- 适用于运行 Jetty 的目标(回显逻辑针对 Jetty 的请求上下文获取方式定制)。
- 属于「回显」类:无需外连、无需落地文件,命令与结果都走同一个 HTTP 请求/响应,隐蔽性高。
- 本 gadget 只生成字节码,必须搭配能把
byte[]变成「被加载的类」的上游装载器才能真正触发。
usedInChains 为空——自由构件,未直接出现在 51 条预设链中。作为回显 sink,可替换任意「命令执行 sink」(如 Exec)用于回显场景。
- 上游(吃
Bytecode的装载器):BytecodeConvert →TemplatesImpl等字节码装载跳板。 - 同族(其它中间件回显字节码 sink):
TomcatEcho、ResinEcho、WebLogicEcho、UndertowEcho、GlassFishEcho等,均以相同的「模板类 +JavassistHelper回填」方式产出,仅回显逻辑针对各自中间件不同。