セキュキャンのアドバイス&昨年度の応募用紙晒すか・・・

2017年度のセキュリティキャンプ全国大会の募集が開始されてます。
セキュリティ・キャンプ全国大会2017 ホーム:IPA 独立行政法人 情報処理推進機構
セキュリティとかわかる人も、わからない人も良い機会になるはずです。
(自分の無力さを知ることも大切です!)

大学生が多いですが、高校生とか高専生もためらう必要はないと思います。

受験者へ

セキュリティキャンプの応募で求められるのは正解ではなく熱意だそうです。
多少間違っていたり冗長であっても全部書ききった方が良いのではないでしょうか。
具体的な基準はわかりませんが、正解だけ書いてあるとか、文章があまりにも短いのはよろしくないみたいです。

例えば、この年の選択問題【8】なんかは「このプログラムはc@Np2Ol6と入力した時に終了コード0、それ以外で終了コード1で終了するプログラムである。」という1行で終わるところを私は延々と求めるまでの手順を書いています。その手順もあまりに稚拙で恥ずかしかったのですが、熱意を見せるならいっそ書くか、と思って書いて出しました。

あと、基本的にわからないことだらけだったので、めっちゃググりました。はい。
こんなの調べずに全部わかるような輩はそうそういないと思います。

黒歴史を晒す

問題はこちら→https://www.ipa.go.jp/files/000053055.pdf

かなり稚拙で恥ずかしいです。あと、一部はXXXと伏字にさせてくださいorz

あと、ごちうさの問題はシャロちゃん派だったので解きませんでした。

共通問題 【1-1】:

最も最近だと、作ったものではないかもしれないが、XXのWebサイトにXSSの脆弱性を発見しIPAに報告した。現在は修正済み。 具体的には、URLの一部のパラメータを書き換えるとエラーページが表示されるという構成になっていた。しかし、そのエラーページの中にコメントアウトしてサーバー上のJavaのIllegalArgumentExceptionのスタックトレースが表示されていた。 そのスタックトレースの中にパラメータに指定した値が出現するため、パラメータに–><script>alert()</script>などを仕込むとスクリプトが実行されてしまう。また、セッションIDのCookieにHttpOnlyがついていないため、Javascriptから読み出されてしまう。 また、タグを生成して偽のログインフォームを作れば罠URLを使って利用者をそこに誘導し、IDとパスワードを抜くといったことも可能かもしれない。

XXのドメインやログイン情報は重要な情報を管理したりXXXXを見ることができてしまう。さらに、XXだとXXXXXとより強い権限を持っている。しかし、それを利用しているXXのリテラシーにはばらつきがある。XXX・もし学校のサーバー上にXSSやCSRFの脆弱性があって誰かが罠URLを張った場合、多くの人が引っかかるのではないかと思った。

その他に作ったものだと、現在はXXXX公開を停止してしまったが、XXXXデータを解析して表示するソフトを作ったことがある。

共通問題 【1-2】:

Webページの脆弱性については、ブラウザでソースを見た際に不自然さを感じ、パラメータを弄ったところエスケープされていないのに気づいた。CookieのHttpOnlyなどについてはChromeの開発者ツールを使ってみた。

ゲームのデータ解析については、C#(WinForms)を使ってプログラムを書いた。データの構造については海外のWikiにある程度解析結果が乗っており、それを元に残りのデータを解析した。バージョンアップによってファイルの構造が一部変わっており、その違いを調べるのにかなり時間がかかった。 データ中には画像データが独自の方法で圧縮されて入っていた。(解析の具体的な内容を3行程度) 当時はそれで精一杯だったが、現在であればもう少し効率の良いプログラムが書けるのではないかと思う。

また、C#だったのでただ解析するだけではなく、GUIで見やすく表示したり、色を変えたりという機能にも比較的簡単に対応させることができた。

共通問題 【2-1】:

