SECCON CTF 2014 Finals に参加した

closeこれは 2 年 10 ヶ月 3 日 前に投稿されたものです。最新のものではありませんので、間違っているかも知れません。

dodododoでした。
懇親会を途中で抜け出して空港に行ったら欠航で翌日帰宅になってしまったり、試験期間真っ只中・研究中間発表準備などがあったり、風邪を引いたせいで、艦これもスクストも何もやっておらず、おちこんだりもしたけれど、私は元気です。ちなみに、欠航分の宿泊費も出してもらえるそうです。JNSAは神。

以下、Writeupと、ネットワーク環境についてです。

2

昨年の「Pisa」のような問題です。FuelPHPで作成されたようです。

q2

「掲示板(CAPTCHA付き)」があり、「5分間の投稿数が多いIPアドレス上位10件」および「その日(問題サーバが停止するまで?)の投稿数が多いIPアドレス上位10件」が確認できるようになっています。投稿(10件分)や、各ランキングについてはJSONのAPIがあり、Ajaxで呼ばれていました。

また、名推理により、「AP(攻撃ポイント)」・「DP(防御ポイント)」について、以下のことが予想されました。

  • 5分間に最も多く投稿するとFlagが表示される(APIの出力結果に「{"key":""}」が見えるため)
  • その日に最も多く投稿するとFlagが表示される(同上)
  • チームフラグを投稿するだけでDPが入る

なお、APは、問題サーバに対する何らかの操作により得られる「SECCON{...}」というFlagをスコアサーバへ送信すれば、100pt得られます。問題によってフラグの数は異なり、この問題の場合は、2個でした。

また、DPは、スコアサーバから示される、各チーム独立・各問題共通の「チームフラグ/チームキーワード」を、予め示された問題サーバの特定のURLで(スコアサーバが?)参照できるようにすれば、5分ごとに20ptが加算されます。複数の問題サーバから参照可能にすれば、その数だけ加算されまくられます。ただし、20ptというのは、1つの問題サーバに対するもので、複数のチームのフラグが参照可能であれば、そのチームで山分けさまれます。

この予想は、その通りだったのですが、フラグが表示されるのは、投稿を行った(IPアドレスを持つ)PCで、「5分間ランキング」「(全期間)ランキング」のページ、またはそのAPIへアクセスした際のみでした。最初の頃に、DPを稼いでいたチームは、ランキングが1位にも関わらず、APが入っていませんでした。そこで、そのチームの投稿IPアドレスの末尾を見ると、「.254」…あっ…(察し)。

DPを得るための「特定のURLから参照できるようにする」のが投稿で、投稿は10件分しか入らないので、他チームのフラグを追い出すため、10件分埋め尽くすと良さそうです。また、ランキングで1位になれば、フラグが得られます。よって、とにかく(出来ればチームフラグを)投稿しまくれば良さそうです。

CAPTCHAの回避

「Pisa」はよく知りませんが、昨年はCAPTCHAの回避が可能であったそうです。

掲示板への投稿を行うためのJavaScriptでの処理の流れは以下のようになっていました。

  1. (ユーザが)ページをダウンロードしてくる。この際、Cookieに「cap_token」「token」がセットされる。
  2. CAPTCHA画像用imgタグのsrcを「/image?(現Unixtime)」にセットし取得させる。
  3. (ユーザが)投稿ボタンを押す。
  4. 名前・本文を取得し、CAPTCHAの答えとして、パズル型のCAPTCHAはD&D後の座標、通常のCAPTCHAは文字列を取得。
  5. 投稿用APIへPOST。
  6. 成否を表示。なお、短時間で何度もCAPTCHAを間違うと一定期間API側で投稿が拒否される。

真面目にCAPTCHAに答えた上でcurlなどで試す際、横着してcap_tokenもtokenもずっと同じまま試していたところ、5.」を何度でも繰り返すことができる、ということも分かりました。しかし、その後の操作を誤ったのか何なのか、しばらくすると不可になってしまいました。

