どうも、開発2部でサーバ担当してる山本です。
今回はスマホゲームを運営される方であれば誰もが悩んだことがあるであろう「チート対策」(不正対策)についての記事です。
チートを放っておけば、ゲーム内の価値観やバランスが崩壊し、「ユーザー離脱」や「売り上げ低下」に繋がりかねません。
一般的なチートの種類やその対策についての知識を身につけ、より良いサービスを目指しましょう!
当記事は特定サービスにおける対策に関したものではなく、一般的なチート対策についてまとめた内容となっています。
チート行為を助長する意図はありませんので具体的な内容やツールについてはふれず、概要のみを記載していますのでご了承くださいm(_ _)m
今回扱うチート対策は以下の通りです。
- 送信パケットの改ざん
- 受信パケットの改ざん
- メモリの改ざん
- ローカルデータの改ざん
- bot
送信パケットの改ざん
クライアントからサーバーに向けて送信するパケットを改ざんし、実際のプレイ内容を改変してサーバーに送るチート行為です。
これはパラメータの妥当性チェック(特にサーバー側)によりある程度防げます。
妥当性は仕様変更による影響を大いに受けるので、仕様変更の際に見落とさないよう影響調査はしっかりおこないましょう!!
例えば「最上位レアリティのSSRキャラクターは進化しない」という妥当性チェックは、SSRの上位にURのレアリティを追加したタイミングで修正を行う必要があります。
以前は妥当でなかった仕様が妥当になったり、その逆であったり、影響調査の漏れによりチートをしていない人が影響を受ける可能性があります。
パケットの改ざんにはハッシュによる改ざん検知も有効な手段です。
クライアントから送信するパケットの内容からサーバーと予め摺り合わせたロジックでハッシュを生成し、サーバー側でパケットを受け取った際には「サーバーで受け取ったパケットから生成したハッシュ」と「クライアントから送られたハッシュ」が一致することにより改ざんを検知するといった形です。
<?php // ヘッダに設定されたハッシュを取得 $header_array = http_get_request_headers(); $receive_hash = $header_array['app-hash']; // 受け取ったパラメータからハッシュを生成 $param = 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER['REQUEST_URI']; $genarate_hash = md5($param); // ハッシュに差異があれば改ざんされたということ if ($genarate_hash != $receive_hash) { echo '改ざん検知!'; }
上記の例ではURLのクエリ文字列をそのままmd5でハッシュ化していますが、実際に導入する際にはソルトをつけるなど工夫をしないと、攻撃者にすぐに見破られ、改ざん検知として機能しなくなるので注意が必要です。
ハッシュによる改ざん検知は、改ざんを検知するのみで攻撃者がパケットの中を確認することはできます。
パケットの中を見られたくない場合は暗号化が有効です。
暗号化と復号化は以下のコードで試すことができます。
<?php $plain_data = 'hogehoge'; $method = 'AES-128-ECB'; $key = 'foobar'; echo $plain_data . PHP_EOL; // 暗号化 $encrypted_data = openssl_encrypt($plain_data, $method, $key); echo $encrypted_data . PHP_EOL; // 復号化 $decrypted_data = openssl_decrypt($encrypted_data, $method, $key); echo $decrypted_data . PHP_EOL;
上記はサンプルですので、実際に導入する場合は$methodの選定や$keyを毎回変えるなどの工夫を行った方がよいです。
単純なkeyの場合は総当たりにより短時間で特定されてしまいます。
この一手間をサービス独自のロジックで実装することで攻撃者が復号化するハードルは格段にあがります。
複雑なロジックになるほどセキュリティは強固になりますが、暗号化、復号化の負荷もあがるので導入する際には処理時間のオーバーヘッドやリソース状況を考慮に入れることも忘れてはいけません。
受信パケットの改ざん
サーバーからクライアントに向けて送信するパケットを改ざんし、改変したステータスなどでゲームをプレイするチート行為です。
受信パケットの改ざんも送信パケットの改ざんと同様の対策が有効ですが、妥当性チェックは仕様変更(バージョンアップ)の影響を多いに受けるので、クライアント側での妥当性チェックはバリデーション程度に留めたほうがよいと思います。
先ほどの例で例えるとSSRが最高レアリティという妥当性チェックをクライアントで実装すると、その上のレアリティを追加したときに妥当性チェックを変更する必要があります。
アプリのバージョンアップの審査の手間やバージョンの混在を考えると、アプリ側での妥当性チェックは簡易な内容にとどめた方がよいです。
メモリの改ざん
メモリに展開されたパラメータをのぞき見たり、改ざんするチート行為です。
攻撃者にパラメータが見つかりにくいよう暗号化したり、クリティカルなパラメータに対してはハッシュによる改ざんチェックを行うことが有効です。
また、androidであればroot化、iOSであれば脱獄を必要とするかと思いますので、該当する端末であればアプリ自体を起動しないようにするのもよいと思います。
ローカルデータの改ざん
端末内に保存されているデータを改ざんするチート行為です。
データ構造がばれてエディタまで開発されてしまうと攻撃のハードルが下がり、チートが蔓延する危険性があります。
これについても受信パケットの改ざんと同様の対策が有効となります。
bot(ボット)
ゲームプレイをツール等により自動化するチート行為です。
botにはアクセス頻度が一定閾値を超えた場合にペナルティを課す対策が考えられますが、攻撃者は閾値を調べてそれを下回る頻度で自動化してくるでしょう。
送信パケットの改ざんと併せて、自動化できる環境(端末)で起動しないようにするのが有効です。
botは完全に防ぎきるのが難しいため、ログの監査、アカウント停止、不正報告機能などにより、不正検知や対処の体制、ポリシーを整えることが大切です。
いかがでしたでしょうか。
チート対策はいたちごっこで完全な対策はありませんが、対策を講じることで攻撃を妨げることはできます。
この内容がチート対策に苦労される開発者の一助になればと思います。
ここまでいくつかのチート対策について書きましたが、チート対策に注力しすぎてサービス側が疎かになっては本末転倒です。
ユーザーとサービス提供者がWin-Winな関係を目指し、バランスのよいサービスを目指しましょう!!
ではでは。