C#でCOMやWin32APIを利用したソフトを作るときに、想定外に呼び出しが失敗したり、取得した値が見つけていた情報と違う形式だったりして苦労した。特に、一部のフックを実装したい時にC/C++の方法は見つかるが、なかなかC#での詳細な解説がなかった。.NET Frameworkはこの科別にぶつかった当時は違うバージョンのランタイムを同じプロセス内で同時実行できないという制限があったりする影響で、基本的には一部を除いてフックに対応していないということだった。

共通問題 【2-2】:

ある問題については、海外のStackoverflowに同様の事をしようとしている質問がいくつかあり、OSのバージョン等によって動作が異なるとの事だった。いくつかの質問の情報を組み合わせることで解決した。 また、フックに関してはSmartSystemMenuというOSSを見つけ、その処理を参考にすることでなんとか実装することができた。そのプログラムではC/C++でDLLを書き、それをフックに登録し、C#からそれを制御することによって問題を回避していた。C/C++の知識が少なかったので苦労した。 http://smartsysmenu.codeplex.com/ また、掲示板で質問し、回答をいただいて解決した問題もある。

共通問題 【2-3】:

共通問題 【3-1】:今回のセキュリティ・キャンプではIoTトラックと解析トラックに大きな魅力を感じています。

大量に上げるとキリがないので、両方から3つずつあげてみようと思います。

IoTトラックでは

■1-B BareMetalで遊ぶ Raspberry Pi 入門編

Linux等の無い、素の環境についての知識を学ぶことにより、IoTや組み込み環境でLinuxが動かないような状況でどのように制御をすればいいのか、ということを学んでみたいです。低メモリなマシンを最大限活用したりする際に役に立ちそうです。同時に、LinuxやWindowsが動く環境でもその仕組を理解し、より効率的なプログラムを書いたり、解析に役立つのではないかと思いました。 最近はTOPPERSなどのOSの話もよく耳にする用になり、あわよくばOS開発の足がかりにしてみたいとも思っています

■6-B AVRマイコンで作るBadUSB自作

BadUSBの話は以前聞き、非常に画期的な脆弱性だと思いました。今までは脆弱性はパソコン上で実行されるプログラムの問題だと考えていましたが、USBデバイスがキーボードのように振る舞い、コマンドを入力するといったデモをネットで見て非常に驚きました。USBデバイスが勝手に危険な動作をするというのは、言われてみれば当然でも考えたことがありませんでした。
しばらくしてソースが公開されたり自作したりと言った話しがWebに上がるようになりましたが、自分で作ってみたりするにはハードウェアの用意と低い層の知識が必要でなかなか挑戦することができずにいました。今回の講義で実際に作ってみることで、USBデバイスの仕組みといったものをしっかり理解したいです。
また、ハードウェアによるキーボードのエミュレーションは攻撃以外の、役に立つハードウェアの作成にも役に立ちそうだというのも理由の一つです。パソコン側でデバイスをエミュレーションしたり、フックしたりするにはドライバを書いたりする必要があり、それもセキュリティ上の理由でMicrosoftの署名が必要になるなど、ハードルは上がる一方です。それをデバイス側を改造することで対処するというのは面白い解決策なのではないかと思いまsy。

■7-B 組込みリアルタイムOSとIoTシステム演習

今まで汎用システムのプログラム以外はほとんどやったことがなかったのですが、近年はIoTがブームになってきており、組み込みやIoTの分野にも挑戦したいと思っています。 TOPPERSを始めとしてリアルタイムOSについてはよく聞くのですが、いまいちその全貌や利点がつかめずにいます。
この講義で組込みやIoTを学ぶ基礎知識を付けてみたいです。

解析トラックでは

■4-D 実行ファイルの防御機構を突破せよ

「攻撃を工夫する」というのがどのような事を指しているのか知りたいです。近年のOSではメモリのランダム配置やメモリの実行権限など様々な対策が取られており、ゲームなどでよく見るバッファオーバーランにより実行領域が破壊され、自分で書き換えができる場所にジャンプして任意コード実行を行う、といったことは難しくなっているのではないかと思っています。しかし、脆弱性の情報を見ていると、どうしてこんなことを思いつくのだろうというようなトリッキーな攻撃手法が紹介されていることがあり、自分でもこのような脆弱性を発見し、将来的にはその修正にも携われるようになりたいと思っています。そのためにこの講演を拝聴したいです。