このことから、

  • cap_token/token を固定しっぱなしにすると良い…かも知れない
  • さらに、CAPTCHAには有効期限がある…かも知れない

ということになります。どちらが効いているのか、またどちらも効いているのかは、ちゃんと調べていないので不明ですが、競技中は「/image?1145141919810893」などとしたCAPTCHAを用い、連投を行いました。

幸い、このときのCAPTCHAが「511 % 500」「765 + 346」など答えが数字となるタイプで良かったですが、パズル型だと困っていたかも知れません。

チームフラグの自動取得

昨年の0x0の方のSECCON 2013 全国大会 Write up - ソースコード置き場によると、チームフラグはSocket.io経由で更新されるそうです。

某氏の手により、このチームフラグを自動取得するスクリプトが用意されていましたが、スコアサーバ側のSocket.ioのバージョンが古く(0.9.x系だったと思います)、上手く動作しなかったそうです。そこで、私も以下のようなスクリプトを用意し、socket.io-clientのバージョンを下げて、対応しました。

これで、「python -m SimpleHTTPServer」などすれば、HTTP経由で見れるというめちゃくちゃな対応です。これだと、最悪の場合、起動から5分経たないとチームフラグが取れないのですが、「flagword」メッセージ以外でも、チームフラグが取れる(connectあたり?)ので、来年出ることがあれば、もう少しちゃんとします。

Socket.ioのバージョンが古い…というのは、ただ単に更新をサボっているだけかも知れませんが、仕様が大きく変わったSocket.io@1.xへの、特に他言語向けクライアントでの対応が追いついていないことへの配慮かも知れませんね。

ともあれ、「CAPTCHAの回避」「チームフラグの自動取得」により、チームフラグを含んだ書き込みを投稿しまくれることになりました。私の作ったシェルスクリプトでは、頑張っていっぱいプロセスを立ち上げてもせいぜい1000[投稿/5min]程度でしたが、シェルスクリプト+Rubyで並列化の魔改造された結果、10000[投稿/5min]近くまで行っていました。この「(APと)DPを得るための攻撃」は、2日目後半ともなると、他チームとも重なって、サーバが死んでいるような感じだったそうです。ひどい。

5

DPを得るための「特定のページ」であり、何らかの内容が表示された「script/index.cgi」だけが、なぜかiframeで貼られたページが問題です。

q5

与えられたドメインを正引きすると、「xxx.yyy.5.2」となっていました。他の問題の場合は、「xxx.yyy.(問題番号).1」です。早速、そのネットワーク全体をnmapでpingスキャンすると、上記サーバに加え、以下のサーバが応答しました。

  • xxx.yyy.5.102
  • xxx.yyy.5.202
  • xxx.yyy.5.252

なお、これらのサーバに、HTTPでアクセスしたところ、全て「It works!」だったので、「-P0 -p 80」も試しましたが、これ以外には発見できませんでした。

その後、某氏によるツールで、「http://xxx.yyy.5.252/key.txt」が発見されました。この内容が、1つ目のフラグです。一応、「xxx.yyy.5.2」にもありますが、ここじゃない的なメッセージが出ます。記憶違いでなければ、全チーム中、一番早かったと思います。

しかし、ここからが大変で、これ以外にフラグは取れず、DPも取れませんでした。以下、試したこと。

ポートスキャン

早速、TCPでのポートスキャンを行いましたが、全サーバで結果は「すべてOpen」です。SYN+ACKが返ります。SYN+FINで送ったりしてみましたが、結果は同じでした。

問題サーバと同じネットワークでないと正しいTCPフラグを返さないのかと思い、アイドルスキャン(PSPを利用したIdle Scan - もりたこの日記家庭用プリンタがポートスキャンの踏み台になった話 - sonickun.log)を試みるもフラグメントIDが不規則に変化するため、無理でした。

