あーさーの備忘録

ゆっくり自由に生きてます

SECCON Beginners 2019 東京 Write-Up

熱が冷める前に書いたので文章が煩雑かもしれません。ご容赦ください。

2019/10/5(土)に行われたSECCON Beginners 2019 東京に参加してきました。

内容としてはWebとリバースエンジニアリングに関する講義を受けて、その後演習としてミニCTF大会が行われるというものでした。この記事はこのイベントの体験記になります。

先に結論を話すと、参加者のレベル幅が広いな、という感想です。1位の人とか絶対ビギナーじゃないでしょ。参加者の現状のスキルによって、本イベントに対する目線がかなり変わってくると思うので、先に私の個人情報について書いておきます。

私のスペック

前準備

Kali Linuxvmを導入するよう案内があったので、virtualboxを利用して入れました。ところが、僕のMacBook Air 2018にはスペック的に若干厳しかったみたいです。アプリケーション一覧のアニメーションが上手く動作せず、描画が重なってしまいます。軽量化のためにいろいろ試したんですが、当日寝坊しては本末転倒なので断念。

f:id:arthur_teleneco:20191005232954p:plain

f:id:arthur_teleneco:20191005233002p:plain

講義

Web

XSSに焦点を絞っていたのは良かったと感じました。Webがどのような仕組みと決まりによって閲覧できるのか、という基本知識があれば十分理解できる分量だったと思います。最近はCSP(Content-Security-Policy)関連の問題がよく出ているというお話も聞けました。Web系の常設CTFは古いものも一定数あり、比較的新しい仕様が登場しないこともあるので、勉強は怠れませんね。

個人的に一番「なるほど」と感じたのは、「攻撃対象となるユーザをいかに誘導するか」が重要、という話です。XSSできるから危ない!脆弱性がある!という短絡的な思考ではダメだな、と反省しました。ここが崩れると何のためにCTFしているかわからなくなります。

この部分に非常に感銘を受けただけに、気になったことが1つだけあります。XSS悪用の流れの図が分かりにくかったです。XSSを起こす部分と、XSSによって作った落とし穴にどう誘導するかの部分で分ける、とか、なんか上手い方法があるのでは、と素人ながら思っています。

リバースエンジニアリング

講義資料は圧巻の181ページ。ページ数が多いため、超特急で進むのでは、と不安でしたが、講義資料をゆっくり見ながらであれば、講義の内容に追いつけるスピードでした。アセンブリの命令の説明など、リファレンスのような形で使える部分が多かったのでページが多かったんですね。個人的には嬉しいです。大事にします。

大事だな、と思った内容は、リバースエンジニアリングに3つのレイヤーがあるということです。stringsコマンドなどで手軽に行う表層解析、逆アセンブラしたコードを読み解く静的解析、実際に動かしながらレジスタの値などの挙動を見る動的解析の3つです。今までなんとなく手探りでやっていたのですが、作業の見通しがはっきりしました。

少し話が飛びますが、アセンブリ言語はやっぱり人間には読みづらいと思います。大学の某講義のTAが「アセンブリは単純!十分読める!」と言っていましたがそんなことないと思います。各命令が省略されているだけで結構ダメです。lea ならload effective addressとか、覚えるのにはまだまだ時間がかかりそう。レジスタ名も普通に分かりにくい。

そこを少しでも解消するために、今回の講義ではIDAというツールを使用しました。分岐がGUIで見えるようになっているのは良いですね。デフォルトでつけられた変数名も自由に変えられるのには感動しました。

演習

ここからが本当の意味でのWrite-upですね。演習の結果は1400ptで8位でした。3位までに入ると賞品がもらえるとのことで、張り切っていましたが入賞ならず。残念です。

f:id:arthur_teleneco:20191005233235p:plain

(上の写真は最終段階ではありません。この後rev2aも解けました。)

解放メモを、だいたい解いた順に載せていきます。が、問題にもうアクセスできない状態で書いているので結構うろ覚えです。ごめんなさい。

welcome [Misc, 100pt]

実は「てけいさんビギナーズ」から解こうと思ったのですが、問題へのリンクが見つからず、スコアサーバーのHTMLを眺めていました。そのときにたまたま見つけたのがチュートリアル問題のflagです。

ビギナーズカンパニー [Web, 200pt]

XSS脆弱性があったので、scriptを埋め込みrequestbinに誘導。リクエストのcookieにflagがある、という講義通りのシンプルな問題でした。

alertme [Web, 100pt]

タイトル通りですね。適当にalert文書いて埋め込んだらflagのalertに置き換わっていました。これどういう仕組みだったのか見ておけばよかった。

この問題を解いたタイミングでは2位だったみたいです。

Can you still do XSS? [Web, 300pt]