■5-D みんなでクールなROPガジェットを探そうぜ

今回の選択問題でもROP的なバイナリの解析がありましたが、巨大なソースもないバイナリファイルからどうやって使えるコード片を探してそれを組み合わせているのかというのが非常に気になります。あの程度の逆アセンブルを読むのでさえ苦労したのに、それよりも巨大なバイナリを読んだり組み合わせたりできる気がしません。ROPを始めとして、よく使われるような脆弱性を効率的に探したりする方法に興味があります。

■7-D .NET プログラムの解析

現在自分の一番好きでメインにやっている言語はC#なので、そのコンパイル後のMSILなどにも興味があります。最近ではC#にも構文糖の追加や、MSILに存在した共変性フラグを設定したなど、MSILの知識があればもっと理解できそうな話がたくさんあります。また、C#やVB.NETで書かれたコードがどのように最適化され、どのようにMSILに展開されているかはプログラムの実行速度に関わることであり、それを読めるようになればこのような根拠からこちらの書き方のほうが良いということができるようになると考えています。 解析という点では逆コンパイルにかけてみた時に、難読化されているプログラムを何度も見かけており、現状のソフトでは逆コンパイルが表示されないものも見たことがあります。(どうやら、無効な命令を追加することで解析を妨害しているようです。)それを解析してある程度まで読める知識がほしいなと思います。

共通問題 【3-2】:

私はセキュリティに大きな興味を持っており、セキュリティ業界やブラウザ、OSの安全性を高めるような仕事が自分の進みたい仕事の候補です。そのために、アセンブリやOS、解析などの低層の知識を身に着けたいと考えています。組み込みや制御の分野にも興味がありますが、IoTによってすべての物が攻撃の対象になりうる時代も到来しており、どちらにしても低層の技術は今まで以上に重要なものになってくると思われます。
しかし、セキュリティの知識は同時に攻撃の手段ともなるので公の場で質問や情報共有がしにくかったり、前提知識が無いと意味が理解できないものが多く、勉強に苦労しています。また、特に低層の知識については入門的な情報が少なかったり古いものが多く、なかなか進展が得られない日々が続いています。
今回のセキュリティ・キャンプでは自分の知らなかったことや学べていなかった事を知り、これから本格的に学んでいくための足がかりにしたいと考えています。

また、同時にセキュリティ分野の専門家の方や、同じようにセキュリティの方面を志している他の学生と面識をもちたいというのがとても大きな理由です。勉強会や懇談会に参加するようになったのは大学に入ってからなのですが、それでプログラミングやコンピュータの細かい話をする相手ができ、同時にわからないことを聞いたり、教えたりということを経験しています。ほかのひとが頑張っていたり、詳しい人から教えてもらうのはとても強い刺激となり、勉強会に行く前と比べて圧倒的に勉強の意欲が増しました。今回のセキュリティ・キャンプでは学生と交流を持つことにより、同年代の友達、ライバル、仲間を増やしたいと思っています。

選択問題 【3】:

(ブログ投稿時のコメント: あまり詳しくない分野です。頑張って気合いでググりました。BIOSの役割説明しているサイトは多いのですが、現在はUEFIがやっているよという事実を知っているアピールと、メモリマップまでなんとか調べて記述しました。)

ノイマン型コンピューターでは、主記憶装置上のプログラムしか実行することができない。 電源が投入されるとまず電源が安定するまでクロックチップによりCPUの動きが抑制される。電源安定度、CPUは動作を開始し、レジスタやキャッシュをクリーンアップする。CPUは予め電源投入時にメモリ上の特定の位置のプログラムの実行を開始する用に設計されている。 そのメモリ位置には、マザーボードのROM上にファームウェアとして記録されているBIOSやUEFIがマップされており、それが実行される。

BIOSやUEFIはまず自分自身の動作に必要なメモリを確保しいくつかのハードウェアチェックや、ディスプレイに対して表示を行う。この段階でエラーがあれば、それを画面に表示。それもかなわなければビープ音異常をしらせる。また利用者のキーボードの入力などにより、設定画面が起動できるようになっている。エラーがなければOSの起動に移ろうとする。

