web-dev-qa-db-ja.com

Unityゲームデータをリモートサーバーに転送するためにmd5を置き換える方法

TL; DR

私は、クライアントで nityScript およびC#を使用し、サーバーでPHP)を使用するゲームシステムに取り組んでいます。データと共有シークレットのMD5ハッシュを使用してデータが転送中に変更されていないことを確認してください。MD5で十分ですか?3つの言語すべてで機能する他のハッシュアルゴリズムを使用できますか?

問題の詳細

人気のゲーム開発プラットフォーム nity について広く使用されているコミュニティWebサイトでいくつかのコードに遭遇しました。現在、MySQLの改善に取り組んでいますPHPおよびそのコード。

コードは、クライアントとサーバー間で共有される「秘密鍵」値を使用します。クライアントからのすべてのメッセージには、データのハッシュ(名前とスコアなど)と秘密鍵が含まれ、サーバーがデータを受け入れる前にチェックします。これは基本的に、渡されたデータが改ざんされていない認証です。

ただし、MD5であるため、ネットワークトラフィックを聞いている人は簡単に秘密鍵を見つけて、必要なデータをサーバーに投稿できます。

だから私の質問は:

  • この現在の状況は改善を急いでいますか?それとも、MD5の現在の使用目的ですか(2017年1月現在)?
  • この通信アクティビティをさらに改善/認証できる別のハッシュアルゴリズムはありますか?このアルゴリズムはPHP、UnityScript、C#で機能する必要があることに注意してください。

コード

  • UnityScript(クライアント側):

    var hash=Md5.Md5Sum(name + score + secretKey);
    
  • C#(クライアント側):

    string hash = MD5Test.Md5Sum(name + score + secretKey);
    
  • PHP(サーバー側):

    $secretKey = "mySecretKey"; // Change this value to match the value 
                                //stored in the client javascript below 
    
    $realHash = md5($_GET['name'] . $_GET['score'] . $secretKey); 
    if($realHash == $hash) {
           //interact with database 
    }
    

追加基準

  • 一部のUnityプログラマーはUnityScript(.NET APIでJavaScriptに似た構文を持つPythonに似た言語)を使用していますが、ライブラリがインストールされていると想定できません。

  • ゲーム開発者はでないPHP/MySQLプログラマーなので、複雑またはサードパーティのPHP/C#/ Jsコードはおそらく役に立たないでしょう。

  • BCryptは明らかに C#で使用するのは賢明ではありません

  • BCryptは 静的ソルト を必要とします(おそらく秘密鍵から派生したのでしょうか?)が、ランダムなソルトで動作することを目的としています。

  • PBKDF2はBCryptよりも優先されるようですが、特にメモリが少ないモバイルデバイスでは 非常に遅い になる可能性があります。

  • セキュリティで保護されたサーバーを処理することは期待できません(場合のみ...)。

  • C#セキュリティライブラリ について十分に理解していないので、リストされているものから最適なオプションを実際に選びます。

  • 概説されたコードは単にハイスコアの更新を行うためのものですが、このコードは過去に存在しており、将来的にはさまざまなデータベースへのパブリックおよびプライベートのあらゆる種類のデータの転送に使用されます。

  • PHP、UnityScript、C#間のハッシュアルゴリズムの相互運用性を処理することは、私が予想していたよりも大きなハードルです。それがだった場合PHPを使用しますpassword_hash

この質問のいくつかの考えと背景:

編集したタイトルがMD5を変更するかどうかわからなかったように思われるので、タイトルを更新しましたが、MD5を変更する必要があることを知っていることが、最初にここで質問する主な理由の1つでした。