そのくせ、(本当に開いているポート以外に)何かデータを送信すると、すぐにソケットを閉じられます。このことを利用して、スクリプトを組んでみましたが、組み方が悪いのか効果はありませんでした。

しかし、Xmasスキャンを行うと、22やら80やらあたりが開いているという結果と共に、サーバによっては、NFSやX11のクライアント側ポートも開いているらしいという結果が返ってきました。

また、時間をかけ、UDPスキャンも行いました。すると、rpcbindと、サーバにもよりますが、NFS用のポートが開いているという結果が返ってきました。

niktoによるスキャン

niktoが役立ちそう(Computer Security, CTF and ... — SECCON 2013 全国大会 Write Up0x75: SECCON 2013 CTF 全国大会 write up [Hanoi])なので、使います。

しかし、特に面白いものはありませんでした。過去のCTF?では、nikto避けのためにUserAgentを見るというのがあったらしい(Kioptrix Hacking Challenge: Part 5 - techorganic.com)ので、それに倣い、UserAgentを変更しても変化なし。

なお、

Nikto2でスキャンをしたところmod_negotiationに脆弱性がありそうだとわかる
(SECCON 2014 全国大会に出た - misodengakuのブログ)

ち~ん(笑)。
Apacheのバージョンについては、なんか古いなとは思っていましたが、そんな結果が出ているとは…。見落としか…悲しいなぁ…。

NFSまわり

スキャンの結果、rpcbindやらNFSがが動いているようなので、調べました。rpcinfoやら、NSEやらで調べると、102/202で、本当に動いているようなので、マウントします。

NFSv3でマウントを試しましたが、権限不足でした。ありがとうございました。

その他

SNMPを試したり、何回かスキャン結果に「iPhone-sync」が出てきたため、会場内のSSID「SECCON」というOpenな、他参加者のハニーポット用?かも知れない怪しいAP(≠攻撃ポイント)に繋いでみたりしてみましたが、無理でした。

なお、

二つ目以降のフラグが手に入らなかったのですが,どうやらこの問題はWebの問題ではなくて,TCP/IPの問題だったそうで,不正なIPヘッダのダミーのパケットが返って来るために通信できないポートがあったそうな.そのダミーパケットをうまく選別して,iptablesでDROPさせればつながるポートがあるらしい.
(SECCON CTF 2014 決勝戦 参加記 « chibiegg日誌)

だそうです。RSTフラグの付いたパケットを破棄させた上で、「nmap -sV」とかすれば良かったのかな。

ネットワーク環境について

今回のSECCONでは、インターネット回線の提供がありました。「独立したネットワークで提供」とあったので、机の上に「競技ネットワーク」「インターネット」の2つの口があるのかと思っていたら、口は1つでした。インターネットは、認証なしのSquidProxy(HTTP/HTTPS)による提供で、非常に役立ちました。

また、昨年に引き続き、今回も、チーム内とチーム外の通信をスイッチでミラーリングし、キャプチャしていました。相変わらず、RaspberryPi(1/Aですら)に勝てるか微妙な性能のPCを用いているため、抜けがあるかも知れませんが、1日目はこんな感じです。

$ capinfos day1.pcap
File name:           day1.pcap
File type:           Wireshark/tcpdump/... - pcap
File encapsulation:  Ethernet
Packet size limit:   file hdr: 65535 bytes
Number of packets:   4912 k
File size:           1064 MB
Data size:           985 MB
Capture duration:    22994 seconds
Start time:          Sat Feb 07 04:24:00 2015
End time:            Sat Feb 07 10:47:14 2015
Data byte rate:      42 kBps
Data bit rate:       343 kbps
Average packet size: 200.70 bytes
Average packet rate: 213 packets/sec
SHA1:                778a1c88d0a0565f275bc35df7da7721c2fb0d8d
RIPEMD160:           e157e8fd3d42927f0198b84239c932a305635b93
MD5:                 1b84065434425fe2fbe09b61a9624b1d
Strict time order:   False

