「リリースしてから入れては駄目ですか」— たいていは大丈夫です、5つを除いて
リリースを2週間後に控えたチームにセキュリティの話を持ち出すと、返ってくる答えはだいたいこうです。「いまはコンテンツの詰めが優先で。出してから反応を見て入れます」
妥当な判断です。実際、ほとんどのセキュリティ機能は後から足せます。検知モジュールを有効にすること、ログを集めること、ポリシーを締めること。どれもライブ運営中にできます。
問題は、そうではないものも混ざっていることです。いくつかの決定はビルドを提出した時点で固まってしまい、後から変えるにはリリースし直すか、プレイヤーのデータに手を入れることになります。急ぐべきはコンテンツで正しい。ただしこの5つは、いま30分確認しておけば後で数週間を節約します。
この記事は何を導入するか選ぶための記事ではありません。いま決めておかないと後で高くつくものだけを扱います。チーム規模に応じて何から導入するかは、インディー・小規模開発者向けのセキュリティ導入ガイドで別に扱いました。
1. スクリプティングバックエンド — Mono で出したなら戻しにくい
Unity のスクリプティングバックエンドは、ビルド成果物の構造そのものを変えます。Mono でビルドすると C# コードはマネージドアセンブリとして残り、デコンパイラで開けます。IL2CPP はネイティブバイナリへ変換します。
変えること自体は設定ひとつですが、リリース後に変えるとそこからが問題です。ビルド時間と成果物のサイズが変わり、ネイティブプラグインやリフレクション、シリアライズのあたりでこれまでなかった問題が出てきます。ライブ運営中にこれを検証する余裕のあるチームは多くありません。
IL2CPP が万能だという話ではありません。メタデータが残るため、復元ツールでかなりの部分を戻せます。詳しくはIL2CPP は本当に安全かにまとめました。ここで言いたいのはひとつです。どちらを使うかはリリース前に決め、その状態で検証まで終えておくほうがよいということです。
2. 署名とパッケージ整合性 — 後から触るとインストール基盤が揺れる
アプリの署名はセキュリティ設定というよりアイデンティティに近いものです。署名が変わればストアと端末から見て別のアプリになります。
Android は Play アプリ署名を使えば鍵の更新経路がありますが、手続きは重く、すでにインストールしたユーザーに影響が及びうるものです。リリース前に確認しておくのはこのくらいです。
- 署名鍵をどこに保管し、誰がアクセスできるかが決まっている。
- ビルドパイプラインが毎回同じ鍵で署名している。
- パッケージが改ざんされたかを判断する基準がビルドに入っている。
三つ目が特に後から足しにくいところです。リパッケージされたビルドを見分けるには、正規のビルドがどういう状態であるべきかを知る必要があり、その基準はビルド時点で作られます。リパッケージ攻撃の流れはUnity MOD APK 対策ガイドで扱いました。
3. サーバーが最終判定する値の境界 — 最も遅く直すぶん、最も高くつく
5つのうち後から変えるのが最も難しい項目です。絡んでいるのがコードではなくデータ構造とプレイヤーの記録だからです。
リリース前に答えておくとよい問いはこれです。「この値が操作されたら、他のプレイヤーや売上に影響が及ぶか」
及ぶのであれば、その値の最終判定はサーバーにあるべきです。通貨の残高、課金の付与可否、ランキングのスコアといったものです。クライアントが計算してサーバーへ通知する構造で出してしまうと、後からサーバー判定へ移すときに、すでに積み上がった記録をどう扱うかから決めることになります。操作された値と正常な値を事後に見分けられない場合が少なくありません。
すべてサーバーへ移せという意味ではありません。シングルコンテンツの演出値までサーバーが判定する理由はありません。どこに線を引くかをリリース前に決めておくという意味です。 セーブデータ側の事例はゲームのセーブファイル改ざんにあります。
4. ビルドに残るもの — 提出前に一度は開いてみる
開発中には必要でも、リリースビルドに残ると困るものがあります。たいていは分かっていながら、締め切りに追われて見落とします。
- 開発・ステージングのサーバーアドレスがビルドに残っていない。
- テストアカウント、チートコマンド、デバッグメニューへの入口が取り除かれている。
- デバッグシンボルと詳細ログがリリース設定に合わせて整理されている。
- 使っていない開発用ライブラリがパッケージに含まれていない。
- サーバーの API キーや秘密の値がクライアントに入っていない。
最後の項目だけ性質が違います。前の4つは片付ければ終わりですが、クライアントに入れた秘密の値はすでに漏れたものとして扱うべきです。ビルドはユーザーの端末にあり、その中の文字列は結局読まれます。見つけたなら必要なのは削除ではなく差し替えです。
5. 検知したあとに何をするか — ポリシーがないとライブ中に決めることになる
検知を有効にすることと、検知の結果で何かをすることは別の仕事です。そして後者はリリース前に決めておかないと、実際に事が起きた深夜に決めることになります。
決めておくのは三つです。
- 何をするか — 記録だけ残すか、警告するか、遮断するか。項目ごとに違ってかまいません。
- 誤検知が出たらどうするか — 正常なプレイヤーが引っかかったときに戻す経路があるか。
- 誰が判断するか — 自動処理の範囲と人が確認する範囲の境界。
誤検知への戻し経路がない状態で遮断を有効にするのが、実務では最も危ういやり方です。正常なプレイヤーを数人誤って止めれば、その損害はチーターを数人取り逃がすより大きくなります。最初は記録だけ残し、データが溜まってから強度を上げる順序が安全です。
導入の方式そのものを検討中なら、自社開発と商用SDKの比較が参考になります。
提出前の最終点検
先の5つをまとめて確認できるように並べました。
ビルド設定
- スクリプティングバックエンドを確定し、その設定で QA を終えた。
- 署名鍵の保管場所とアクセス権限が決まっている。
- パッケージ改ざんを判別する基準がビルドに含まれている。
構造
- 操作されると他のプレイヤーや売上に影響する値の最終判定がサーバーにある。
- クライアントが判定する値とサーバーが判定する値の境界が文書に残っている。
ビルドの残留物
- 開発サーバーのアドレス、テストアカウント、デバッグの入口が取り除かれている。
- クライアントに秘密の値が入っていない。入っていたなら差し替えた。
運用の準備
- 検知項目ごとに何をするかが決まっている。
- 誤検知を戻す経路がある。
- 初期は記録中心で始めることに合意している。
OZero Security を検討中であれば
この記事の5つのうち、私たちがお手伝いできるのは1・2の一部と5です。Check Setup が IL2CPP でないプロジェクトを知らせ、Android の署名証明書と manifest 署名を確認します。検知後の対応(ログ・コールバック・終了)は Response Settings で決めます。3・4はゲーム設計とサーバー、リリース手順の担当であり、私たちが代われるものではありません。
導入の負担についてだけ付け加えると、パッケージをインポートすると(Asset Store 購入分は Package Manager の My Assets、カスタマーポータルからのダウンロード分は .unitypackage)Welcome ウィンドウが開きます。Check Setup がプロジェクトに残っている設定を示し、Auto Setup が推奨設定を一段階ずつ確認しながら適用し、モジュールは Project Settings > OZero Security で設定します。シーンを直したりゲームロジックを変えたりする必要はありません。リリース直前に検討される場合でも、1番や2番より負担は小さいはずです。
ただし順序は守っていただくほうがよいでしょう。スクリプティングバックエンドと署名の体系が先に決まってこそ、その上での整合性検証が意味を持ちます。
結論:後からできることと、できないことを分ける
リリース前のセキュリティ点検を「セキュリティをどれだけ備えたか」で捉えると切りがありません。完全な状態でリリースするチームはありません。
代わりにこう分けてみてください。後から足せるものと、いま決めるべきもの。この記事の5つが後者です。残りはリリースして反応を見てから足しても遅くありません。