SECCON2017CTF 国内 本戦 - 参加記録

起床フェーズ

negainoido というチームに参加し、予選と本戦に出場してた. 予選はオンラインで人数制限がなく、我々は6人で参加したが、本戦に出場できるのは4人まででどうにかして抽選する必要がある. 我々は、貢献度の重み付き抽選を行って4人を選んだ. 私自身はそんなに大きく貢献したと言えないのだが、選ばれたので出場した.

SECCON 自体は 02/17から02/19 までの3日間あり、その初めの1日目の中のイベントの1つとして、国内本戦がある. (残り二日間はよりレベルの高い、国際戦がある.) 朝の10時前に北千住駅に着き、そこから徒歩5分くらいを掛けて東京電機大学に向かった. チームメンバーはなかなか来なかったので一人で受付を済ませて席で準備をしていた.

SECCON本戦は二年ぶりの二度目だが、前回と同様に、ルーターが机に置いてあるので持参した有線LANでイントラネットに繋いで、スコアサーバ等にアクセスする仕様. あ、でも今回はインターネットにも接続できるようになっていた. チーム内のファイルの共有などを Slack で行った. 前回はインターネットが繋がってなかったので、そこがネックだった.

そういえばコンセントも4つ口が1つ(実は足元に+1)しかないので、電源タップを持ってきておいて正解だった. SECCON運営はこういったアナウンスが弱いと思う. 今回は事前に Slack が立てられて参加者はそこに参加することになっていたが、無料プラン (最近の一万メッセージだけが閲覧できる) なのにプライベートチャンネルでがんがんメッセージを書き込んでるヒトがいて、書き込んだメッセージが次の日には流される状態となっていた. もっとも、食事に関する註意くらいしか、大切なことは書き込まれていなかったけれど.

本戦

1030-1100 は運営による案内があり、1100から本戦が始まった. 問題は4つあり、それぞれ、船橋、府中、幕張、梅田、という名前がついnていた. 地名なのは間違いないが、どういう意味が込められてるのかは謎だった. それぞれの問題はそれぞれが web サービスの形をなしている. 一昨年は各チームが web サービスを運営維持するというルールだったが、今回は、運営が1つだけを運営し、各チームがそこにアタックするという仕組みだった. フラグは2種類あり、webサービスをハックすると取得できる、Attack フラグ. これは各問題について1つか2つかだけあって、ルールにその個数が書いてある. こちらがメイン. もう一つは Defence フラグというものがあり、フラグ自体はチームごとに配布されており、ただし5分したらそのフラグの期限は切れ、新しいものが配布される. このDefenceフラグは各webサービスのどこかに書き込んでおくと、5分ごとに運営がチェックし、点数が入る. こちらは、Attackでの点数に差をつけるために副次的な意味合いが強そう.

船橋

これはwebサービスというか、クイズみたいwebページ. 指紋の写真を1枚と20枚とを表示され、一致する (同一人物の同じ指の指紋) がどれかを当てる、というクイズを10問正解するとAttackフラグが1つ得られ、加えて5問正解するとDefenceフラグを書き込む権利が得られる?? 15問なので気合を入れればどうにかなるかもしれないだろうが、Defence フラグは5分ごとに新しくということは、5分ごとに15問を正解して新しく書き直さないといけないことを意味している.

二人で協力することで、10問を人力で解くことに成功し、Attackフラグは得た. 自動化でかなり苦戦した. 試したのは、次の方法:

  1. 問題セットを大量に仕入れる
  2. 仮定、\(X\) に対して \(Ys\) はランダムに選ばれる. そこにある一枚 \(X'\) が常に含まれる
  3. 問題セットから ある \(X\) について \((X, Ys_1), (X, Ys_2), \ldots\) を選ぶ
  4. 集合の積 \(Ys' \equiv Ys_1 \cap Ys_2 \cap \cdots\) の中に X' が含まれる
  5. 特に \(|Ys'|=1\) なら、\(Ys' = \{X'\}\) である

初め、時間を掛けて問題セットを集め、 \((X, Ys')\) の組で解こうとしていたが、未知の \(X\) ばかりが出現することに気づいた. チームメンバーから、問題のセットは時間ごとに異なる 500 枚が使われているのではないかという指摘を受け、問題セットを一旦空にして、改めて問題セットを集め直すと、20分程度で、500枚の \((X_i, X_i')\) が手に入ってしまった. チームメンバーはそれを元に、Greasemonkeyのスクリプトを書いて、ブラウザ上で自動化した. しかし我々は結局Defenceスコアを手に入れることはできなかった. システムが壊されており、15問に正解した時点での処理 (おそらく、Defenceフラグを書き込めるようにするためのセッションが発行される) でサーバ側のエラーが発生した. また、強引にDefenceフラグを書き込もうとすると (エラーは出たが処理は済んでいると踏んで)、「今のDefenceフラグは何秒保護されている、5回連続でまた15問正解すると、秒数を減らせる」というメッセージが出る. どうもこのシステムにおけるDefenceフラグはただ1つしか同時に存在できないらしく、書き込んだフラグは期限で保護されるらしい. 他のチームが解けば秒数を減らせるが、逆に自分のチームが解くと秒数を増やせるらしい. おそらく、この指紋認証システムの自動化に成功したチームはほとんど無かった. 我々1チームだけでは到底減らせない秒数に膨れ上がっていた.

梅田

InSECtagram という Instagram のような web サービス.

問題のルールに、 /most-liked がフラグページであることが書いてある. このページのタイトルが1つ目のAttackフラグだった. Defenceフラグはこのページのコメントに書き込めばよい. ただしこのページにコメント欄がないので、指してる画像ページに一旦行ってから、書き込めばよい.

コメントを書き込むとか、あるいはそもそもスコアサーバから Defence フラグを取得するとかいうのを私は puppeteer で行った、が、安定性がなくて辛かった. ページ遷移の後に十分な sleep を挟まないといけない. sleep が足りないと嫌なエラーが出る. そして十分は sleep というのは1秒とかするので、結果としてかなり遅い. 最後の方は、一回の書き込みに2秒程度かかるプログラムを8個程度並列で動かしてごまかしたが、他チームの書き込み速度に全く追いついていなかった.

梅田はやることがはっきりしているので、早い段階からDefenceで稼げた. アカウントを作成してlikeするというプログラムも作って /most-liked の参照先を動かして他チームを晦ますといった手法 (参照先を決め打ちしてコメントしているチームもいた) も、最初の方は通用した.