「80MBのファイルを4人がダウンロード」した昨年との比較でも、2倍のトラフィックがありました。Proxyサーバとの通信もキャプチャした(されてしまった)こと、「2」の掲示板への投稿が要因として考えられます。また、以下は、この日の、問題ごとと、スコアサーバとの通信を切り出した結果です。

$ ls -lh
合計 752M
-rw-r--r-- 1 test test  26M 2月  10 14:58 q1.pcap
-rw-r--r-- 1 test test 277M 2月  10 15:04 q2.pcap
-rw-r--r-- 1 test test 231K 2月  10 15:10 q3.pcap
-rw-r--r-- 1 test test 309K 2月  10 15:18 q4.pcap
-rw-r--r-- 1 test test 199M 2月  10 15:24 q5.pcap
-rw-r--r-- 1 test test 1.8M 2月  10 15:31 q6.pcap
-rw-r--r-- 1 test test 250M 2月  10 15:39 score.pcap

「5」、スコアサーバの通信も結構あるじゃねぇかという感じです。なお、以下が2日目です。

$ capinfos day2.pcap
File name:           day2.pcap
File type:           Wireshark/tcpdump/... - pcap
File encapsulation:  Ethernet
Packet size limit:   file hdr: 65535 bytes
Number of packets:   5403 k
File size:           1466 MB
Data size:           1380 MB
Capture duration:    18263 seconds
Start time:          Sun Feb 08 00:12:02 2015
End time:            Sun Feb 08 05:16:25 2015
Data byte rate:      75 kBps
Data bit rate:       604 kbps
Average packet size: 255.40 bytes
Average packet rate: 295 packets/sec
SHA1:                c04c30e80a9f63061ec76c4a2be95a57e0babc93
RIPEMD160:           be743fb836c885d30109ea8d1d73a36689acc121
MD5:                 c5e2e1fd388178e4f9fdd70e03a45e71
Strict time order:   False
$ ls -lh
合計 936M
-rw-r--r-- 1 test test 4.2M 2月  10 22:39 q1.pcap
-rw-r--r-- 1 test test 756M 2月  10 22:59 q2.pcap
-rw-r--r-- 1 test test 4.0M 2月  11 13:48 q3.pcap
-rw-r--r-- 1 test test 382K 2月  11 14:07 q4.pcap
-rw-r--r-- 1 test test  80M 2月  11 14:25 q5.pcap
-rw-r--r-- 1 test test 812K 2月  11 14:44 q6.pcap
-rw-r--r-- 1 test test  92M 2月  11 15:03 score.pcap

投稿するだけで700MBを越える「q2」。

おまけ

全パケットを見て、「SECCON{...}」が含まれたらどこかに通知するシステムを作ったらどうか?と言われたので、以下のようなものを動かしていました。

そのうち、きちんと整えた上で、公開する気でいますが、Socket.ioなどを経由し、以下のように通知します。

snode-1
snode-2

チーム外から接続があると、BAN画面になります。しかし、接続はありませんでした。なお、2日目から持ち込みのシグナルタワーを経由しての通知も行いました。これにより、いちいちブラウザを確認せずとも、すぐに気付くことができましたが、新たなフラグはなく、効果は無かった模様。

本当は、MIDIメッセージを受け取れるように改造したシグナルタワーを持って行き、運営側で使っているブザーの音を以下のように模倣したしたかった(NHL-3FB1-RYGは高いから…)のですが、MIDIファイルの作成が間に合わず、通常版を持って行ってしまいました。

一応、MIDIファイルも置いておきます。

seccon.mid

本来は、1800Hzで鳴らしているようですが、その周波数に一致するMIDIノート番号が無いため、1865Hz(ノート番号94)で鳴らしています。そのため、少し音が高いような気がします。

おまけのおまけ。

このシグナルタワーについては、
KNCT-KPC/thinbook
で、たぶん恐らく可能であればもしかすると、4月ぐらい発刊予定の第1号で書きます。

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>