ゲーム開発におけるセキュリティのベスト プラクティス
この記事では、ゲーム開発で使用するベスト プラクティスについて説明します。
はじめに
オンラインゲームやユーザー作成コンテンツを使ったゲームをプレイする人が増えています。 これと、Microsoft Windows オペレーティング システムのセキュリティ強化が相まって、ゲームは攻撃者にとってますます魅力的な標的となりつつあります。 ゲーム開発者は、リリースするゲームが攻撃者に悪用されるような新たなセキュリティホールを生み出さないようにすることに重点を置く必要があります。 ゲーム開発者は、顧客のコンピュータが悪意のあるネットワーク データ、ユーザーによる変更、または改ざんによってハッキングされるのを防ぐ責任と利害関係を持っています。 脆弱性が悪用されると、顧客や金銭を失う可能性があります。 この記事では、開発時間を過度に増やすことなくコードのセキュリティを強化するための一般的な方法とツールの概要と説明を示します。
製品をリリースする際に開発チームが犯す最も一般的な 3 つの間違いは次のとおりです。
- 管理者権限が必要です。 ゲームには管理者権限は必要ありません。 詳細については、 ゲーム開発者向けのユーザー アカウント制御を参照してください。
- 自動保護を使用していません。 開発者は通常、 /GS、 /SAFESEH、または /NXを使用していません。 これらのコンパイル/リンク フラグを使用すると、作業負荷を大幅に増加させることなく、多くの基本的なセキュリティ ホールを発見または排除できます。 これらのフラグについては、この記事の後半で説明します。
- 禁止されている API の使用。 プログラマーのエラーが発生しやすく、セキュリティホールが発生しやすい API (strcpy、strncpyなど) が多数あります。 開発者はこれらの API を安全なバージョンに置き換える必要があります。 Visual Studio 2005 には、オブジェクト ファイル内の安全でない API への参照を自動的にチェックできるバイナリ ファイルを分析するツールが付属しています。 このツールで生成された情報をどのように処理するかについての詳細は、Martyn Lovell 著の Repel Attacks on Your Code with the Visual Studio 2005 Safe C and C++ Libraries を参照してください。 また、コードから禁止された関数を削除するのに役立つ
banned.h
ヘッダー ファイルを入手することもできます (Microsoft の無料セキュリティ ツール - banned.h を参照)。
リストされている間違いはどれもよくある間違いであるだけでなく、開発の作業負荷、コーディング標準、または機能に大きな変化を与えることなく簡単に修正できます。
安全でないコードの例
以下は、攻撃者がバッファ オーバーラン攻撃を実行するために必要なすべての簡単な例です。
void GetPlayerName(char *pDatafromNet)
{
char playername[256];
strncpy(playername, pDatafromNet, strlen(pDatafromNet));
// ...
}
表面的には、このコードは問題ないように見えます。結局のところ、安全な関数を呼び出しているのです。 ネットワークからのデータは 256 バイトのバッファにコピーされます。 strncpy 関数は、ソース文字列内の NULL 終端文字の検索に依存するか、指定されたバッファ カウントによって制限されます。 問題はバッファサイズが正しくないことです。 ネットワークからのデータが検証されていない場合、またはバッファ サイズが間違っている場合 (この例のように)、攻撃者は単に大きなバッファを用意して、バッファの終了後にネットワーク パケット内の任意のデータでスタック データを上書きすることができます。 これにより、攻撃者は命令ポインタを上書きし、戻りアドレスを変更することで任意のコードを実行できるようになります。 この例の最も基本的な教訓は、検証されるまで入力を決して信頼しないことです。
たとえデータが最初にネットワークから来なかったとしても、潜在的なリスクは存在します。 現代のゲーム開発では、多くの人が同じコードベースを設計、開発、テストする必要があります。 将来この関数がどのように呼び出されるかを知る方法はありません。 データがどこから来たのか、攻撃者は何を制御できるのかを常に自問してください。 ネットワークベースの攻撃は最も一般的ですが、セキュリティホールを作成する唯一の方法ではありません。 攻撃者がセキュリティホールを開くような方法で MOD を作成したり、保存されたファイルを編集したりする可能性がありますか? ユーザーが提供する画像ファイルやサウンドファイルについてはどうでしょうか? これらのファイルの悪意のあるバージョンがインターネットに投稿され、顧客に危険なセキュリティ リスクをもたらす可能性があります。
ちなみに、例を修正するには、 strncpy の代わりに strsafe.h または Safe CRT を使用してください。 Safe CRT は、C ランタイムのセキュリティを完全に見直したもので、Visual Studio 2005 の一部に付属しています。 Safe CRT の詳細については、Michael Howard 著の Security Enhancements in the CRT を参照してください。
セキュリティを向上させる方法
開発サイクルでセキュリティを向上させる方法はいくつかあります。 以下に、最良の方法をいくつか示します。
-
セキュリティについて読む
-
Michael Howard と David LeBlanc による著書 Writing Secure Code, Second Edition では、攻撃を防ぎ、エクスプロイトを軽減するための戦略と方法について詳細かつ明確に説明しています。 本書では、リリースにセキュリティを組み込む方法からネットワーク アプリケーションを保護するテクニックまで、ゲーム開発者が自分自身、製品、顧客を攻撃者から保護するために必要なすべての側面を網羅しています。 この本は、開発スタジオにセキュリティ文化を浸透させるために使用できます。 コード セキュリティを開発者やテスターの問題としてだけ考えないでください。 セキュリティは、プログラム マネージャーからデザイナー、開発者、テスターまで、チーム全体がプロジェクトに取り組むときに考慮すべき事項であると考えてください。 レビュー プロセスに参加する人の数が増えるほど、リリース前にセキュリティ ホールを発見できる可能性が高くなります。
『Writing Secure Code, Second Edition』 は Microsoft Press Store で入手できます。また、より一般的なセキュリティ情報については、Michael Howard 著の 『Fending Off Future Attacks by Reducing Attack Surface』 に記載されています。
Michael Howard、David LeBlanc、John Viega は、このテーマについて、すべての一般的なオペレーティング システムとプログラミング言語を網羅した「ソフトウェア セキュリティの 19 の致命的な罪」という別の本を執筆しました。
ゲームに焦点を当てたセキュリティ プレゼンテーションは、 Microsoft XNA Developer Presentations ダウンロード ページにあります。
-
脅威モデル分析
-
脅威モデル分析は、特定の言語やツールを使用するのではなく、数回の会議で実行できる広範なエンドツーエンドの方法でシステム セキュリティを評価する優れた方法です。 スレッド モデルが適切に実装されると、プロジェクトに多大な作業負荷や会議時間を追加することなく、システムの長所と短所をすべて特定できます。 脅威モデリングの方法では、開発プロセスの前と開発プロセス中にシステム セキュリティを評価するという考え方にも重点が置かれており、最もリスクの高い機能に焦点を当てながら包括的な評価が行われるようにするのに役立ちます。 これはセキュリティのためのプロファイラーと考えることができます。 脅威モデリングは、特定の言語に基づいたり、特定のツールに依存したりしないため、あらゆるジャンルのあらゆるプロジェクトに取り組むあらゆる開発スタジオで使用できます。 脅威モデリングは、セキュリティは他人の問題ではなく全員の責任であるという考えを強化する優れた方法でもあります。
脅威モデルを作成するときは、次の点に特に注意してください。
- UDP データ ソース
- 認証を必要としないデータソース
- 広範囲の情報収集の一環として頻繁に調査されるデータソース
- クライアントが他のクライアントにデータを直接送信する機能
これらはセキュリティ上の弱点となる可能性が高い領域です。
脅威モデリングの詳細については、 脅威モデリング および Frank Swiderski と Window Snyder の共著である書籍 脅威モデリング を参照してください。
-
データ実行防止 (/NX)
-
複数のエクスプロイトを軽減する最近のツールは、データ実行防止 (DEP) です。 ビルド コマンドにスイッチ /NX を含めると、Visual Studio は、コードに実行権限があるかどうかを示すフラグを使用してメモリ ページにマークを付けます。 EXECUTE 権限が付与されていないメモリ ページでプログラムを実行しようとすると、プログラムが強制終了します。 この防止はプロセッサ レベルで強制され、自己変更コードまたはネイティブ JIT 言語コンパイラを使用している開発者に影響を与えます。 現在、実行防止をサポートしているのは AMD の Athlon64 および Opteron プロセッサと、Intel の Itanium および最新の Pentium 4 プロセッサのみですが、将来的にはすべての 32 ビットおよび 64 ビット プロセッサが実行防止をサポートする予定です。 (開発者が使用するコピー防止スキームは実行防止の影響を受ける可能性がありますが、Microsoft はコピー防止ベンダーと協力して影響を最小限に抑えるよう取り組んでいます。) DEP を使用することをお勧めします。
DEP の詳細については、 データ実行防止を参照してください。
-
バッファ セキュリティ チェック (/GS) とイメージに安全な例外ハンドラ (/SAFESEH) がある
-
コンパイラ フラグ /GS で指定されるバッファー セキュリティ チェック、およびリンカー フラグ /SAFESEH (Visual Studio .NET 2003 で最初に実装) で指定される イメージには安全な例外ハンドラーがあります により、開発者がコードを保護する作業が少し簡単になります。
/GS フラグを使用すると、コンパイラは、関数の戻りアドレスを上書きするために悪用される可能性のある、スタックベースのバッファ オーバーランのいくつかの形式をチェックするようになります。 >/GS を使用すると、すべての潜在的なバッファ オーバーランが検出されるわけではなく、万能とは言えませんが、優れた多層防御テクノロジと言えます。
/SAFESEH フラグを使用すると、実行可能ファイルまたは DLL の安全な例外ハンドラのテーブルも生成できる場合にのみ、実行可能ファイルまたは DLL を生成するようにリンカーに指示します。 Safe Structured Exception Handling (SafeSEH) は、例外がディスパッチされる前に、例外ハンドラーがイメージ ファイル内にある関数テーブルに登録されるようにすることで、例外処理がバッファ オーバーラン攻撃の標的になることを排除します。 これらの保護の利点は、Windows XP SP2、Windows Server 2003、Windows Vista、および Windows 7 で有効になります。 また、 /SAFESEH が適切に機能するためには、オールオアナッシング方式で使用する必要があります。 実行可能ファイルまたは DLL にバインドされたコードを含むすべてのライブラリは、 /SAFESEH を使用してコンパイルする必要があります。そうしないと、テーブルは生成されません。
詳細については、 バッファセキュリティチェック(/GS)およびイメージには安全な例外ハンドラがあります(/SAFESEH)を参照してください。
Microsoft Visual Studio 2012 の /SDL フラグ と Visual Studio 2012 の /GS フラグの強化 に関する情報も参照してください。
-
PREfast
-
PREfast は、コンパイルされた C または C++ の実行パスを分析して実行時のバグを見つけるのに役立つ、Microsoft が提供する無料のツールです。 PREfast は、すべての関数のすべての実行パスを処理し、各パスに問題がないか評価することによって動作します。 もともとドライバーやその他のカーネル コードの開発に使用されていたこのツールは、見つけにくいバグやコンパイラによって無視されるバグを排除することで、ゲーム開発者の時間を節約するのに役立ちます。 PREfast を使用することは、作業負荷を軽減し、開発チームとテスト チームの両方の取り組みを集中させる優れた方法です。 PREfast は、Visual Studio Team Suite および Visual Studio Team Edition for Software Developers でコード分析として利用でき、コンパイラ スイッチ /analyze によって有効になります。 (このオプションは、Windows ソフトウェア開発キットに同梱されているコンパイラの無料バージョンでも利用できます。)
Note
Visual Studio 2012 はすべてのエディションで /analyze をサポートしています。 Visual Studio のすべてのエディションでのコード分析の可用性の詳細については、「コード分析の新機能」を参照してください。
ヘッダー注釈 (特にバッファー ポインター引数) を使用することで、PREfast は、メモリ上書きバグ、クラッシュの一般的な原因、潜在的なセキュリティ脆弱性などの追加の問題を明らかにすることができます。 これは、標準注釈言語 (SAL) を使用して行われます。これは、C/C++ 関数プロトタイプのマークアップの一種で、予想されるポインター引数のセマンティクスや、長さパラメーター、宣言されたバッファー サイズなどとの相関関係に関する追加情報を提供します。Windows オペレーティング システムのすべてのヘッダーには注釈が付けられており、独自のライブラリのパブリック API ヘッダーに SAL マークアップを追加すると、PREfast はそのような API のクライアント コードでより詳細かつ積極的なチェックを実行できるようになります。 SAL の概要と詳細情報へのリンクについては、Michael Howard のブログ記事「標準注釈言語 (SAL) の簡単な紹介」を参照してください。
-
Windows アプリケーション検証ツール
-
Windows アプリケーション検証ツール (AppVerifier) は、1 つのツールで複数の機能を提供することで、テスターの作業を支援できます。 AppVerifier は、一般的なプログラミング エラーをよりテストしやすくするために開発されたツールです。 AppVerifier は、API 呼び出しに渡されるパラメータをチェックし、誤った入力を挿入してエラー処理能力をチェックし、レジストリとファイル システムへの変更をログに記録できます。 AppVerifier は、ヒープ内のバッファ オーバーランを検出し、アクセス制御リスト (ACL) が適切に定義されていることを確認し、ソケット API の安全な使用を強制することもできます。 AppVerifier は網羅的ではありませんが、開発スタジオが高品質の製品をリリースするのに役立つテスターのツールボックスの 1 つのツールになります。
Application Verifier の詳細については、「Application Verifier」および「ソフトウェア開発ライフサイクル内での Application Verifier の使用」を参照してください。
-
ファジー テスト
-
ファズ テスト は、現在のテスト方法を強化できる半自動テスト方法です。 ファズ テストの中心的な考え方は、ランダム データを入力してすべての入力を完全に評価し、何が壊れるかを確認することです。これには、すべてのネットワーク データ、mod、保存されたゲームなどが含まれます。ファズ テストは非常に簡単に実行できます。 ランダムなバイトを挿入したり、隣接するバイトを反転したり、数値を反転したりすることで、整形式のファイルまたはネットワーク データを変更するだけです。 0xff、0xffff、0xffffffff、0x00、0x0000、0x00000000、0x80000000 は、ファズ テスト中にセキュリティ ホールを明らかにするのに適した値です。 AppVerifier を使用して、結果として生じる相互作用の組み合わせを観察できます。 ファジングは網羅的ではありませんが、実装と自動化が容易であり、より捉えにくい予測不可能なバグを検出できます。
ファズ テストの詳細については、 Gamefest 2007 のプレゼンテーション「ゲーム セキュリティの実践的な手順」を参照してください。
-
Authenticode 署名
-
Authenticode は、ユーザーが受け取る実行可能ファイル、DLL ファイル、および Windows インストーラー パッケージ (.msi ファイル) が開発者がリリースしたものから変更されていないことを確認する方法です。 Authenticode は、暗号化の原則、信頼できるエンティティ、業界標準を組み合わせて使用することで、実行可能コンテンツの整合性を検証します。 Microsoft は、署名されたコードの改ざんを自動検出するために使用できる暗号化 API、CryptoAPI を提供しています。 リリース後にセキュリティ漏洩が発生した場合、証明書は取り消され、その証明書で署名されたすべてのコードの認証が停止されます。 証明書を取り消すと、その証明書で署名されたすべてのタイトルの検証が取り消されます。 Windows は Authenticode 署名と連携するように設計されており、特定の状況では、ユーザーの PC が攻撃にさらされる可能性がある未署名のコードについてユーザーに警告します。
Authenticode は、セキュリティの問題を排除する方法ではなく、実行可能ファイルがリリースされた後に改ざんを検出する方法と見なす必要があります。 悪用可能なセキュリティ問題を含む実行可能ファイルまたは DLL は、Authenticode を使用して署名および検証できますが、それでも新しいシステムにセキュリティ問題が導入されます。 製品またはアップデートが安全であることが検証された後にのみ、コードに署名して、改ざんされていないリリースであることをユーザーに保証する必要があります。
開発者が自分のリリースが変更される恐れがないと感じたとしても、他のテクノロジーやサービスは Authenticode に依存しています。 コード署名は簡単に統合および自動化できるため、開発者がリリースに署名しない理由はありません。
Authenticode 署名の詳細については、「ゲーム開発者向けの Authenticode 署名」を参照してください。
-
権限を最小限に抑える
-
一般に、プロセスは動作に必要な最小限の権限セットで実行する必要があります。 Windows Vista および Windows 7 では、 ユーザー アカウント制御を使用してこれを実現し、ゲームを管理者ではなく標準ユーザーとして実行できるようにします。 Windows XP の場合、通常、ゲームは常に管理者として実行されます。 Windows Vista および Windows 7 でも、特定の操作を行うには完全な管理者権限に昇格する必要がある場合があります。
プロセスが完全な管理者権限で実行されている場合、通常、実際に必要な権限は標準ユーザーの権限を超えるいくつかの権限だけです。 管理アクセスには、正当なコードでは必要とされないが、プロセスの何らかの弱点を通じて攻撃者によって使用される可能性がある多くの権限が含まれます。 このような権限の例としては、SE_TAKE_OWNERSHIP、SE_DEBUG、SE_CREATE_TOKEN、SE_ASSIGNPRIMARYTOKEN、SE_TCB、SE_SECURITY、SE_LOAD_DRIVER、SE_SYSTEMTIME、SE_BACKUP、SE_RESTORE、SE_SHUTDOWN、SE_AUDIT などがあります (「権限定数」を参照)。
プロセスは一度開始するとそれ以上の権限を取得することはできませんが、権限を簡単に放棄することはできます。 起動時に、プロセスは Win32 API を使用して、必要のない権限をすぐに削除できます。
-
Windowsのセキュリティ機能を活用する
-
Windows Vista および Windows 7 には、コードのセキュリティを強化する多くの新機能が含まれています。 ユーザー アカウント制御 は確かに理解して受け入れるべき最も重要な機能ですが、他にも機能があります。 Windows Vista および Windows 7 でも利用可能な Windows ファイアウォール、データ実行防止、バッファー セキュリティ チェック、安全な例外ハンドラーなどの Windows XP SP2 テクノロジに加えて、考慮すべき 3 つの新しいセキュリティ機能があります。
- オプトイン アドレス空間レイアウトのランダム化機能。 これは、Visual Studio 2005 Service Pack 1 または Visual Studio 2008 でオプション /DYNAMICBASE とリンクすることで有効になります。 これにより、システムはプロセス空間内の主要なシステム DLL の多くをランダム化するため、インターネット上で広く伝播する悪用可能な攻撃プログラムを作成することがはるかに困難になります。 このリンカー フラグは、Windows XP およびそれ以前のバージョンの Windows では無視されます。
- ヒープ破損は、さまざまなセキュリティ上の脆弱性につながる可能性があるため、Windows Vista および Windows 7 のメモリ システムでは、ヒープ破損が検出されるとプロセスを終了するモードがサポートされるようになりました。 HeapSetInformation を HeapEnableTermianteOnCorruption とともに呼び出すと、この動作が有効になります。 この呼び出しは、Windows XP およびそれ以前のバージョンの Windows では失敗します。
- サービスを作成するときに、実際に必要な権限を指定したり、リソース アクセスを特定の SID に制限したりする新しい機能を使用してサービスを構成できます。 これは、SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO と SERVICE_CONFIG_SERVICE_SID_INFO を使用して、ChangeSeviceConfig2を通じて行われます。
まとめ
現在および将来の市場向けにゲームを開発するには、コストと時間がかかります。 セキュリティ上の問題のあるゲームをリリースすると、最終的に適切に修正するためにさらに多くの費用と時間がかかります。 したがって、リリース前にセキュリティ上の脆弱性を軽減するためのツールとテクニックを統合することは、すべてのゲーム開発者の利益になります。
この記事の情報は、開発スタジオが自分自身と顧客を支援するために何ができるかについての紹介にすぎません。 一般的なセキュリティ プラクティスとセキュリティ情報の詳細については、 Microsoft セキュリティ デベロッパー センター を参照してください。