OS起動の仕方はBIOSとUEFIでは大きく違う。BIOSではまず、補助記憶装置の中で最も優先度が高く設定されているものを参照し制御装置に命令し、その先頭セクタをRAMに読み込む。その中身を見て起動メディアかどうかをチェックする(フロッピーなどは無条件で起動メディアと判断する。)起動メディアであればその先頭セクタはブートローダであるため、実行する。なお、この処理は非常に古いコンピュータから引き継いできた歴史的事情により、サイズの小さい先頭セクタしか読み込めず、リアルモードで行われるため、メモリなどに大きな制限がかかる。ブートローダはOSを補助記憶装置からRAM上に読み込み、順次起動処理を行っていく。

UEFIでは起動対象のディスクのGUIDパーティションテーブルを参照し、EFIファイルパーティションを特定し、その中の設定で決められたファイルをRAM上にロードし、実行する。ここではBIOSでのブートローダと同じく、OSの起動プログラムをRAM上に読み込み、実行していく。ただし、BIOSと違いCPUはプロテクトモードで動作可能であり、メモリや起動プログラムも大きなサイズ制限を受けない。そのため、非常に楽にプログラムを書くことができるようになっている。

OSが起動すればBIOSやUEFIはほとんどの役目を終え、今後はOSが補助記憶装置上から実行するプログラムをRAM上に読み込むか、メモリマップなどを使って主記憶装置上にあるのと同等の状態にした上で実行している。

組込み機器などの場合は汎用OSと違い、実行されるプログラムが製造時に確定していたり、規模が小さい。その場合はROM上にプログラムが書き込まれており、それを主記憶装置としてマップすることで電源投入時にそのままCPUがBIOSを実行するのと同じように実行を開始することとなる。

選択問題 【5】:

(ブログ投稿時のコメント: 組み込み開発も全くの未経験です。噂とググったのだけで書きました。)
汎用OSは様々な環境で様々なプログラムを動かすことを想定して設計されており、ハードウェアも用途によっては過剰なスペックを持ったものが使われる。それに対して組込みシステムは利用用途が決まっている。ハードウェアもそれに合わせた最小限のものになっている場合もあり、組込みOSは必要な要件を満たした上でそのハードウェアの能力を最大限生かすような動作が求められる。例えば、OSが専有するメモリが汎用OSより少なかったり、特定のハードウェアを前提としてそれに依存した動作をするなどが考えられる。例えば時間的な制約があるシステムの制御(車のブレーキはすぐに動作しなければならないし、機械の制御の計算が一定の時間に終わらなければ故障に繋がる)では、動作が完了する最悪の時間が定められていたり、動作が一定の間隔で実行されるリアルタイムOSなどが存在する。

一方で、十分なハードウェアがある場合は汎用OSに近いOS(Windows Embeddedなど)が用いられることがある。これは汎用OSに組み込み用の機能を追加したものである。必要に応じて汎用OS用のソフトやデバイスを利用できるという利点がある。しかしPOSシステムやナビゲーションシステムなどのように使用用途が決められている場合は必要以上の機能を持っているとそこから攻撃を受けたり、情報流出したりといったリスクが発生する。そのため、組込みOSでは機能を強く制限し、必要な機能以外は完全に使えなくシたり、特定のポートの通信をフィルタリング、監視したり、ハードディスクに情報を残さないようにしたりといった方法でセキュリティ対策を行える用になっている。

OSが無い、ベアメタル環境ではむき出しの金属のようにハードウェアを直接制御することができる。OSがないため、メモリも物理メモリに直接アクセスすることとなりmallocといったOSによって提供される機能を標準では利用できず、スタックとヒープといった違いも存在しない。また、メモリ保護などもCPUの機能などを除けば存在しない。一方で、ハードウェアやメモリをOSの制限を受けることなく利用できるため完全にプログラマの手で制御を行うことが可能で、より効率的で省メモリなプログラムを書くことができる。 しかし、正しくて効率のよいプログラムを書かないとメモリを破壊するなど不安定だったりセキュリティリスクが生じたり、OSに頼ったプログラムより遅くなったりメモリ効率が悪くなってしまう場合もある。OSにがやってくれていることの一部を自力で実装したりするわけで同じことをしようとすれば難易度やかかる時間は大きく増えてしまうと考えられる。OSがある場合にプログラミング入門でやるHelloWorldもOSなしでは困難であり、LEDライトをつけるなどが入門編となる。