Webの講義では時間が足りずCSP関連の演習ができませんでした。この問題はその演習問題ほぼそのまま、という感じでした。Content-Security-Policyselfが設定されており、単純にscriptタグを埋め込んでも動作しません。以下の流れで解きました。

  1. requestbinにリクエストを投げるJavaScriptのコードで記事を作成
  2. 1.の記事のraw textをscriptタグで読み込むような記事を作成
  3. 2.の記事に巡回者がアクセスするとrequestbinにflagが届く(cookie)

実際のサービスでわざわざraw textとして表示する機能はなさそうですが、テキストファイルとしてpublicな場所に保存してしまっていた、などの事例はあるかもしれません。

てけいさんビギナーズ [Misc, 100pt]

見覚えがあるタイトルなのはさておき。ページを開くと、足し算の式と、答えを入れるフォームが。正しい答えを150回入れるとflagが手に入るようです。数弱の私は当然自動化します。

私のChromeにはTampermonkeyを導入しているので、好きなページで自分が書いたJavaScriptを実行することができます。以下のスクリプトを実行するようにしました。

(function() {
    function safeEval(val) {
        return Function('"use strict";return ('+val+')')();
    }
    if (document.getElementsByTagName('h3')[0].textContent == '現在の正解回数 : 150') return false;
    var siki = document.getElementsByClassName('a')[0].parentElement.textContent;
    document.forms[0].answer.value = safeEval(siki);
    document.forms[0].submit();
})();

演算対象の2つの整数の要素には.a .bとclassで名前がついていました。最初は足し算しか出てこないと思っていたので、この2つの要素のinnerTextを取得し足し合わせていたのですが、途中から引き算に……。しかも演算子の部分は独立した要素ではなかったので、取り出すのが結構面倒。そこでこのような形に落ち着きました。作問者結構いじわるですね。

この問題は「てけいさん」で解くことも可能です。もしそれを防ぐなら、一定時間内に送信しないとアウト、という実装を作問者がすればよいのです。でも、そうしないということは、「てけいさん」も意味のない行為ではない、ということだと思います。1位の人も手計算で頑張っていたようですからね。

restricted ビギナーズカンパニー [Web, 200pt]

考えすぎて全然解けなかった問題。「ビギナーズカンパニー」と見た目は同じですが、scriptという文字が入っていると弾かれてしまいます。

解法としては、imgタグのonerror属性を利用することで突破可能です。

最初は昔みつけた( https://arthur.hateblo.jp/entry/2018/05/27/185550 ) meta refreshを使ってやろうとしましたが、cookieにあるflagが見れませんでした。他にも、同じ内容で違うactionのフォーム要素を埋め込んだりなど、色々模索して失敗していた気がします。

rev1a [Reversing, 100pt]

バイナリファイルが渡されたので、とりあえずfileコマンドとstringsコマンドを使います。今回の趣旨的にはfileコマンドはいらなかったかもしれませんが。stringsからflagの断片を得たので連結しましたが上手く行かず。IDAも使って眺めていたら、delimを挟んで連結していることが分かりました。中身は_だったので、これでつないでflagを得ました。

rev1b [Reversing, 150pt]

こちらもstringsでflagの断片が出てきました。意味が通るように断片を並び替えたら通っちゃいました。

rev2a [Reversing, 150pt]

2とあってさすがにstringsで分かるような問題ではありません。IDAで静的解析。

input_codecheck_codeという、イカニモな関数を発見。check_codeの中身を見ると、入力した数字と、16進数の6AAC52E...を比較して、等しかったらCorrect!と出るようです。そこでこの16進数を10進数に変換するのですが、ここで悲劇が。この変換がうまくいきません。ネットで適当に調べて出てきたツールを使って答えを出しましたが、得られた数字では通りません。仕方なく手計算しましたが普通に間違えました。原因はコピペミスです。つらいです。しかも、IDA上で右クリックしたら変換できました。

f:id:arthur_teleneco:20191006002719p:plain

初めてReversing問題自力でまともに解けた気がします。これだけで来た価値がありました。それに、終了2分前に通した問題。諦めないの大事ですね。

ちなみに、この問題は演習解説会のときに解説しました。「解けた人手を挙げて」と言われたので手を挙げたら、話すことになってしまいました。Webならもう少し流暢に解説できた気もします。心残りですね。

まとめ

個人的にはReversing解けたので来て良かったです。万人にウケるイベントは無理ですが、もう少しターゲットが明確に絞れるともっと良いなぁと感じました。Beginnerが広すぎるんですよね。本当の初心者はそもそも未経験なので、過去の大会成績などの数値指標を持っていないところも厳しい。

あと私はコミュ障なので交流会が少し辛かったです。劣等感で押しつぶされそうでした。みなさんどうしてそんなに話せるのでしょうか。もちろん交流会は参加必須ではないですが、特に用事がないのに早く帰るのもアレですよね。帰り道に花火大会帰りのカップルと遭遇したのもあってダブルパンチで傷心中です。悲しすぎてセッターカートンやけ買いです。