元の質問は、クライアントマシンのゲームとリモートサーバーのデータストレージの間のやり取りを処理する方法について、(他の場所の中で) ここ に示されているひどいコードの提案を更新したかったということでした。これは、Unityの初心者プログラマー向けのコード提案であり、このサイトはUnity Technologies自身によって運営されています。
見てみると、元の質問(上記にリンク)はPHP Mysql_関数(およびPDOのかなりひどい無効な形式と同様)。これは書き直しのメリットがあると感じました。元のコードもmd5ルーチンを使用して目的のデータをハッシュしていたことがわかりました。 MD5の置き換えに関しては、コンパイルされたプロジェクトファイルの脆弱性や、このコードブロックを実際に安全にするために必要な作業のサイズ/規模(サーバーまたはクライアント側とのやり取りのいずれか)を理解していませんでしたデータ)。私の最初の探求は、不足していることを知っていたので、必要なさまざまな言語(UnityScript、C#、PHP)で動作するMD5の代わりに適したドロップを見つけることでした。私は(ここのコメントから判断して)実際にexeに侵入してハードコードされたデータを取得するのがどれほど退屈なほど簡単であるかを理解していませんでした。

この質問は[〜#〜]ではありません[〜#〜]私が作っているゲームについてですではありません私のプロジェクトについて、そして私が置き換えるつもりであると引用されているコードは私によって書かれていませんでした。どういうわけか人々がメッセンジャーに挑戦しているというコメントの多くを読みましたが、この質問は、教育用WikiのWebサイトの既存の欠点を改善したいという私自身の願いから生まれました。私はこの質問に答えることで共有された知識に最大の敬意を払っていますが、Unityのドキュメントと学習サイトを調査した過去6か月から、ローカルアプリケーションとマルチプレーヤーまたはその他のリモートインタラクションの両方のセキュリティ保護に大きなギャップがあることを認識しています。

ジョージからの回答は悪い回答だとコメントに多くの回答者がいますが、それは当時私が尋ねた特定の質問に対する回答です。ありがとう。

最後の注意:
このBlobの投稿 Luke Briggsのコメントから、ローカルのUnityゲームアプリケーションデータを操作することは非常に簡単なプロセスであることが強調されました。脆弱なローカルファイルがどのようにどのように理解していないか.

49
Martin

編集:明確にするために、私はあなたのアプローチの安全性について話すことはできません。ハッシュの部分のみです。ここには、あなたのアプローチを思いとどまらせる強いコメントがあります。 (つまり、適切なハッシュは、適切なドア/フレームまたは薄いドア/フレームのいずれかで適切なロックを使用できるのと同じように、安全なアプローチまたは安全でないアプローチの一部である可能性があります)

あなたのTL; DRに応じて、SHA-2がドロップイン置換ハッシュ関数として推奨されていることは間違いありません。

長さが問題になる場合は、MD5よりも切り捨てられたSHA-2を使用することをお勧めします。

SHA-2には、224、256、384、512の4つのサイズがあります。 256と512が最も一般的です。

これは汎用(高速)ハッシュであり、パスワードの保存には適していませんが、TL; DRが示唆するように、データの整合性を保証するのに適しています。

BCryptはスローパスワードハッシュであり、一種の片方向暗号化が必要な場合に使用されます。 (つまり、パスワードは決して保存されず、そのハッシュのみであり、ブルートフォースすることが困難です)

27
Bryan Field

このアプローチには根本的な欠陥があります。クライアント側のあらゆるものがプレイヤーによって改ざんされる可能性があります。これは、DRMを使用不能にするのと同じ問題です。ユーザーは、マシンとその上のすべてのデータ(実行可能ファイル、メモリ内のデータなど)を所有します。アルゴリズムを秘密に保つことは機能しません( Kerckhoffsの原理)を参照 )コードが何をしているかを理解するために必要なリバースエンジニアリング作業はほんのわずかです。

たとえば、ゲームクライアントに、レベルスコアをサーバーに送信するルーチンがあるとします。ネットワーク経由で改ざんされないように、何らかの形式の暗号を使用します。これを回避する方法はたくさんあります:

  • Cheat Engineなどのメモリ編集ツールを使用して、現在のスコアをスキャンし(一時停止、スコアの検索、一時停止を解除、スコアが変更されるまで待機し、再度検索し、値を含むメモリアドレスが見つかるまで繰り返します)、それを編集します。レベルが完了すると、スコア値はコードによって正当なものとして適切に扱われ、サーバーにアップロードされます。
  • 「レベル完了」コードが実際のスコア値を無視して別の値を選択するように、ディスク上のゲーム実行可能ファイルを変更します。
  • ディスク上のゲームの実行可能ファイルを変更して、単純なこと(たとえば、1人のモンスターを殺すこと)でスコアを本来の1000倍に増やします。
  • ディスク上のゲームの実行可能ファイルを変更して、決して死なないようにしたり、パワーアップを無限にしたり、1ヒットでキルしたり、その他多くの助けとなるようにして、非常に高いスコアを簡単に達成できるようにします。
  • ゲームのロード後にこれらの変更をメモリ内で実行して、元の実行可能ファイルがそのまま残るようにします(不快な整合性チェックがある場合に役立ちます)。
  • 「レベルを終了しました。スコアをアップロードしてください」というコードをプロセスの外部に公開するだけで、誰でもプログラムから呼び出すことができます。ネイティブコードでは、小さなスタブを挿入して、エクスポートテーブルにエントリを追加するか、コードを独自の実行可能ファイルに直接コピーできます。 .NETでは、クラスとメソッドの可視性フラグを変更し、それを新しいプログラムにインポートするだけです。これで、ゲームを実行することなく、好きなスコア値を送信できます。
  • ゲームをリバースエンジニアリングして「秘密」の鍵を手に入れ、独自のアプリを作成してスコア値をサーバーに送信します。

これは氷山の一角にすぎません。より複雑なゲームでは、アンチチートやその他の問題に対するあらゆる種類の回避策がありますが、使用される防御策に関係なく、常にクライアント側の値をいじくる方法があります。

安全なアプローチの重要な機能は、プレーヤーのコンピュータ上の何も信頼されないことです。サーバーコードがプレーヤーからパケットを受信したら、ゲームが実行されていない可能性があると想定します。これは、すべてについて嘘をついている完全に自作のコードである可能性があります。

マルチプレイヤーゲーム(またはゲームの状態を確認する必要があるあらゆる種類のゲーム)を保護するのは簡単ではありません。問題は、実際にはセキュリティの問題ではなく、使いやすさとパフォーマンスの問題です。マルチプレーヤーゲームを保護する最も簡単な方法は、サーバー側でゲーム全体の状態を保持し、そこですべてのゲームロジックを実行および維持し、クライアントにプレーヤー入力をサーバーに送信させるだけです(「ユーザーがマウスをクリックした」 、ユーザーはWキーを押し続けます」)、オーディオとビデオをプレーヤーに返します。これを行うことの問題は、ネットワークのレイテンシが原因で非常に楽しいゲームにならないことであり、サーバー側でのスケーリングが非常に困難です。代わりに、クライアント側とサーバー側のバランスを取る必要があります。たとえば、「プレイヤーはこのドアを開ける鍵を持っていますか?」というロジックです。サーバー側でチェックする必要がありますが、「ドアを開ける」ためのコンテキストアイコンをいつ表示するかのロジックはクライアント側に残ります。繰り返しになりますが、敵の健康状態や位置などはサーバー側で維持する必要があり、その敵にダメージを与えるプレイヤーの能力も確認する必要があります(十分に近いかどうか)。つまり、AIをクライアント側で維持することはできません。しかし、敵が表示しているアイドルアニメーションの選択のようなものは、おそらくクライアント側のものになります。

ここではゲームのセキュリティについていくつか質問がありますので、それらを一読することをお勧めします。

また、GameDev SEで次の質問もお勧めします。

また、BlackHat EU 2013の マルチプレイヤーセキュリティに関する優れた論文非権威のP2Pネットワーキングに関する記事 もあり、どちらも役立つかもしれません。

202
Polynomial

ここには3つの問題があります。

  • あなたがしようとしていることは、多項式の答えで説明されているように、いくつかの点で根本的に誤っています。

  • とにかくそれを主張するなら、あなたは正しいプリミティブさえ使用していません!メッセージの認証には、ハッシュではなく [〜#〜] mac [〜#〜] が必要です。ハッシュからMACを構築することは可能です-これは [〜#〜] hmac [〜#〜] が行うことです-しかし、見た目ほど簡単ではありません。貼り付けたコードが行っていることは、ハッシュから単純にMACを構築しようとしていることであり、これらの種類の単純な構造は通常壊れています。

  • また、ええMD5は悪いハッシュ関数です。しかし、これは本当にあなたの心配の最小です... MD5はこのデザインの弱点ではありません。窓の上のバーを2インチの厚さのスチールメッキに置き換える方法についてアドバイスを求めていますが、正面ドアは大きく開いています。これを「より良いセキュリティ」であると正当化しても意味がありません。

40

私の友人はかつてフラッシュゲームを作成し(そうだとすればそれはかなり前のことです)、同じスキームmd5(authenticated data + secret key)を使用してから、サーバーで検証しました。

私はそれをいくつかのツールでリバースエンジニアリングし、彼が使用していた秘密の値を約30分で見つけました。ゲームオーバー。

しかし、ええ、それは2番目に良いオプションです。 md5の代わりにsha2を使用するかどうかに関係なく、またハッシュアルゴリズムの代わりにhmacを使用するかどうかに関係なく、ユーザー入力は決して信頼されません。ユーザーが自分のマシンでゲームを実行し(つまり、自分の制御下にある場合)、ハイスコアを送信できる場合、ユーザーは常にツールを使用してスコアを向上させることができます。

あなたができる最善のことは、リプレイ(たとえば、記録されたキープレス)をアップロードしてサーバーで再実行し、結果の時間を検証することです。これはコーディングするのに多くの作業であり、より多くのサーバーリソースを必要とし、フロートをどこかで使用する場合は決定論的な物理学が必要になります...彼らがカンニングしたい場合はゲーム。

11
Luc