セキュリティ・キャンプ 全国大会 2015 個人的なWriteupのようなもの


本日のお昼頃、応募していたセキュリティ・キャンプ 全国大会 2015が無事に合格だったことを知り、大学の食堂でガッツポーズをしました。やったぞと。非常に嬉しかったですね。
しかし、Twitter等で参加する方々のプロフィールなどを見ていくと、やはり凄まじい技術力とオーラが漂っておりまして、ええ、覚悟はしてましたけどやはり圧倒されてしまいました。

そんな中で、どうやら応募用紙のWriteupを書かれている方が思ったより多くいらっしゃって、Twitter上で公開を勧められたこともあり、簡単にですが書いてみることにしました。
他の方々の用紙を見ていると、アセンブリでバリバリ書いていたりしていますが、私は書いてないです……なんかすみません……。

まだまだ未熟者で、見る人が見れば鼻で笑ってしまうような内容なのかもしれませんが、一応公開しておきます。

なお、公開という形にはなりますが、今後問題となるようであれば削除する方針です。
後半はほぼ内容そのままです。


筆者注 : これは2015年の筆者が『セキュリティキャンプに応募するために作成した、課題の(正確性を保証しない)解答』に過ぎません。
内容には不正確である部分が含まれます。書いた私が言うのも変ですが、絶対に鵜呑みにしないでください。

■共通問題1 (セキュリティ・キャンプに応募した自分なりの理由とセキュリティ・キャンプで学んだことをどう活かしたいか)

まず、昔から映画や小説などの影響を受けてセキュリティが好きだったこと、昔は自宅に古いコンピューターしかなかったことから、あまり実践ができていなかったことを冒頭で書きました。
そして、中学生以降自宅に新しいパソコンが入ってきて実践をスタートしたはいいものの、本などだけで得た知識は既に古くなっていたり、断片的過ぎてあまり役に立たないという事実を知ったこと、反省してセキュリティのみならずあらゆる分野から知識を吸収しようとしたということを中心に、今までも、そしてこれからも努力し続け、今回のセキュリティ・キャンプを通してさらに視野を広げていきたいという気持ちを精一杯綴りました。
また、最後には航空機へのサイバー攻撃の例を挙げて、今後のセキュリティがどのような役割を担うのか、自分がどのように社会へ貢献していきたいのかを説明しました。

■共通問題2 (印象に残っているセキュリティ関係の出来事、その理由)

NSAの大規模なデータ盗聴についてが主題です。
いくらテロリストの行為を防止するためとはいえ、関係のない一般市民のプライバシーをあそこまで徹底的に侵害する理由にはならないということを中心に、国民を監視するための『合法マルウェア』についての話題にも触れながら、ITに関する取り組みを進める前に、プライバシーの問題などについてもっと真剣に取り組む必要があるのではないか、という意見を書きました。

■共通問題3 (自己アピール)

高校生の時に放送部や生徒会で活動していたことから、どうすれば円滑に仕事を進められるのか、面白くなるのかということを考えてきたということ、そして部のウェブサイト運営やアプリケーション開発、サーバーの運用などを行ってきたことで、より実践的な経験が身についたということを書きました。
また、(これはこの後の選択問題にも使う話題なのですが)学校で使用する演出用のシステムと、それを操作するための遠隔操作プログラムを組んだということ、生徒会でバラバラだったデータを一か所で管理できるよう環境を整えたということ、大学ではプログラミングサークルに入ったので、モバイル系のアプリケーションについても積極的に学んでいきたいということも書いています。
そして、まだまだ技術は未熟ですがセキュリティに対する愛は健在です、ということを書いて締めています。

■選択問題3 (過去に作成して、気に入っているプログラムの詳細と今後の改善点)

学校で使用する演出用のシステムと、操作用の遠隔操作プログラムについて記述しました。
詳細はいろいろとアレなので伏せますが、簡単に説明すると、暗号通信や複数端末での映像同期再生機能やライブストリーミング連携などの機能を持ったシステムを作って、実際にそれを用いて予餞会を行った結果、成功したということを書いています。
今後はコンピューターに慣れていない人でもより簡単に操作できるような設計にするとともに、Raspberry Piを用いてさらに拡張し、より面白いものにして改善をしていきたいということを最後に書きました。

■選択問題7 (ネットワーク下に不審な通信をしているPCがある。これに対するアプローチ)

これについては以下の内容で解答しました。
標的型攻撃に関する本を参考に、若干のアレンジを加えています。