選択問題 【6】:

(ブログ投稿時のコメント: これも聞きかじったり適当に勉強したりした知識で・・・って、全部そればっかじゃないかorz。個人的には、我々は攻撃者ではないといぜアピールとして「独立したテスト環境」とかを入れたのがポイント)

まず、セキュリティテストを行うのなら本番環境と同様の独立したテスト環境で行わなければならない。生じた問題によってはデータベースを破壊したり、サービスが停止してしまう恐れがあるためである。仮想環境を利用すると作りやすい。

まず、Saasなどを利用することにより、サーバーのOSのセキュリティなどについてはSaasの提供側に任せることができる。よって、Webアプリのセキュリティテストに専念できると考える。 最初にSQLインジェクションやXSSなど、入力値やURL、HTTPヘッダなどに対する処理が適切に行われているかを検証すると良いと考える。それにはいくつか理由がある。 ・ユーザーがブラウザから送信するデータは自由に設定でき、Webアプリのプログラムで処理することになるため脆弱性が生まれやすい。 ・XSSなどを生じさせるデータを送信したりしても不正アクセスとはみなされにくいため、低リスクに攻撃が行える。 ・攻撃しようという意思がなくとも、いたずらや簡単な検証、場合によっては偶然でも脆弱性を踏んでしまう可能性がある。 ・Seleniumやスクリプト類を使って自動化することでテストの手間を軽減できる。

XSSやCSRFはたとえ致命的な脆弱性でなかったとしてもそれが存在したというだけで、他の部分のセキュリティ対策への信用を落とす結果となりかねない。 また、一箇所でエスケープのミスをしていれば、別のもっと致命的な場所でも同じミスをしている可能性がある。特にSQLインジェクションやOSコマンドインジェクションは不正にログインされる程度ではすまず、データを破壊したり、想定していないような危険なことを実行される可能性があるため、特によく確認しなくてはならない。

選択問題 【8】:

(ブログ投稿時コメント: うむもちろんアセンブリはほぼ未経験だ。CASLの入門書を図書館で昔読んだり、でじたるとらべしあさんのサイトを読んだりしたぐらいです。この当時はgdbも使ったことがなくて、よく分からないまま紙に延々と処理を書いていました。)

まず、結論から言うとこのプログラムはc@Np2Ol6と入力した時に終了コード0、それ以外で終了コード1で終了するプログラムである。

プログラムの内部では以下の様な動作が行われている。 まず、最初にプログラムはスタックにアドレスや引数と言った値を0x4000fcまでの命令で積む。そして、retqによって積まれたスタックをコールスタックと解釈し、その命令の番地にジャンプする。 最初にジャンプする0x400102では、積んであるスタックから値を%raxレジスタに格納する。 そして、再びretqでスタックの値をコールスタックとして解釈し、ジャンプする。 同様にスタックに格納された値をrdi,rsi,r10,rdxレジスタに格納する。 そして、0x400119 syscallでシステムコールを行う。この際、raxはシステムコールの番号、rdi,rsi,r10,rdxは順にその引数となる。この呼び出してはraxは0なので、read(2)が呼び出される。引数は0,スタックへのポインタ,8,0となる。 man pageによると、read(2)の構文は以下である。 ssize_t read(int fd, void *buf, size_t count); ファイルデスクリプタが0の時はstdinを意味しており、size_tは8byteなので2つのレジスタで表されるので、標準入出力から8byteをスタックのとある位置に書きこむ、というシステムコールとなる。

