ψ(プサイ)どうしても試験勉強に身が入らないのでちょっと気分転換がてら晒してみるテストでございます。来年度以降セキュリティ&プログラミングキャンプに応募しようと思ってる方はどうぞ。こーんなどーしようもない事書いてても大丈夫です。Cやアセンブラによるプログラミングに興味はありますか?[ある][C]キャンプの公式Webページの講義科目に記載されたこの組の講義科目の[概要]と[詳細]と[補足]をよく読んで納得できましたか?[できた]■この組を希望した自分なりの理由を教えてください。何を学びたいか教えてください。(選考上もっとも重視します)今まで逆アセンブラによる解析を行ったり、それを用いたソフトウェアの移植、ゲーム内データのコンバート、自分のさせたいように処理を改変するパッチの作成、コピープロテクト外し(勿論、ちゃんと買った製品でですよ!;起動時に毎回DVDを入れるのが面倒なもので)、簡単なセキュリティホールの発見や攻撃のデモの作成等を行ってきましたが、どれも攻撃一辺倒で防御側の経験が全くありません。基本的に学習は(ネット上で手に入る教材の多い)コピープロテクト外しやゲームの改造を題材に行ったもので行っており、それ以上の応用は難しく、ウイルスや実際のソフトウェアの脆弱性に基づいた攻撃といった、高度な攻撃手法には全く太刀打ちが出来ませんでした。そこで、このキャンプに参加することで「実際の攻撃で使われる」実用的な攻撃手法について体系的に学ぶとともに、防御側から見たセキュリティについても考えてみたいと思っています。正直に言えば、その知識を使って社会の役に立ちたいといった立派な目的とか、あるいは逆に銀行のシステムに侵入して自分の口座に大金を送金したい(笑)といった思いは全くなく、純然たる知識欲、あるいは「ハッカーになりたい」という思いで今回応募させていただきました。実際、プログラムを解析したり、脆弱性の突き方を考えるのが楽しくてしょうがないです。いった人の方が純粋な探究心は高いでしょうし、歴史的に言えば、そういった純然たる知識欲からセキュリティ上の悪戯をして逮捕されたハッカーが素晴らしいセキュリティ専門家になることもままありましたから、そういう人が居ても良いんじゃないかと思います。■プログラミング歴を教えて下さい。(特にシステムプログラム†1)があれば、差し障りのない範囲で具体的に教えてください。プログラミング暦は10年ほど。アセンブラからシェルスクリプト、ウェブアプリから組み込み系(主にゲームハード用)まで、言語・ジャンルは何でも書きますが、何かしらのパズルを解くような、アルゴリズムが最重視されるようなプログラムは不得意で、ツールやシステムをいじるようなプログラムをよく書きます。randomization)によってライブラリの関数のアドレスは変わっても、アプリケーション内に存在する関数のアドレスは変わらないことを利用した、return-to-libcの攻撃コードです。アプリに含まれる任意のコードがすべて実行可能になります。原理や攻撃コードの中身については上記のページをご覧ください。HTTPなトンネリングソフトです。高校の時、フィルタリングによって高校のネットワークからニコニコ動画に繋ぐ事が出来なかったので作成しました。(もちろんニコニコ動画以外にもつなげます)一回自宅のサーバ(私のblogがおいてあるサーバです)を経由することで、フィルタリングを回避します。↑[はづきクライアント]→(暗号化)→[自宅サーバで走るはづきサーバ]→↑(代理アクセス)このはづきサーバはLinuxのデーモンとして実装してあります。当時の自宅サーバは諸事項でカーネルverが2.4台だったのでプレフォーク型サーバとして実装してあります。この後、自宅サーバへの異常なトラフィックからサーバ管理者(このキャンプを紹介してくれた人)に見破られ、自宅サーバへもアクセス制限が掛けられて結局使用不能になりました(笑)。CGIとして実装しなおして複数のフリーウェブサーバに分散して配置し、それらをラウンドロビンして使うといった事も考えましたが、そこまで気合がなかったというのに加え、さすがに負荷が高くフリーサーバでそこまでするのはどうかという思いから断念しました。■さきゅばすニコニコ動画の動画を、コメントを動画に焼きこんで(デフォルトでxvidのaviとして)保存するソフトウェアです。変換部分はffmpegという有名なオープンソースの動画エンコーダに動画フィルタを追加して実装しています。この動画フィルタは、ffmpeg.exeに追加したDLLローダからnicovideo.dll(実際のフィルタ処理が書いてある)を動的に呼び出して処理しています。した理由は、ffmpeg.exeが余りにも巨大でリンクに5分以上かかるため、頻繁に更新するフィルタ処理部分をdllで分けたほうが開発時間短縮になるからです。オープンソース化し、そこそこ人気も出ているようです。■ZERO昔つくったオセロプログラムです。Javaで書かれていて、一般的なNegaScoutというアルゴリズムで動いていました。Yahoo!レーティングで1700(結構上級者)くらいまで行きました。ルビー/サファイア/エメラルド/ファイヤーレッド/リーフグリーン」に対応した、セーブデータの書き換えツールです。実装に当たってはゲームのROMを吸い出してエミュレータ上でセーブデータの保存処理を解析し、チェックサムを正しく書き換えています。■巫女が死ぬとファイルが消える東方ゲームの処理の一部を書き加えた上で自分で書いた処理を付け加え、プレイヤがミスをするとマイドキュメントのファイルが一個ずつ消えていくようにしたジョークプログラムです。緊張感が凄いです(笑)。注意メッセージの表示部分をつぶしてP2Pに流されると非常に危ないので動画しか公開していません。自分の顔写真をアップロードして、顔の中心・あご下・頭のてっぺんの位置を指定すると、証明写真を印刷するためのPDFが作られて、それを印刷することで自分で証明写真を作れるサービスです。iText(PDF作成ライブラリ)で実装しています。■UFO大好き霊子さん同様にウェブサービスです。使用者が余りにも居なかったのでサーバ更新時に廃止してしまいましたが...。UFOや心霊、廃墟や超心理学に関する場所をGoogleMapを使って登録して共有し、現地の写真を投稿したりコメントがつけられるサービスです。ストリートビューとも連携していて、ストリートビューに写っている心霊写真も登録されていたりしました。C数年前に流行った「成分解析」という占いプログラムを解析して、CによるCGIに実装したウェブサービスです。■SynFlood攻撃プログラムシステムプログラムと呼べるかどうかは分かりませんが、ioctlとかを使って生パケットを組み立て送信して、synflood攻撃をするプログラムを書いたこともあります。外部に向けて送信しようとしてもプロバイダで弾かれるのでLAN内でしか効果が無いのですが。時間が無くて開発は出来ていませんが、以下のようなプログラムを作りかけています。■強制Portable化ランチャ(win32)USBなどにアプリを入れて持ち運ぶ「PortableApps」が最近人気ですが、レジストリに設定を書き込むソフトはそのままではPortableに出来ませんし、「/ユーザ名/config」に設定を書き込むタイプのアプリも、PCがわかってユーザ名が変わるとやはり設定が引き継がれません(毎回設定ファイルをコピーすればよいのですが、面倒)。そこで以下の手順でAPIをフックする事で、レジストリや設定ファイルの書き込みを制御し、Portable化するソフトです。スペンドした状態でPortable化するアプリをCreateProcessエントリーポイントのコードをを無限ループに書き換えとりあえず実行して定期的にEIPを監視EIPがエントリーポイントまで行ったらプロセスをサスペンド制御用のDLLを注入IATを書き換えてRegOpenKeyExやFileOpenのようなファイル操作関数をフックCreteProcessもフックし、Portable化するアプリが子プロセスを作るときも1~6を繰り替えし、子プロセスが読み書きするファイル・レジストリも制御するフックしたRegOpenKeyExやFileOpenでは、同じフォルダにある設定ファイルに基づいてレジストリやファイルの読み書きを制御し、レジストリはファイルに、設定ファイルもユーザ名の部分を適宜変換して読み書きさせ、他のファイルは普通に元のAPIに処理させます。XPで1/3開発しただけなのでVista以降だともしかするとUACが必要かもしれません...。FastCGI(マルチプラットフォーム)Prologでウェブアプリを作ろう、とふと思い立ちProlog用のFastCGIモジュールを作りました。Apache/Lighttpdで動きます。Prolog」は動いているのですが、Webアプリにあると便利な様々な述語が実装しきれていないのでまだ未公開です。■これまでに開発したプログラムで経験したバグ、およびその影響について差し障りのない範囲で具体的に教えてください。公開はしていないのですが、開発したシューティングゲームで何故か特定の弾(1~2発程度)の速度が異常に速くなるバグがありました。原因はいわゆるOff-by-oneで、メモリの配置がちょうど弾の構造体の前のほうにあったデータを長さを超えて書き込んでしまい、ちょうどその「書き込みすぎた」データが弾の速度の領域に被っていて、その書いたデータを速度として読み取ると高速になる、というバグでした。(静的に確保した領域だったので、メモリの配置が毎回ほぼ一緒でした)デバッガーを使ってメモリの状態を監視することでやっと発見することが出来ました。C」で入力したテキストのを実態参照に変換し忘れて表示していて、XSSが可能になっていたというバグがありましたが、使われる前に気づいたので無事でした。0のときにNULLが帰ってきてクラッシュしたり、といったバグは経験した事がありますが、脆弱性となるようなバグは今のところ経験した事がありません。(たぶん発見されていないだけですが)このように、全体的に防御する側の経験が不足しています。■セキュリティホールは放置しておくとなぜ危険なのでしょうか。自分の言葉で説明してください。それは、コンピュータはプログラマの忠実なしもべであるはずだからだと思います。コンピュータはプログラマという主人の命令に忠実に働く、信頼できる最高の奴隷である、と私は考えています。その信頼関係があるからこそ、勝手にレジのお金を盗むアルバイトと違って大事なデータも預けられるし、大事なお仕事も代行させられるのだと思います。それが脆弱性によってコンピュータが攻撃者の命令も聞くようになってしまったり、喋ってはいけない情報を無理やり喋らされてしまったりすることで、主人(プログラマやプログラムを使う人)と奴隷の信頼関係の前提が根本から失われてしまうから、ではないでしょうか。(逆に、だからこそセキュリティホールを突いたりゲームを改造したりコピープロテクトを外したりするのが楽しいと感じる人が多いのだと思います)■ソフトウェアの脆弱性をなくすには何が必要でしょうか。短期的には、ソフトウェアを開発するときはできるだけリッチで枯れたライブラリに任せ、”できるだけプログラムを書かない”ことだと思います。これは車輪の再発明による開発効率の低下を防ぐ意味もありますが、何よりプログラムが短ければそれだけバグも生まれなくなるはずです。ソートやデータ構造や文字列操作は自分で書く利点はありませんし(とくにマルチバイト文字列)、絶対にライブラリ任せにした方が良いと思います。長期的には、プログラマはミスをする、という事を前提に対策するしかないと思います。バッファオーバーフローならJavaやC#みたいに毎回配列を超えていないかをチェックする事で完全に防げますし、NXビットを使えば仮にスタックオーバーフローしてもスタック上にシェルコードを置いて実行させる手法は非常に難しくなります。ハードウェアやカーネル、実行処理系で注意深く対策し、その上で動く大多数のプログラムはバグが発生してもセキュリティ上の問題までは至らない、という方向に持っていくほか無いように思います。■これでも防げない攻撃はあると思います。前調べたあるWebの予約管理システムで、ユーザIDとパスワードのチェックはログイン時にしかしておらず、その上さらセッションIDもなく、GETリクエストにユーザIDを入れてユーザを識別しあとはノーチェック(だからそのGETリクエスト先に直接アクセスすればパスワード無しで他人のアカウントをのっとり放題)という、にわかには信じがたいシステムがありました。この問題自体は確かにWebアプリのフレームワークを用いれば解決できますが、この問題の本質はフレームワークを使っていない事でも、セッションIDがない事でも、ログイン時にしか認証していない事でもなく、プログラマの想像(この場合は「ログインページで認証したのだから、ユーザの個別ページには入れないはずだ」)を超えた、正規の手段(「別にログインページを通過しなくてもユーザ別のページにアクセスできる」)が実は存在した事なのだと思います。フレームワークの範疇を超えた範囲でのこういった、プログラマの想像を超えるようなセキュリティホールは無くならないだろうと感じました。これに関してはまだ解決策が見えていないというのが率直なところです。■あなたがある程度読み書きできるプログラミング言語を書いてください。(いくつでも可)手続き型でしたら、他の言語に移植する程度であれば大体読めます。ある程度頑張って読み書きした事があるのは以下でしょうか。ActiveBasicPrologBrainfuck(笑)ニワン語(現在処理系を実装中)■そのほかアピールしたいこと、書き足りないことがあれば自由に書いてください。小さいときに魔法少女アニメを見て魔法使いになりたいと思ったものの、現実世界に魔法は存在しなかったので、変わりに電脳世界の魔法使いだと思ったハッカーになりたいと思い、コンピュータを始めました(笑)。「電脳コイル」が現実になり、電脳世界と現実世界の境界が曖昧になってくれば私の最初の夢に近づいていくのに。システムプログラムとは、WindowsのDLLやLinuxのデーモン、各種デバイスドライバやカーネルモジュールなどを指します。(IPA)の主催する「プログラミング&セキュリティキャンプ2010」の「セキュリティコース/ソフトウェアセキュリティ組」への参加が決定したのでお知らせします。高校の時から参加したかったんですが受験で参加できず、大学入ってからやっとこさの参加でございます。小学校の同窓会と思いっきり被ってるんですが気にしない事にしました(キリッ結局ネットがあるし、同窓会っても本当に8年ぶりに会う人って稀なんだよなあ。ψ(プサイ)なんか、こう色々と諸方面から圧力が掛かってきたのでtwitter始めました(サイドバーにも表示してあります。面白いことはつぶやけませんのであしからず。idは”tikal”です。フォローとかはいくらでもどうぞ。ψ(プサイ)久しぶりです。7月一杯はテスト続きで遊べそうにありません...。8月は多少遊べるかと思いますが、9月の初旬にはまたテストがあります。9月の初旬のテストの後はまた一ヶ月ほど休みがあるので、その時には色々出来るかもしれません。あっ、でも免許取らないと。いえ、情報科学概論Iという講義を聴いている最中にふと思いついたセキュリティネタがあったので投稿します。調べた感じだとこの手法は見つからなかったんですが、どう考えてもたいした工夫ではないので既出かもしれません。return-to-libc攻撃とASLRまずreturn-to-libc攻撃について説明しましょう。知ってるという方は飛ばしてください。return-to-libcはバッファオーバーフロー攻撃の一種です。スタック上のバッファに、その大きさ以上のデータを書き込んでしまうことで発生します。イメージとしてはこんな感じ関数がリターンした後のスタックの構造が、ちょうどsytem関数を呼び出したときと同じように工夫するのがミソです。CPUはこの時、system(“cmd”)が実行された時と同じように振る舞い、結果任意のコマンドを実行させる事が可能になってしまいます。Vista以降では、ASLRといって、system()関数も含めた外部ライブラリに含まれる関数のアドレスを毎回ランダムにする事でこの攻撃を防いでいます。戻るべきsystem()関数のアドレスが毎回変わってしまうのですから、攻撃を成功させることも難しくなる、大変有効な対策です。†1アドレスが毎回変わらない関数しかし、毎回アドレスが絶対に変わらない関数があります。それはアプリケーション内の関数です。アプリケーション内の関数は、DLLでロードされるライブラリと違い、毎回ロード先のアドレスが変わらないようです。Starter(32ビット)で確認できた実演デモ本来はファイルの内容を表示するプログラムですが、この脆弱性によってシェルを実行するように改変されています。Starter(どちらも32ビット)で動作を確認しています。Vista(どちらも32ビット)で動作を確認しています。アップーデートで使えなくなる可能性は十分ありますので、起動しなくてもめげないでね!■スクリーンショットこんな感じでシェルが実行されます。■コードの解説まずは意図的にバッファーオーバーフローさせてるプログラムのソースコードを。);//ファイルサイズ分だけコピー。ここでオーバーフロー。0;}上のほうのexec()がポイントです。想定としては、プログラム内から他のアプリケーションを呼ぶような動作を模擬したものと考えてください。message”を表示させることなくsystem関数を呼び出し、さらにそのコマンドも”ipconfig”でなく”cmd”を実行します。....最初の40バイトはバッファにあふれない分のデータです。何かメッセージが出ないと寂しいので、文章を書き込んであります。<JMP.&msvcrt.system>"がおいてあるところへのポインタ関数が戻るまでにクラッシュしないように工夫した†2ローカル変数領域です。リターンアドレスが、exec()内でsystem関数を呼び出す直前になっています。<JMP.&msvcrt.system>”に戻ったときに使うデータです。<JMP.&msvcrt.system>”を実行すればコマンドプロンプトが実行される、というわけです。libcに限らず、実行できてはいけない処理が意図しないタイミングで実行されるこの手法を使えば、プログラム中に含まれるありとあらゆる処理が意図しないタイミングで実行し放題になると思われます。出来そうな事はこんな感じ。今回のように、アプリケーション内で呼ばれているAPI(たとえばsystem())に戻って任意のコマンドを実行するパスワードやらなにやらの認証機構で保護されている処理を無理やり呼び出すWinGrooveのコピートラップ関数を呼び出す(笑)Linuxではさらに制限が掛かるlinuxでは「PAX」によって以下のようにスタックのアドレスも毎回ランダムで変わるので、Windowsより制限が厳しくなります。スタック破壊を検出するStack-Smashing-Protectorとかでも制限が掛かるかも...。bfbc6288このように、毎回かなりランダムになる事が分かります。文字列等のポインタを扱うにはスタック上のアドレスが必要なので使えず、イミディエイトな値のみしか扱えなくなります。いえ、この辺は通常のreturn-to-libcと同じなのでいろいろと回避テクがあるかもしれません。出来そうな対策は?DLLだけでなく、アプリのロード先も毎回ランダムにするこれしかないと思います。今ちょっと確認したところ、殆どのソフトウェア内のcall/jmpはすべて相対ジャンプで行われているようですし、たぶん問題は起きないと思います。DLLでは既にそうなっていますから、特に問題は無いはず...。ちなみに、洞窟物語のパッチがうまくVista以降で動かないのもこれが原因です。それ故に...悔いの残らぬよう、やり遂げなさい。