(1) Wiresharkなどで通信をモニタリングし、本当に不審な通信かを確かめます。
不審なようであれば、通信をモニタリングし続けながらIPやMACアドレスから通信元のPCを特定します。
深刻そうな場合は、通信元PCの通信を物理的に遮断します。踏み台にされている場合、今後の解析作業中に外部へと攻撃が行われている可能性があるためです。

(2) 通信元のPCを特定できたら、まず該当PCのスナップショットとメモリダンプを取り、動作しているPCのデータを取得します。
取得には FTK Image Lite などの専用ツールを用います。取得後、通信を遮断します。

(3) この後、ログの解析に取りかかります。通信ログから通信先のIPアドレス等を取得して、解析に備えます。
必要に応じてブラックリストやrobtexなどのサービスを利用し、通信先の素性を確かめます。使用サービスや国が分かれば、攻撃について多少の推測がつくからです。
また、リクエストしているデータなどから、それがどのような動作をしているのかを推測します(例:C&Cサーバーとの通信なのか、マルウェアのダウンロード等を行っているのか、など)。

(4) PCから取得したスナップショットやメモリダンプを参考に、マルウェアやバックドアツールなどの痕跡を探す作業に移ります。特にPsExecなどのメジャーかつ高機能なツールに注意することが重要です。
また、存在を確認したら、タイムスタンプや残存データなどからどのような攻撃が行われたのかを推測します。

(5) 必要であれば、RegRipper等を用いてより深い調査を行います。レジストリ値の洗い出し、イベントログなどの調査を通じて、不審な点がないかを徹底的に洗い出していきます。
タイムラインを作成し、ファイルが汚染されていないかを調べます。

(6) 可能な限り、不審ファイルを解析します。但し解析といっても、あくまで個人で許される範囲でのみ行います。
その後VirusTotalで既存のマルウェアかどうかを調べ、必要であれば解析結果と検体の情報を各種セキュリティベンダーに提供します。

(7) 以上までの過程で得た情報から、攻撃方法、被害、それに伴う対処と対策を考えます。
既存のアンチウイルスやセキュリティ製品で対応できる場合は、不審な通信元のコンピューターに対してインストール、実行して対応します。
もしそれらで対応できないか、もしくは完全に対応しきれない可能性がある(不審な通信が再発した等)場合、システムの完全リカバリかクリーンインストールを実行します。
万が一それでもダメであれば(非常に低い可能性だとは思いますが)ファームウェアレベルでマルウェアがインストールされている可能性があるので、ファームウェアを書き換えられる余地のある機材をすべて一新するか、破棄します。
また、情報漏洩などが確認された場合(C&Cサーバーとの通信、不正なP2P通信等)、使用しているサービスのパスワードや認証情報をすべて再設定します。

(8) 再発防止のための対策を講じます。必要であれば各種機関に連絡を行います。

(9) 可能な範囲でウェブ上に情報を公開し、今後、同様の攻撃を他のユーザーが受けないようにします。

(10)新しい発見や、対処のプロセスなどを確認しつつ、今後もセキュリティをさらに深く学ぼうと努力を続けることも大切だと考えています。

■選択問題9 (以下のコードの問題点を指摘せよ。textの中身は自由にできるものとする)

function makeUrlLinks( text ){
 var html = text.replace( /[\w]+:\/\/[\w\.\-]+\/[^\r\n \t<>"']*/g, function( url ){
   return "<a href=" + url + ">" + url + "</a>";
   } );
 document.getElementById( "output" ).innerHTML = html;
}

試してみると、明らかに脆弱性を持ったコードであることが分かります。
また、個人的に気になった点もあったのでそれにも対応してみました。
以下が解答となります。

[問題1]
まず、最大の問題として、この関数は XSS 脆弱性をはらんでいます。
今回の場合、JavaScriptの仕様上 text に <script> タグが渡されていても通常実行されません。しかし、以下のような攻撃コードを text として渡された場合、XSSが成立します。
これにより、攻撃者が自由にJavaScriptを埋め込むことが可能になってしまいます。

textに渡される攻撃コードの例 :
<img src="/" onerror="alert('XSS success');">

また、JavaScript以外にもHTMLタグが自由に使えてしまうため、使われ方次第では大いに問題となるでしょう。例えば、
<a href="JavaScript:window.alert('clicked');">ダミー</a>
のようなコードをtextに渡せば、自分で勝手にJavaScriptを埋め込んだリンクを生成できてしまいます。

makeUrlLinks() がHTMLタグを許可してしまっている点が原因なので、リンク生成前にエスケープ処理を行うことで解決します。
エスケープされていれば、これはただの文字列となるので攻撃は成功しません。

