KDL BLOG

SECCON 2017国際決勝大会 参加レポート(前編)

はじめまして、入社して数ヶ月な新入社員のセキュリティソリューション事業部の馬場です。

この度、2018年2月18日~19日に開催された「SECCON 2017 国際決勝大会」というハッキング技術を競い合うコンテストにチーム「binja(ビンジャ)」の一員として参加しました。この2日間、一体どのような戦いを繰り広げたかをご紹介します。

seccon2017_01.png

ハッキング技術で旗取り競争する競技、CTF(Capture The Flag)

SECCONで行われた競技はいわゆるCTF(Capture The Flag)というもので、直訳すると「旗取り合戦」です。情報セキュリティの分野においてFlag(旗)は「情報」を意味し、与えられたサーバやファイルなどに隠された「情報」をハッキングの技術を用いていかに奪取するかを競います

決勝大会で主に行われたのはCTF競技の中でも「King of the Hill」と呼ばれる形式の競技で、ただサーバなどからFlagを奪取するだけではなく、そのサーバに対して脆弱性などを利用して所定の場所に自分たちのチームのFlagを書き込むことでも得点になり、また他のチームが行おうとするFlagの書き込みを妨害する(丘の頂を目指し、自らの一位のために他者を蹴落とす)いわゆる攻防戦スタイルです。SECCONではFlagの奪取で得られる得点をAttack Points、Flagの書き込みはDefense Pointsと定義し、前者は一律100pt、後者は5分毎に20ptで複数のチームがFlagの書き込みに成功した場合は仲良く山分け、となります。

問題構成

問題ページは全部で6つあり、問題名はそれぞれ「壱」から「六」の大字が割り当てられています。その内の「壱」から「伍」がKing of the Hill形式で、「六」はDefense Pointsが設けられていない問題が5問配布されていました。問題概要は次の通りです。

seccon2017_02.png

プログラミング言語「Brainf*ck」に独自の拡張が加えられた言語を実行できるオンラインインタプリタサービス。より短く「Hello, World!」を出力するコードを書いたチームがDefense Pointsを得られます。いわゆるコードゴルフですね。

自明なスタックベースのバッファオーバーフロー脆弱性があるARM、MIPS、AArch64バイナリが、改変されたqemu上でそれぞれ動作しているサービス。その脆弱性を用いてサーバ上の所定のファイルを読み書きすることで、Attack PointsとDefense Pointsを得られます。いわゆるマルチアーキテクチャのエクスプロイトチャレンジでSECCONの定番問題です。

ビンゴゲームサービスが稼働しているRaspberry PiとそこにSSH接続するためのアカウントを与えられました。そのビンゴゲームに定期的にアクセスしてくるボットに対し、より早いレスポンスを返したチームがDefense Pointsを得られます。いわゆるISUCONですね。

IPアドレスの一覧を与えられ、そこに適当なポートで接続するとそのポートに対応した文字が返ってき、更にその文字がサーバ上の所定のファイルに書き込まれるという謎サービス。そのファイルに自チームのFlagを書き込むことによってDefense Pointsを得られます。

ハングル(EUC-KRで定義されている文字)で構成された機械語を実行できるサービス。サーバ上の所定のファイルを読み書きするコードを書くことでAttack PointsとDefense Pointsを得られます。

Web、pwn、forensics、BadUSBと多種多様なジャンルの問題が、予選と同様な形式で出題されました。これらはAttack PointsのみでDefense Pointsは設けられていませんでした。

個人的に面白かった 、波乱万丈の「壱」

ということで、今回は個人的に面白いと感じた問題「壱」について解説します。まず問題ページにはサービスのWebインターフェースのURLと動作環境の情報が記載されており、またインタプリタの実行ファイルはダウンロードできる状態です。WebインターフェースのフォームにBrainf*ckのコードをサブミットすることで、サーバ上でそのコードが実行されて結果が出力され、合わせて自分たちのチームのFlagと「Hello, World!」を出力するコードをサブミットすることで「Code Golf Ranking」に掲載されます。そのランキングで1位になったチームがDefense Pointsを得られるという感じです。

seccon2017_03.png

Attack Pointsについては全部で4つあり、1つ目のFlagは単に「Hello, World!」を出力するコードを実行すると貰えます。ここでは短いコードを書く必要はなく、サービス問題ですね。

2つ目のFlagは配布されているインタプリタの実行ファイルに平文でそのまま埋め込まれており、stringsコマンドなどで普通に取り出せます。ということで、こちらもサービス問題ですね。

さて、3つ目のFlagからは先の2つと違って少し工夫が必要になっています。まずインタプリタをIDAなどの逆アセンブラで解析していくと、入力したBrainf*ckコードが「」の際に「/attack3.txt」というファイルを読み込み、現在のBrainf*ckポインタが格納されている [rbx+100020h]の値とコード実行前のBrainf*ckポインタが格納されているrbpレジスタの値の差を取り、その分をlseekしてから1バイトだけreadする処理が存在することがわかります。

seccon2017_04.png

attack3.txt」というファイル名からして3つ目のFlagが入っていそうですね。ということで、ポインタを進めながらattack3.txtの読み込み処理をさせて出力するコードを実行することで、3つ目のFlagを得られます。(ちなみに、競技中はバイナリ解析が得意なメンバーが解きました☆(ゝω・)v)

ところでこのインタプリタですが、作問者の方がソースコードなどを公開されていますのでそちらもご参考ください。
https://github.com/shiracamus/seccon2017/tree/master/final_international/tower_1_brainhack

最後の4つ目のFlagですが、main関数の最初の方を見ると「YXR0YWNrNC50eHQ=」というファイルを読み込んでいる処理があり、またファイル名がbase64でエンコードされた文字列であることが自明なのでとりあえずデコードしてみると「attack4.txt」という文字列になりました。

4つ目のFlagが入っていそうですね。

seccon2017_05.png

このファイルは先のattack3.txtの読み込み処理と違って一気に256バイトでreadされており、ポインタをそこまで移動させて出力すればFlagを得られそうです。

ところが、Brainf*ckコードのポインタデクリメントはコード実行前のBrainf*ckポインタが格納されているrbpレジスタの値より前にデクリメントできないよう制限されており、また「YXR0YWNrNC50eHQ=」のread先はそのポインタのアドレスよりも前になっていて普通のコードでは参照できないようになっています。

seccon2017_06.png

そこで普通のBrainf*ckには存在しない拡張されたコードの処理を見ると、そこには何の制限もなくポインタのインクリメントとデクリメントが可能な「{」と「}」という構文を確認できます。

seccon2017_07.png

これを用いることで、本来アクセスできない領域に格納されているFlagのアドレスまでポインタを持っていき、それを出力することで4つ目のFlagを得られます。(例によって、競技中はバイナリ解析などが得意なメンバーが解きました☆(ゝω・)v)

まだまだ解説は続きます・・・ということで続きは後編へどうぞ!

◎後編:SECCON 2017国際決勝大会 参加レポート(後編)