その後、同様にretqとスタックを駆使しながらdecとjneを使ってループを回し、先ほどのシステムコールでの入力の位置を1byteずつxorbで排他的論理和を取っていく。それをcmpで比較し、0x4000a2のmovabsの引数となっている値と一致すれば0を、一致しなければ1をレジスタにセットし、システムコールの60番(exit(2))を呼び出してプログラムを終了する。

[調査の過程]

アセンブリの知識は殆ど無く、ニーモニックもpushqのqがなにを意味しているかわからなかったのでそこから調べた。 簡潔にまとまっているサイトはなかなかなかったが、qはQuadWordのqで、64bitの操作を意味しているとわかった。 ぼんやりとコールスタックやレジスタで引数を渡す程度の認識はあったが、ひたすらpushを繰り返しているのがなぜか分からず、とりあえず実行環境を整えることにした。

objdumpを使うということで、linux環境と判断し、linux上でアセンブリをコンパイルする方法を調べると、gccで可能だった。最初はやり方もわからず適当なプログラムの逆アセンブルを指定されたプログラムに書き換えようとしたがなかなかうまく行かず、.textを最初につければそのまま.sファイルとしてコンパイルできることに気づいた。 しかし、そのままではメモリ配置がずれてしまうので正常に動作しない。そこで、調べて-nostdlibで標準ライブラリのリンクを無効に、リンカオプションの-Ttext=0x400080で.textセクションのベースアドレスをを指定した。しかし、別のセクションと領域がかぶっているというエラーが出たので、さらに調べて–build-id=noneを指定する事によって別のセクションが入らないように出来、想定しているメモリ配置を実現できた。

その後は、gdbでステップ実行をしているうちに、このコードが最初にスタックをまとめて積んで、それをコールスタックなどに解釈しながら実行していく、というプログラムだと気づいた。それを元に、紙にプログラムの動きをメモしながら処理を確認していたが、毎回Illigal Instructionでプログラムがクラッシュしてしまった。よくよくobjdumpの結果を比較すると、0x400129のジャンプがもとと違って長い命令が生成されている事に気づいた。おそらく、相対ジャンプではなく絶対ジャンプの命令が生成されたのではないかと思う。そこをヘキサエディタのGHexで書き換え消したのと同じ長さ分、プログラムの末尾にnopを追加した。 これで問題なくプログラムがエラーで止まることはなくなった。

その後も処理を追っていくが、gdbがなかなか見難く、GUIのツールを探したがC言語のソースをデバッグする際にgdbを使うといったものが多く、逆アセンブルだけを読むためのツールはDDD程度しか見つからなかった。最終的に、gdbにText User Interfaceがあり、 layout asm layout reg と入力することによって逆アセンブルとレジスタの状態を常に確認しながら実行できることがわかったのでそれを使うことにした。 スタックの状態を綺麗に見られないのが辛かったが、displayコマンドなどを活用し、なんとか読み進めた。 最終的に、xorbがrsiを書き換えているのに気づくのに時間がかかったが、なんとか全体の理解に成功した。

[感じたこと]

retqが繰り返されるのを見ると、これはROPの模擬コードではないかと思った。 非常に単純な命令を組み合わせてシステムコールを呼び出したり、ループしてxorをかけるなど複雑な処理を行っている。 実際のROPはさらに余分なコードが付加されているはずで、これを解析するのは時間がかかりそうだと感じた。

解析中に感じた感想としては、とにかく、アセンブリの知識が無いのが辛かった。 公式リファレンスなども参照してみたが、あまりにもページ数が多く難解だった。 また、ツールとしてもWindowsではollydbgを本を見ながら少し触ったことがあったが、Linuxで同様のことができるGUIツールを知らず、探しても見つからなかったのでそこが辛かった。スタックの状態やブレークポイントをGUI上で確認、設定できればだいぶ楽に読めたと思う。多分そのようなツールも存在すると思うので、ぜひとも知りたい。 かなり苦労したが、意味が読み取れたタイミングはとても達成感があり、面白かった。

終わりに

現在の知識量は致命的な問題ではありません。
回答期間は1ヶ月あるので、テストとかがあるのなら、なおさら早く始めましょう。合計1週間程度徹夜すれば回答ができるはずです! 頑張ってくださいね!!