KSNCTF #9 Digest is secure!
問題
考えたこと
だいたい #8 と同じような感じだけど、認証のところが Digest になってて、データのやりとりとか難しそうなことをしてる。
仕組みは wikipedia 読んでだいたい分かった。
Base64 でエンコードみたいなガバガバな通信じゃなくて MD5 方式で暗号化されている。
wikipedia の言葉をそのまま使うと、とりあえずパケットから
Authorization: Digest
username="q9"
realm="secret"
nonce="bbKtsfbABAA=5dad3cce7a7dd2c3335c9b400a19d6ad02df299b"
uri="/~q9/"
algorithm=MD5
response="c3077454ecf09ecef1d6c1201038cfaf"
qop=auth
nc=00000001
cnonce="9691c249745d94fc"
MD5 はそんなに強くない暗号らしい。とりあえずレスポンスが c3077454ecf09ecef1d6c1201038cfaf
だということは分かったので、これを decrypt しないといけないっぽい。
md5 decrypt とかでググって上から順番に試してやっと解いてくれた。
MD5 Decryption: Encrypt & Decrypt MD5 Hashes
c627e19450db746b739f41b64097d449:bbKtsfbABAA=5dad3cce7a7dd2c3335c9b400a19d6ad02df299b:00000001:9691c249745d94fc:auth:31e101310bcd7fae974b921eb148099c
レスポンスは hash1:nonce:nc:cnonce:qop:hash2 という文字列を暗号化したものらしいのでちゃんと解読できてそう。
この hash1 は ユーザ名:realm:パスワード を暗号化したものなので、これを decrypt すればよさそうだけど、 google 先生の2ページまでの decrypter 全部試したけどだめだった。助けてくれ!!!!
ここまで書こうとしたけど、 hash1 は 分かってるし、 hash2 は httpmethod:uri をMD5 encrypt すればいいので、サーバから送られてきた nonce に対して適当に cnonce を生成して response 作って投げれば認証成功する気がする。コード書いた。
https://github.com/sekai013/ksnctf/blob/master/digest/digest.rb
通った。やったぜ。
思ったこととか
hash1 だけじゃなくて 2 もそのまま使えるやんと思ってたけど、パケットでは /~q9/
にリクエストしてるけど、旗のある場所は /~q9/flag.html
なので hash2 も変えないといけないということに気づくのに1時間くらいかかった。
最初は MD5 decrypter に投げるだけかよおいおいって感じになったけどそんなことはなかった。
1回目で解けなくて投げたけどブログ書いてる間に思いついて解けた。やっぱり復習というかしばらくしてから見直すのも良さそう。
KSNCTF #8 Basic is secure?
問題
考えたこと
HTTP のパケットっぽい。
認証が必要なページにアクセスして、Basic 認証を経てコンテンツを取得しているらしい。
旗は認証のパスワードらしい。
Authorization: Basic cTg6RkxBR181dXg3eksyTktTSDhmU0dB
これ認証情報な気がしたので、「Basic パスワード 解析」とかでググった。
メールやFTP、ベーシック認証のパスワードを忘れたときの対処法 - [その他 + その他] ぺんたん info
Base64 やんけ!ということで前書いたデコーダーでデコードしたら旗出てきた。
思ったこととか
これ書いてて思ったけど、問題のファイルには .pcap って拡張子がついてる。気付いてなかった。
なるほど。
量がすくなかったのでさーっと眺めてたら怪しそうなの見つかったけど、ちゃんとしたビューワーもある。
apt-get install wireshark
で入る。
basic 認証は username:password という文字列を Base64 で変換して送ってるだけらしい。なるほど。
KSNCTF #7 Programming
問題
考えたこと
*.cpp って C++ の拡張子だったよなという感じで普通にコンパイルして実行した。
% gcc program.cpp % ./a.out FROG_This_is_wrong_:(%
はい。
コンパイル時に警告めっちゃ出たのでそこが脆弱性なのかもと思ったけど、プログラムの脆弱性を突く問題ならコンパイルしたあとの実行ファイルだけ配ればいいはずで、ソースコードを渡してきてるということはソースに意味があるという気がした。
インデントとか無駄なスペースを消してソースを見やすくして見てみたりしたけど何も得られなかった。
gcc でコンパイルできてしまったけど、 C++ はコンパイルの仕方が違うのか?とか思って調べて g++ とかでコンパイルしたりしたけど結局わからなかった。
諦めてググったら whitespace という言語があるらしい。
拡張子に騙されてしまった。ググったら ws2js という JavaScript への変換機能つきのインタプリタを見つけたのでコード投げたら、PIN を入力しろと言われたけど、変換されて出てきた JavaScript のコードみたらなんとなく分かったのでそのまま入力したら旗取れた。
Whitespace Interpreter written in JavaScript
思ったこととか
知ってるかググるかというタイプはなんか微妙な気がするけど、知らない側がそれを言っても仕方ないし、CTF やってる人にとっては知ってて当たり前なのかもしれない。
今後も似たような問題見るかもしれないし、たまたま聞いたりした esolang は覚えておくとか、拡張子を鵜呑みにしないとかそういうところは意識していきたい。
esolang といえば大学で聞いた Grass を思い出す。
KSNCTF #6 Login
問題
考えたこと
指定されたページに飛ぶと admin としてログインしろと言われたのでとりあえず ID, Pass 両方 admin で送信するとダメだよと言われる。
ちなみに ID, Pass 両方 admin にしたのは大学から借りた MacBook Air がそうなっていたからで、つい手が動いた。
気を取り直して SQL インジェクションを試してみた(本で読んだ)。
ID, Pass に 'or 1=1--
を入力して送信したらあっさり通った。ドヤ顔でページ読んだら、「旗は admin のパスワードだよ」ってことと、ヒントとして認証ページのソースが書いてあった。認証突破するだけじゃダメらしい。
<?php //認証部分抜粋 function h($s){return htmlspecialchars($s,ENT_QUOTES,'UTF-8');} $id = isset($_POST['id']) ? $_POST['id'] : ''; $pass = isset($_POST['pass']) ? $_POST['pass'] : ''; $login = false; $err = ''; if ($id!=='') { $db = new PDO('sqlite:database.db'); $r = $db->query("SELECT * FROM user WHERE id='$id' AND pass='$pass'"); $login = $r && $r->fetch(); if (!$login) $err = 'Login Failed'; } ?>
SELECT pass FROM user でいけるのでは?という気がしたけど出力されないから pass を知る手段がない。
SQL さっぱりわからん。ブルートフォースアタックは流石にキツそう。
ググったらブラインド SQL インジェクションというのがあることを知った。
WHERE id='' OR (SELECT length(pass) FROM user WHERE id='admin') <= length
みたいな WHERE 句を作ればパスワードの長さを絞っていける。長さが分かったら
WHERE id='' OR substr((SELECT pass FROM users), n, 1)='a'
みたいなコードで頑張れる。 JavaScript っぽく書くと pass.charAt(n) === 'a'
みたいなことをやる。
頑張れそうだけど、手動では頑張れないのでコード書いた。
https://github.com/sekai013/ksnctf/blob/master/login/login.rb
二分探索でパスワード文字数を調べて、あとは総当りで何文字目が何なのか調べる。 走らせたら何分かで旗出てきた。
思ったこととか
SQL は全部ググった。substr とか length みたいなメソッドがあることも知らなかった。
流石に SQL 読み書きできるようになりたい。 SQL さえ知っていればググらずに思いつけた気がする。頑張りたい。
KSNCTF #5 Onion
問題
考えたこと
知ってるやつ。 Base64 とかいうやつ。
ググってデコーダ見つけたのでぶち込んだらまだ暗号化されたままだった。
何重にも暗号化されてる気がしたので、出力をコピペしてまた入力に…ってやるのはめんどくさかったのでコード書いた。
https://github.com/sekai013/ksnctf/tree/master/onion
10何回かデコードしたら意味ありそうのが出てきた。
begin 666
51DQ!1U]&94QG4#-3:4%797I74$AU
end
まだ暗号文だけど、記号的にもう Base64 ではなさそう。
begin 666 でググると uuencode というのが出てくる。
デコードは UNIX の uudecode コマンドでできるらしいけど、コマンドみつからないって言われてしまったのでググってデコーダ見つけた。デコードしたら旗出てきたので入力したら通った。
思ったこととか
知ってたから最初の取っ掛かりが楽で、あとはググっていったら解けたという感じだった。
Base64, uuencode は電子メールでよく使われる暗号化方式らしい。
KSNCTF #4 Villager A [uncompleted]
問題
考えたこと
ssh q4@ctfq.sweetduet.info -p 10022
ログインできた。とりあえず
[q4@localhost ~]$ ls flag.txt q4 readme.txt
ちょろw
[q4@localhost ~]$ cat flag.txt cat: flag.txt: 許可がありません
はい。
[q4@localhost ~]$ cat readme.txt You are not allowed to connect internet and write the home directory. If you need temporary directory, use /tmp. Sometimes this machine will be reset.
なるほど。
[q4@localhost ~]$ file q4 q4: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
なるほど。実行できるらしい。
何回か実行した結果、名前を入力すると、それを echo して、その後 do you want the flag? という質問を繰り返し、 no と入力されるとプログラムを終了するという感じのプログラムなのは分かった。
ググったり gdb disas
したりした結果、 名前を echo するところに format string の脆弱性があることが分かった。
[参考] format string attack (ググった)
ここから1時間半くらい何もわからなかったので風呂入って寝た。得点も高いし初心者にはまだ早いということにした。
x86 に慣れるとか gdb の使い方を知るとかが必要な気がする。
飛ばして他の問題を一通り解いてきたら戻ってきたい。