[問題2]
Internet Explorerでは、URL末尾のスラッシュ後に % のみ、あるいは %(数値一桁) がついたものが存在する場合、ハイパーリンクとして正しく機能しない仕様となっています。
例 : http://www.example.com/%
これはRFCに忠実に従った仕様であって、決してInternet Explorerの問題ではない上、このようなURLは正常とは言い難いです。
このままではリンクを生成する関数として未完成であるような印象を受けるので、この点も改善します(完全に除去できない可能性もありますが、可能な限り対応するようにします)。
URL末尾のスラッシュ後に %(数値なし または 十六進数一桁) が存在した場合、正常なリンクではないとみなし、エラーを表示して処理をスキップします。
なお、クエリでは %(数値なし または 十六進数一桁) も許容されます (例 : http://www.example.com/?q=%) が、いずれにせよ正常な動作が期待できないのでこれも正常でないとみなします。

[改善版コード]

function makeUrlLinks( text ){
  var delem = document.createElement('div');
  delem.appendChild(document.createTextNode(text));
  var escaped = delem.innerHTML;

 var html = escaped.replace( /[\w]+:\/\/[\w\.\-]+\/[^\r\n \t&lt;&gt;&quot;']*/g, function( url ){
     if(!url.match(/\/?%$/g) &amp;&amp; !url.match(/\/?%[0-9a-fA-F]$/g) &amp;&amp; !url.match(/%[0-9a-zA-Z]?%/) &amp;&amp; !url.match(/%[0-9a-fA-F][g-zG-Z]/) &amp;&amp; !url.match(/%[g-zG-Z][0-9a-fA-F]/)){
       return &quot;&lt;a href=&quot; + url + &quot;&gt;&quot; + url + &quot;&lt;/a&gt;&quot;;
     } else {
       return &quot;(Invalid URL : &quot; + url + &quot;)&quot;;
     }
   } );
 document.getElementById( &quot;output&quot; ).innerHTML = html;
}

ツッコミがあるかもしれませんが、一応このような形になりました (一部変更)。

■選択問題10 (アンチデバッグや難読化について知っていることを記述)

アセンブラに関しては初心者なので、出来る限り知っていること、分かったことをベースに構成しています。
しかしツッコミ所とか多いんだろうなぁ……と思ってます。もっと学ばなくては。

アンチデバッグや難読化という技術は、ソフトウェアの解析を防ぐための技術の一つです。
一般には商用アプリケーションやマルウェアにおいて、逆アセンブルのような静的解析やOllyDbgなどによる動的解析により、ソフトウェアの動作を割り出されることを防ぐために使用されます。

アンチデバッグは実行されているコンピューターで動作しているプログラムやメモリ、動作環境をスキャンし、プログラムの解析などに用いられるツール群、具体的には IDA ProやOllyDbg、各種IDEや仮想マシンやサンドボックスなどを検出した場合、自身の実行を停止したりツール群に対して動作の妨害を行う技術です。
この技術を悪用し、マルウェアなどはセキュリティベンダーなどによって容易に対応されないようにしています。
具体的には、複数スレッド複数プロセスを作成しデバッガによる追跡を困難にしたり、デバッガが使用する命令コードを監視し、存在する場合はデバッガをクラッシュさせるような動作等をします。
有名なものとしてはint 2dhを利用した方法などがあります。

難読化は、主に逆アセンブル、リバースエンジニアリングによる解析を困難にします。
ソースを他者に見られたくない場合、あるいはマルウェア作者が自身の作成したマルウェアに対する解析を妨害する場合などに用いられます。

難読化の具体的な方法としては、ツールを使ったものが主力です。
商用の難読化ツールを用いたり、パッカーやCrypterを利用して動作を複雑化させ、解析や既存のアンチウイルスによる検出を困難にします(FUD)。
マルウェアでは解析を妨害するため、パッカーやCrypterを複数利用するような手段をとっているものも少なくありません。
特にCrypterはアンダーグラウンド系サイトで公開されており、類似のツールも多く提供されているのが現状です。有名なものとして、xProtect等が挙げられます。
スキルのあるプログラマーは、独自のCrypterを用いることでより解析の困難さを上げることもあります。市場に出回っているツールは既に対策が進んでいる可能性が高いためでしょう。

また、マシン語として余分なものを追加する方法もあります。これらの方法は逆アセンブラでの表示を狂わせ、解析者が混乱するのを狙ったものです。
具体的には、ガベージバイトを用いて、実際には実行されないダミーの命令を挿入する方法などが挙げられます。
当然マシン語に対して理解がある人間でないと行えないので、実装できる人が限られるのが難点です。

最近ではPHPなどといったスクリプト言語でも使用されるケースがあります。
この場合、コードをbase64などでデコードしeval()で実行させるパターンや、ioncubeのように暗号化、プリコンパイルして独自のローダー経由で実行するパターン等に分かれます。
eval()タイプの難読化は WordPress を狙ったマルウェアに使用されていて、ioncubeのようなタイプは WHMCS のような商用製品で用いられています。

また、アンチデバッグや難読化はしばしば組み合わせて使用されます。有名な例として、UltraSurfのような匿名化ツールが挙げられます。
これは過去に銀行のサイト等をスキャンしていたとして話題になったツールでもあり、Ver 11の時点で難読化やOllyDbgに対する対策、デバッガーでアタッチすると終了する仕組みなどが取り入れられていました。

アンチデバッグや難読化などの技術は確かに解析を困難にしますが、重要なのは、まず確実に破られるという点でしょう。
どれだけ複雑にしても、腕のいい解析者であればじきに破ってしまいます。そのため、暗号鍵などの機密データをプログラム中に含めると、情報流出のリスクに晒されることとなります。

■選択問題11 (下記バイナリについて説明)

D4 C3 B2 A1 02 00 04 00 00 00 00 00 00 00 00 00 
00 00 04 00 01 00 00 00 88 EB 40 54 A2 BE 09 00 
52 00 00 00 52 00 00 00 22 22 22 22 22 22 11 11 
11 11 11 11 08 00 45 00 00 44 1A BD 40 00 80 06 
3A 24 C0 A8 92 01 C0 A8 92 80 10 26 01 BB 86 14 
7E 80 08 B3 C8 21 50 18 00 FC 0D 0E 00 00 18 03 
03 00 17 01 0E FB 06 F6 CD A3 69 DC CA 0B 99 FF 
1D 26 09 E1 52 8F 71 77 45 FA

他の方の解答を見ると、WireSharkに読み込ませるのではなくて、そもそもの仕様を調べてあくまでバイナリ的に解析している方や、MACアドレスに注目して解いている方もいらっしゃいました。
MACアドレスも重要なポイントだったのですね。それには気付けませんでした。まだまだ未熟であることを実感した次第であります……。

先頭が D4 C3 B2 A1 となっていることから、これは パケットキャプチャツールである Wireshark で閲覧可能な記録データです。

Wireshark で開くと、 192.168.146.1 から 192.168.146.128 への TLSv1.2 Heartbeat Request の記録だと分かります。送信元ポートは4134で、宛先ポートは443です。
また、Heartbeat Requestでエラーが発生している (通信に問題がある) 旨が表示されます。

確認すると、Payload Lengthが 3835 となっており、異常に長いのが分かります。実際のPayloadは 4バイト なので、3831バイト分が余計にリクエストされています。
ここで、実際のペイロード長よりも大きな値を指定し、SSLサーバーの脆弱性を突く攻撃だと判断しました。
これは、昨年三菱UFJニコスからの情報奪取でも使用された、OpenSSLにおける致命的な脆弱性 『Heartbleed (CVE-2014-0160)』を狙った攻撃の一部である可能性が高いと考えます。

Heartbleed脆弱性は、対処されていない古いOpenSSLにおいて、Heartbeat応答時に指定されたペイロード長をそのままメモリから読み込んでしまい、それが詐称されていた場合は実際のペイロード以外のデータも同時に送信してしまうという非常に有名な脆弱性です。
今回の場合、対象が古いOpenSSLサーバーであった場合、一回のリクエストで3831バイト分のデータがサーバーから漏洩してしまいます。
もちろん複数回リクエストも可能なので、サーバー側のアップデートが行われていない場合は大きな被害になる可能性が非常に高いでしょう。

〇結果を見て

結構自信もなくて、「来年はもっと勉強して受けよう」などと別の覚悟を決めていたりもしたのですが、何とか合格できて、まずは素直に嬉しいです。
しかし他の方の解答を見ると、やっぱり自分はまだまだだなと感じます。もっと勉強が必要ですね。
アセンブリコードなんて、若干しか読めませんもの。一応学んでいますが、まだまだ実用には程遠く……。
うーん、頑張らねば!

折角のセキュリティ・キャンプ。凄いスキルを持った人たちと会えることに感謝しつつ、自分もより高いレベルを目指して努力していこうと思います。