はらへり日記

腹に弾丸

CTF for ビギナーズ Finalに参加してきました(Write up)

CTFはかじったことはあったけどどんな解き方があるかとか全然わからなかったので参加してきた。

2016.seccon.jp

講義のおかげか、運良くぽんぽん問題が解けて3位になれました。

講義も演習も楽しく取り組むことができました。運営の皆様お疲れ様でしたm( )m

Write up

自分が解けて覚えてるものだけ書いておきます。

解けなかったのはファイル持ち帰ったので時間あるときに取り組んでまたWrite up書きたいと思います。

解けた問題はこんな感じ。

f:id:sota1235:20170129233111p:plain

Misc 100 Welcome

解くだけ。サービス問題。

Misc 200 CountUp Game

問題文の案内通り、サーバに接続するとゲームが始まる。

お互い、3つまで数字を言って21を言ったら負けなゲーム。

ただし必ず相手が先攻で始まる。

問題数が多かったらプログラムで自動化しないと無理だったけど10問だったので手動で解いた。

基本的に相手に5, 9, 13, 17を言わせるようにすれば必ず勝てるのでその通りに解いていく。

Web 100 Classical Injection

ユーザ名とパスワードを入れるテキストフォームが表示される。

データベース系と見てシングルクォーテーションを入れるとエラーが表示される。

そこで以下のようなSELECT文が実行されると仮定してみる。

$sql = "SELECT * FROM users WHERE loginid = '${loginid}' AND password = '${password}'";

そこでユーザ名のテキストフォームに' OR 1 = 1;--と打ち込んで後半の条件文を無視するようにインジェクションするとログインができてflagが表示される。

Web 100 May the extensions be with you.

問題忘れてしまいました…誰かWrite up頼むorz

Web 200 もぐもぐ(・~・)

アプリにアクセスすると検索フォームが表示される。

f:id:sota1235:20170129233921p:plain

適当に文字を打って検索すると検索結果がないと言われる。

SQLインジェクションを疑いシングルクォーテーションを入れるとPHPのエラーが表示される。

エラーから読み取るにSQLの実行結果からループで結果を取って表示しようとしてるっぽい。(たしかfetchArray()でエラーがでてた)

とりあえず講義で教わったようにテーブルスキーマを盗めないか試す。

以下の文字列を検索フォームに入れる。

' UNION SELECT null, null, null, null; #

データベースが何かの特定はエラー分からは推測できないのでMySQL, PostgreSQL, SQLiteの可能性を順番に試した結果、MySQLぽかった。

ここでnullの値を変えていくと(確か)4つでページにデータが表示された。

ので次に以下でテーブル一覧を取る。

' UNION SELECT null, table_name, null, null FROM INFORMATION_SCHEMA.COLUMNS; #

これによりsecret_umasugiというテーブルがあることがわかる。

ちなみにtable_nameを2番めにしてる理由は、1番目だと画面に描画されなかったからです。(もしかしたらソースにはあった?)

というわけで以下のテキストで検索してフラグゲット。

' UNION SELECT * FROM secret_umasugi; #

ちなみにたまたまカラム数が一致したので通ったけどもしこれで通らなかったらカラムの名前を調べたりGROUP_CONCAT()あたりで頑張ることになりそう。

Web 300 Easy SQL Injection

ページにアクセスするとLogin ID, Display name, Passwordを入力できる。

また、ログインボタンと登録ボタンが存在する。

とりあえず普通に登録してみるとログインできることがわかる。

問題名が問題名なのでひとまずシングルクオーテーションを入れてみるとDisplay nameのときだけバリデーションエラーのメッセージが微妙に違うことがわかる。

そこでこんなSQLが書かれていると仮定する。

$sql = "INSERT INTO users VALUES ('${loginId}', '${displayName}', '${password}')";

そこでこんな文字列をDisplay nameのフォームに入れて登録を試す。

', 'pass'); --

