[解決済み】FlashゲームのPHPベースのハイスコアテーブルをハッキングされないようにする最善の方法は何でしょうか?
質問
スコアの上限がなく、技のリプレイなどでサーバー上でスコアを確認することができないアクションゲームについてです。
私が本当に必要としているのは、Flash/PHPで可能な限り強力な暗号化と、Flashファイルを介して以外のPHPページを呼び出さないようにする方法です。過去に1つのスコアに対して複数の呼び出しを行い、チェックサム/フィボナッチシーケンスなどを完成させる簡単な方法を試したことがあり、またAmayeta SWF EncryptでSWFを難読化しましたが、結局すべてハッキングされました。
StackOverflowの回答のおかげで、Adobeからいくつかの詳細な情報を見つけることができました。 http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_12.html と https://github.com/mikechambers/as3corelib - で、暗号化には使えそうです。しかし、これでCheatEngineを回避できるかどうかはわからない。
AS2とAS3が違う場合、それぞれの最適な解決策を教えて欲しいです。
主な問題はTamperDataやLiveHTTPヘッダーなどのようですが、もっと高度なハッキングツールもあるようですね - CheatEngineとか(Mark Websterに感謝)。
解決方法は?
これはインターネットゲームやコンテストの典型的な問題です。あなたのFlashコードは、ゲームのスコアを決めるためにユーザーと一緒に動作します。しかし、ユーザーは信頼できないし、Flashコードはユーザーのコンピュータで実行されます。あなたは孤立無援です。攻撃者がハイスコアを偽造するのを防ぐためにできることは何もありません。
-
Flashは、バイトコードがきちんと文書化されており、高級言語(Actionscript)を記述しているので、あなたが思っている以上にリバースエンジニアリングがしやすいのです。
-
攻撃者はFlashインタプリタのランタイムメモリをコントロールするため、プログラム可能なデバッガの使い方を知っていれば、いつでもどんな変数(現在のスコアを含む)も変更でき、プログラム自体も変更することが可能です。
システムに対する最も単純な攻撃は、ゲームの HTTP トラフィックをプロキシ経由で実行し、ハイスコアの保存をキャッチし、より高いスコアでそれを再生することです。
例えば、ゲーム起動時に暗号化されたトークンをクライアントに送信するなどして、各ハイスコア保存をゲームの単一インスタンスにバインドすることで、この攻撃をブロックしようとすることができます。
hex-encoding( AES(secret-key-stored-only-on-server, timestamp, user-id, random-number))
(セッションクッキーを使っても同じ効果が得られます)。
ゲームコードは、このトークンをハイスコアの保存と一緒にサーバーにエコーバックします。しかし、攻撃者は、ゲームをもう一度起動してトークンを取得し、そのトークンをすぐにハイスコア保存のリプレイに貼り付けることができます。
そこで次に、トークンやセッションクッキーだけでなく、ハイスコアを暗号化するセッションキーも与えます。これは128ビットのAESキーで、それ自体はFlashゲームにハードコードされたキーで暗号化されています。
hex-encoding( AES(key-hardcoded-in-flash-game, random-128-bit-key))
これは、Flash バイナリに high-score-encrypting-session-key-decrypting-key がハードコードされているためです。この復号化されたキーとハイスコアのSHA1ハッシュを使用してハイスコアを暗号化します。
hex-encoding( AES(random-128-bit-key-from-above, high-score, SHA1(high-score)))
サーバー上のPHPコードは、リクエストが有効なゲームインスタンスから来たことを確認するためにトークンをチェックし、暗号化されたハイスコアを復号化し、ハイスコアのSHA1と一致することを確認します(このステップをスキップすると、復号化は単にランダムに、おそらく非常に高い、ハイスコアを生成することになります)。
攻撃者はFlashコードを逆コンパイルし、すぐにAESコードを見つけます。このコードは、たとえそうでなくても、メモリ検索とトレーサーを使えば15分で突き止められます(quot;このゲームのスコアは666だとわかっているので、メモリ内で666を見つけて、その値に触れる操作をすべてキャッチしましょう-ああ見て、ハイスコア暗号コード!")。セッションキーがあれば、攻撃者はFlashコードを実行する必要さえなく、ゲーム起動トークンとセッションキーを取得し、任意のハイスコアを送り返すことができるのです。
ほとんどの開発者が諦めてしまうような状況になっていますね。
-
XOR演算によるAES鍵のスクランブル
-
鍵のバイト配列を鍵を計算する関数に置き換える
-
偽の鍵の暗号化とハイスコアの掲示をバイナリ中にばら撒く。
これはほとんど無駄なことばかりです。言うまでもないことですが、SSLも役に立ちません。2つのSSLエンドポイントのうち1つが悪である場合、SSLはあなたを保護することはできないのです。
実際に高得点詐欺を減らすことができるものを紹介します。
-
ゲームをプレイするためにログインを要求し、ログイン時にセッションクッキーを生成させ、同じセッションで複数の未処理のゲーム起動や、同じユーザーの複数の同時セッションを許可しないようにします。
-
実際のゲームの最短時間よりも短いゲームセッションからのハイスコアを拒否する (より洗練されたアプローチとして、平均ゲーム時間よりも2標準偏差未満しか続かないゲームセッションのハイスコアを隔離してみる)。サーバーサイドでゲーム時間をトラッキングしていることを確認してください。
-
1~2回しかゲームをプレイしていないログインからのハイスコアを拒否または隔離し、攻撃者がログインするたびに妥当と思われるゲームプレイの証跡を作成しなければならないようにします。
-
ゲームプレイ中のスコアをハートビート(Heartbeat")することで、サーバーは1回のゲームプレイの間にスコアが伸びるのを確認することができます。合理的なスコア曲線に従わないハイスコアを拒否する(例えば、0から999999にジャンプする)。
-
ゲームプレイ中のゲームの状態(例えば、弾薬の量、レベル内の位置など)をスナップショットし、後で記録された中間スコアと照合することができます。このデータの異常性を検出する方法を最初から持っている必要はありません。
-
セキュリティチェックに失敗したユーザーのアカウントを無効にする(例えば、暗号化されたハイスコアを送信して検証に失敗した場合など)。
しかし、ここでは高得点の不正を抑止しているに過ぎないことを忘れないでください。そこには 何もない を防ぐことはできません。もしあなたのゲームでお金がかかっているならば、誰かがあなたが考え出したどんなシステムも破ってしまうでしょう。目的は 止める この攻撃は、ただゲームが上手くなって打ち負かすよりも、もっと高くつくようにすることです。
関連
-
[解決済み】PHP 7.2 - Warning: count(): パラメータは配列かCountableを実装したオブジェクトでなければならない [解決済み]
-
[解決済み】 PHP 未定義関数の呼び出し
-
[解決済み] SQLSTATE[HY093]: 無効なパラメータ番号: パラメータが定義されていません
-
[解決済み】mysqli_select_db()は、パラメータ1がmysqliであることを期待し、文字列が与えられる。
-
[解決済み】メッセージ。Trying to access array offset on value of type null [重複]配列のオフセットにアクセスしようとしています。
-
[解決済み] 入力ファイルが指定されていない
-
[解決済み】phpのシンタックスエラー、予期しないT_IFエラーを修正する方法は?[クローズド]。
-
[解決済み] Forbidden :このサーバーの /phpmyadmin にアクセスする権限がありません。
-
[解決済み] PHPの文字列で、シングルクオートとダブルクオートの違いは何ですか?
-
[解決済み] PHPでは@記号はどのように使うのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】XAMPPポート80をPID 4の「Unable to open process」が使用中 [重複] XAMPPポート80をPID 4の「Unable to open process」が使用中。]
-
[解決済み] PHP & MySQL: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given [重複] PHP & MySQL: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given.
-
[解決済み】PHP定数「PHP_EOL」はいつ使うの?
-
[解決済み】PHP 7.2 - Warning: count(): パラメータは配列かCountableを実装したオブジェクトでなければならない [解決済み]
-
[解決済み] SQLSTATE[HY093]: 無効なパラメータ番号: パラメータが定義されていません
-
[解決済み] 警告:mysqli_fetch_array()は、パラメータ1がmysqli_resultであることを期待する、オブジェクトはで指定された。
-
[解決済み】phpMyAdmin: シークレットパスフレーズ?
-
phpのAllowed memory size of 134217728 bytes枯渇問題の解決法
-
[解決済み] $_SERVER['DOCUMENT_ROOT'] と $_SERVER['HTTP_HOST'] の違いについて
-
[解決済み] 致命的なエラーです。mysqli_result 型のオブジェクトを使用できません [終了] 。