- 类别:javanative 别名:— 优先级:—
- 作者:—
- 依赖:无(纯 JDK)
构造一个 java.lang.ProcessBuilder,预置好待执行的命令行;当上游 gadget 触发其 start() 方法时即执行任意系统命令。是不依赖任何第三方库的命令执行 sink。
- 入口
tags:无(@GadgetTags空标注)——不通过标签自动串联,需人工作为终点组合,或由能调用start()的上游包裹。 - 衔接
nextTags:无——本类是链尾 sink,无下游。 excludes:无。
@Param(name="命令")
public String cmd = "calc";
public String action = "start";
public java.lang.ProcessBuilder getObject() throws Exception {
List<String> cmd = Arrays.asList(this.cmd.split(" "));
return new java.lang.ProcessBuilder(cmd);
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
context.put(ContextTag.SPECIAL_METHOD_NAME_KEY, "start");
return this.getObject();
}getObject 将用户参数 cmd 按空格切分为 List<String>(如 "calc" 或 "/bin/sh -c id"),交给 new java.lang.ProcessBuilder(cmd) 构造,返回该 ProcessBuilder 对象本身。
invoke 不调用 chain.doCreate(无内层),只向 GadgetContext 写入 SPECIAL_METHOD_NAME_KEY = "start",声明上游触发器应调用的方法名是 ProcessBuilder.start()——正是执行进程的入口。真正的命令执行发生在上游 gadget 在反序列化期间调用 start() 那一刻。
注意:ProcessBuilder 本身不实现 Serializable,因此它不能作为独立可反序列化对象,必须由上游 gadget(如通过 TemplatesImpl 字节码、MethodHandles、Transformer 等反射机制)在反序列化过程中主动 start() 才能落地。相比链尾常见的 Exec(产出 ProcessBuilder 字节码经 BytecodeConvert 装入 TemplatesImpl),本 gadget 直接给出的是 ProcessBuilder 对象,用于依赖「调用任意方法」的触发场景。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
cmd |
命令 | 待执行命令,按空格切分为 argv 数组 | calc |
自由输入 |
(action 为公开字段,固定 start,即上游应调用的方法名,非用户参数。)
- 纯 JDK,无版本/依赖约束;命令按空格 split,含空格参数需注意分词(无 shell 解析,建议用
/bin/sh -c "..."形式自行包裹)。 - 触发点是
start()而非 getter/toString,需上游具备「调用指定方法」能力。 - 因 ProcessBuilder 不可序列化,通常作为「方法调用型」sink 与反射触发器搭配,而非直接作为反序列化根对象。
自由构件,未直接出现在预设链(usedInChains 为空)。命令执行预设链一般走 BytecodeConvert + Exec 的字节码路线。
- 同类命令执行 sink:
Exec(字节码形式的 ProcessBuilder,经 BytecodeConvert 装入 TemplatesImpl)、ExecCustom。 - 可能的上游触发器:能调用任意方法的反射类 gadget(如
TransformerWithMethodHandles、SwingLazyValueMethodUtil等)。