これで登録が通り、パスワードがパスワードのテキストフォームに入れたものでなく、'pass'になる。(確か)

ちなみにこの時にコメントアウト#にして試せばMySQLでないことがわかるのでSQLitePostgreSQLのどちらかに絞れる。

ここにSQLインジェクションできることはわかったので次にこのDisplay nameにデータベースから抜いた情報を入れられないか試す。

テーブル情報を引き抜くのを講義資料を元にSQLite, PostgreSQL両方試し、結果的にSQLiteだった。

こんな感じ。

'||(SELECT sql FROM SQLITE_MASTER), 'pass'); --

こうしてログインが成功すると最初はDisplay nameに何もでないがもう一回ログインし直すとusersテーブルのスキーマ情報が抜ける。

あとはそれを元にもう一度インジェクションし、ログインし直して情報を抜いてフラグゲット。

ユーザ名をadminにした理由は勘なのでこれが外れたらLIMIT, OFFSET句あたりを使って一行ずつ抜いていくとかになるんですかね。

'||(SELECT password FROM users WHERE loginid='admin'), 'pass'); --

Forensics 100 みつけてみよう

pcapファイルなので中身をWireSharkで開くとHTTP通信を何回かしている。

とはいえ回数多くて全部読むのがめんどくさくてstrings for100.pcap | grep ctf4bしたら1つだけ中身のあるフラグがあった。

Forensics 200 漏洩した情報を特定せよ

この問題が個人的には面白かった。

まずpcapファイルをWiresharkで開き、ざっと見てみる。

特に怪しいものはなかったのでHTTP通信にフィルタするとこんな感じになる。

f:id:sota1235:20170129235815p:plain

通信の流れを見るとクライアントが

  • GET /c2/xor_cipher_key/
  • POST /c2/leak_info/

としてるのがわかる。問題のシナリオを推測すると情報を漏洩させた人は

  • 情報を他社にリークする
  • その際、情報を暗号化して送信した
  • 暗号化の手段はXOR演算

と推測できる。

まずGET /c2/xor_cipher_key/のレスポンスを見るとこんな感じ。

f:id:sota1235:20170130000023p:plain

ffとだけある。これがXOR演算のためのキーだと仮定する。

その後のPOST /c2/leak_info/のリクエストボディを見る。

f:id:sota1235:20170130000111p:plain

���˝��ϊ������̛̛��ύ��̜�����ϑ��というURLエンコードされた値を送信していることがわかる。

先程のシナリオから逆算するとこの値は

  • 情報にffを用いてXOR演算する
  • その値をURLエンコードする

ことによって得られたと仮定できる。

なのでこれを読み解くには逆のことをすればいい。

超適当スクリプトを書いて実行する。

<?php

$data = '���˝��ϊ������̛̛��ύ��̜�����ϑ��';
$bytes = explode('%', $code);

$answer = '';

foreach ($bytes as $b) {
    $num = hexdec($b);
    $const = hexdec('ff');

    $result = $num ^ $const;

    $answer .= '%'.dechex($result);
}

echo $answer;

これで元のデータをURLエンコードした文字列が得られるのであとはこんな感じでコマンドを叩いてフラグゲット!

f:id:sota1235:20170130000601p:plain

なぜかcが抜けてたけど足してSubmitしたら通った。

Binary 100 HiddenFlag

これを終了3分前に焦って解いて、結果的に3位になれた。

3分で解いたという時点でお察しで、こんなコマンド叩いて解きました。。。

strings bin100_1 | grep ctf4b

stringsコマンド便利すぎた。

参加してみて

CTF4Bはすごく前から参加してみたくて、今回予定も合って参加できてよかった。

短い時間の中で講義も丁寧にやってもらって資料も充実していて、演習ではそれが生かせる問題ばかりだった。

とはいえまだまだビギナーの身なので大会か何かあればちょろっと参加してみたい気持ちです。

参加した皆様、お疲れ様でした!