ox0xo infosec tutorial

SECCON CTF4B 2022 writeup

2022-06-05
CTF

2022-06-05に開催されたSECCON CTF for Beginners 2022に参加しました. 今回はじめてチームでの参加で 822 point の 94 位でした. 運営の方によれば昨年よりも易化傾向という事ですが私にとっては十分歯ごたえがありました. 私が担当した問題の Writeup を記録しておきます.

Web

Util

IPアドレスを渡すと裏で /bin/sh が ping を実行し, その結果を表示する Web サービスがある. Dockerfile によると /flag_{16桁ランダム英数}.txt が存在するので cat /flag* を実行出来れば良い. ただしクライアントサイドで javascript が入力をチェックしており IP アドレスの書式に合わないコマンドは渡せない. そこで javascript の入力チェックをバイパスするために HTTP リクエストを直接送信すればフラグが手に入る. 今回は Fiddler を使用した.

ドロップダウンから拡張子を選択すると対応するファイル一覧が返されて, それをクリックするとファイルを閲覧できる Web サービスがある. 拡張子はクエリストリングの file_extension を介して渡されるので, ドロップダウンに存在しない拡張子を指定できる. ソースコードを読むと拡張子が flag である入力をフィルタしているので, これを渡せば手がかりが得られそうである.

fileExtension := strings.ReplaceAll(r.URL.Query().Get("file_extension"), ".", "")
fileExtension = strings.ReplaceAll(fileExtension, "flag", "")

つまり file_extension から . と flag を除外した後に flag という文字が残れば良い. たとえば fflaglag のような文字列が該当する. これで一覧に flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf が表示される.

Web ブラウザからこの pdf を閲覧すると一面 ? で埋め尽くされたテキストが返される. Content-Length ヘッダによるとこのファイルのサイズは 16,085 バイトである. ソースコードによると 10240 バイトより大きいファイルは ? で上書きされてしまうから, ファイルを分割してダウンロードする必要がある.

一部の Web サーバに備わっている Range リクエストによってこれを実現する. 0-10239 バイト部分と 10240-16085 バイト部分を分割してダウンロードし, copy コマンドで結合すれば回答フラグが入手できる.

serial

ユーザー認証機能を持つ ToDo 管理帳のような Web サービスがある. 2_init.sql を読むと flags テーブルに回答が入っているが, このテーブルはどこからも参照されていないので SQLi でリークする必要がある.

SQLi に繋がる脆弱性を探して database.php を読むと次のように誘導がある. このメソッドは各画面でユーザー認証をするため user.php の login() から呼び出されており, さらに login() は todo_update.php で使用されている. todo_update.php は ToDo を完了する時に呼び出されるので, これを攻撃面にして SQL を調整していく.

/**
 * findUserByName finds a user from database by given userId.
 * 
 * @deprecated this function might be vulnerable to SQL injection. DO NOT USE THIS FUNCTION.
 */
public function findUserByName($user = null)
{
    if (!isset($user->name)) {
        throw new Exception('invalid user name: ' . $user->user);
    }
    $sql = "SELECT id, name, password_hash FROM users WHERE name = '" . $user->name . "' LIMIT 1";
    $result = $this->_con->query($sql);

たとえば次のような SQL が有効である. user.php を読めば分かる通り passwod_hash はユーザー認証のため必要になるので name を上書きする.

SELECT id, name, password_hash FROM users WHERE name = '存在しないユーザー名' UNION SELECT 1, body, 3 FROM flag WHERE '1'='1' LIMIT 1;

この SQL を実行するためには 存在しないユーザー名' UNION SELECT 1, body, 3 FROM flags WHERE '1'='1$user->name に渡す必要がある. 外部入力を $user に渡す機会はあるだろうか.

$user はログインしているユーザーの認証に利用されており, シリアライズされた状態で __CRED クッキーにセットされている. todo_update.php はこれをデシリアライズしてユーザー認証することで, 別人の ToDo を変更してしまわない仕組みになっている. この仕組みを悪用する.

__CRED を Base64 デコードして次のような $user を入手し

O:4:"User":3:{s:2:"id";s:4:"1291";s:4:"name";s:1:"s";s:13:"password_hash";s:60:"$2y$10$Vq3hlN0dOmWpH3I1zcLKbOR./6Q8nLOHxPx8cH94zcnEDwNq5rLCC";}

name を SQL で上書きする


O:4:"User":3:{s:2:"id";s:4:"1291";s:4:"name";s:59:"i17cAd0hh9' UNION SELECT 1, body, 3 FROM flags WHERE '1'='1";s:13:"password_hash";s:60:"$2y$10$Vq3hlN0dOmWpH3I1zcLKbOR./6Q8nLOHxPx8cH94zcnEDwNq5rLCC";}

このクッキーをセットした状態で todo_update.php を呼び出せばフラグが手に入る.

Misc

phisher

渡された文字列を画像に変換し, OCR を利用して再び文字列に変換するプログラムがある. OCR に www.example.com という文字を認識させればフラグが手に入るが, 入力文字列に www.example.com が渡されるとブロックされるのでホモグラフを利用する.

以下の Web サイトで適当な文字を検索した. https://www.irongeek.com/homoglyph-attack-generator.php

H2

簡単な Web サーバのソースコードと pcap が渡される. この Web サーバは x-flag ヘッダがセットされたリクエストを受け取った時に特別な挙動を示すようになっている. pcap を読むと大量のリクエストとレスポンスが含まれており, この Web サーバへのアクセスをキャプチャしたものだと推察できる. そこで x-flag がセットされたパケットを探せばフラグが手に入る.

Wireshark を使えば http2.header.name == "x-flag" フィルタで見つけられる.

hitchhike4b

python の help をオンラインで提供するサーバがある. たとえば help(print) などと入力すれば python の print メソッドに関する説明が表示される. ここでヒントとして __main__ スコープにフラグが存在する事を示唆するコードが表示されるので help(__main__)をリクエストすればフラグが手に入る.

雑感

Revers は初めから別担当に任せていたので良いんですが, Crypto と Pwn は挑戦したけれど解けなかったので力不足を感じます. 過去ログを振り返ると 2 年前の CTF4B の時も同じことを言っていたので進歩がない.

ただ, Crypto の primeperty は方針まで辿り着いていて, その後ゴリゴリ計算するところに時間を使えなかった(それよりも点を取れそうな問題をやりたい)ので, 時間の使い方が上手ければ解けていたかもしれません. 現状のスキルでは得点効率が Crypto < 他カテゴリ なので, 他の簡単な問題をスピーディーに解けるようになるのが先決. その上で Crypto の練習が必要です.

あと衝撃的な事実として, Crypto を解けるようになりたくて数学をやり始めて4年目ですが, その効果はほとんど感じられませんでした. これは手を動かしてきた時間が圧倒的に少ないからだと思います. 本気でやるなら RSA の基本問題などを沢山解かないと本来の目的を果たせません.


Similar Posts

Content