Skip to content

Latest commit

 

History

History
54 lines (43 loc) · 3.67 KB

File metadata and controls

54 lines (43 loc) · 3.67 KB

执行任意命令(ClosureWithRuntime)

  • 类别:javanative 别名:— 优先级:—
  • 作者:—
  • 依赖org.codehaus.groovy:groovy:2.4.3

作用

构造一个 org.codehaus.groovy.runtime.MethodClosure,其目标对象为命令字符串、目标方法为 "execute"。当上游 Groovy 链在反序列化时触发该闭包的 call(),即调用 String.execute()(Groovy 为 String/CharSequence 注入的扩展方法),最终走到 Runtime.exec 执行系统命令。是 Groovy MethodClosure 利用链的命令执行 sink。

链接标签

  • 入口 tagsClosureWithRuntimeChain —— 承接上游产出 nextTags=ClosureWithRuntimeChain 的 gadget(GroovyGroovy2GString 等),由它们把本闭包包进 Groovy 代理触发结构。
  • 入口 tagsEND —— 本 gadget 是链尾 sink,其后不再接其它构件(nextTags 为空)。
  • 衔接 nextTags:无。
  • excludes:无。

源码剖析

@GadgetTags(tags={"ClosureWithRuntimeChain", "END"})
@GadgetAnnotation(name="执行任意命令", dependencies={"org.codehaus.groovy:groovy:2.4.3"})
public class ClosureWithRuntime implements Gadget {
    @Param(name="命令")
    public String cmd = "calc";

    public Object getObject() throws Exception {
        return new MethodClosure((Object)this.cmd, "execute");
    }

    @Override
    public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
        return this.getObject();
    }
}

逻辑极简:直接 new MethodClosure(cmd, "execute")MethodClosuregroovy.lang.Closure 的子类,构造时保存 owner=cmd(命令字符串)与 method="execute"。这里不调用 chain.doCreate(context)——因为它是链尾,目标对象就是用户输入的命令字符串本身,无需内层 gadget。

触发路径(由上游 Groovy gadget 提供):反序列化 AnnotationInvocationHandler(memoized 代理)→ 其 readObject 遍历成员时对 Map 代理调用 entrySet()ConvertedClosure.invokeCustomClosure.call()MethodClosure 以无参形式在 owner 上反射调用 method,即 "calc".execute()。Groovy 运行时通过 DefaultGroovyMethods/ProcessGroovyMethodsString 提供 execute() 扩展,内部 Runtime.getRuntime().exec(this) 完成命令执行。

参数(@Param)

字段 名称 说明 默认 可选值
cmd 命令 待执行的系统命令(作为 MethodClosure 的 owner 对象,通过 String.execute() 运行) calc 自由文本

适用版本与原理要点

  • 依赖 org.codehaus.groovy:groovy:2.4.3MethodClosure 在 2.4.3 与 2.4.4+ 的 serialVersionUID 不同,若目标环境是 2.4.4~2.4.7 需改用带 SUID 兼容处理的 ClosureWithRuntimeSandboxed
  • String.execute() 走的是 shell 无关的 Runtime.exec(String),命令按空白分词,复杂命令建议用数组或 bash -c 形式(可借 sandbox 变体或改写 owner)。
  • 无参触发:Groovy 链的 entrySet 调用不带参数,故 sink 方法必须为无参可用的方法,execute 满足。

所属预设链

  • 自由构件,未直接出现在预设链(usedInChains 为空)。需与 Groovy/Groovy2GString 等上游手动组合成完整链。

关联