81

私はウェブサイトを運営していますが、ゲームをプレイした回数に応じてポイントを獲得できるスコアリングシステムがあります。

ハッシュを使用してスコアリングのhttpリクエストの整合性を証明し、ユーザーが何も変更できないようにしますが、私が恐れていたように、誰かがそれを変更する必要がないことを理解し、ハイスコアを取得して複製する必要がありましたhttpリクエスト、ヘッダー、その他すべて。

以前は、この攻撃の可能性が低いと考えられていたため、この攻撃から保護することは禁止されていました。しかし、それが起こったので、私はできます。httpリクエストはフラッシュゲームから発信され、phpによって検証され、phpがデータベースに入力します。

ノンスが問題を解決することはかなり確信していますが、それらを実装する方法は正確にはわかりません。ノンスシステムをセットアップするための一般的で安全な方法は何ですか?

4

5 に答える 5

63

それは実際には非常に簡単です...あなたのためにそれを行うためにそこにいくつかのライブラリがあります:

  1. PHPノンスライブラリ
  2. OpenIDノンスライブラリ

または、自分で書きたい場合は、非常に簡単です。ウィキペディアのページを出発点として使用する、擬似コード:

サーバー側では、2つのクライアント呼び出し可能関数が必要です

getNonce() {
    $id = Identify Request //(either by username, session, or something)
    $nonce = hash('sha512', makeRandomString());
    storeNonce($id, $nonce);
    return $nonce to client;
}

verifyNonce($data, $cnonce, $hash) {
    $id = Identify Request
    $nonce = getNonce($id);  // Fetch the nonce from the last request
    removeNonce($id, $nonce); //Remove the nonce from being used again!
    $testHash = hash('sha512',$nonce . $cnonce . $data);
    return $testHash == $hash;
}

そしてクライアント側では:

sendData($data) {
    $nonce = getNonceFromServer();
    $cnonce = hash('sha512', makeRandomString());
    $hash = hash('sha512', $nonce . $cnonce . $data);
    $args = array('data' => $data, 'cnonce' => $cnonce, 'hash' => $hash);
    sendDataToClient($args);
}

この関数makeRandomStringは、実際には乱数または文字列を返す必要があります。ランダム性が優れているほど、セキュリティも向上します...また、ハッシュ関数に直接フィードされるため、実装の詳細はリクエストごとに重要ではないことに注意してください。クライアントのバージョンとサーバーのバージョンが一致している必要はありません。実際、100%一致する必要がある唯一のビットは、で使用されるハッシュ関数hash('sha512', $nonce . $cnonce . $data);です...これは適度に安全な関数の例makeRandomStringです...

function makeRandomString($bits = 256) {
    $bytes = ceil($bits / 8);
    $return = '';
    for ($i = 0; $i < $bytes; $i++) {
        $return .= chr(mt_rand(0, 255));
    }
    return $return;
}
于 2010-11-10T15:07:18.577 に答える
31

ノンスはワームの缶です。

いいえ、実際、いくつかのCAESARエントリの動機の1つは、ナンスの再利用に耐性のある、できればストリーム暗号に基づく認証済み暗号化スキームを設計することでした。(たとえば、AES-CTRでナンスを再利用すると、プログラミングの1年生がメッセージを解読できる程度にメッセージの機密性が失われます。)

ノンスの3つの主要な考え方があります。

  1. 対称鍵暗号の場合:再利用しないように注意しながら、増加するカウンターを使用します。(これは、送信者と受信者に別々のカウンターを使用することも意味します。)これには、ステートフルプログラミングが必要です(つまり、各要求がで開始されないようにナンスをどこかに格納し1ます)。
  2. ステートフルランダムナンス。ランダムなナンスを生成し、後で検証するためにそれを記憶します。これは、CSRF攻撃を打ち負かすために使用される戦略であり、ここで求められているものに近いように聞こえます。
  3. 大きなステートレスランダムナンス。安全な乱数ジェネレーターがあれば、生涯でナンスを2回繰り返さないことをほぼ保証できます。これは、 NaClが暗号化に使用する戦略です。

したがって、それを念頭に置いて、尋ねるべき主な質問は次のとおりです。

  1. 上記の考え方のうち、あなたが解決しようとしている問題に最も関連しているのはどれですか?
  2. どのようにナンスを生成していますか?
  3. ノンスをどのように検証していますか?

ノンスの生成

ランダムナンスの質問2に対する答えは、CSPRNGを使用することです。PHPプロジェクトの場合、これは次のいずれかを意味します。

  • random_bytes()PHP7以降のプロジェクトの場合
  • paragonie / random_compat、PHP5ポリフィルrandom_bytes()
  • ircmaxell / RandomLibは、ランダム性を扱うほとんどのプロジェクト(firパスワードのリセットなど)が独自のロールではなく使用を検討する必要があるランダム性ユーティリティのスイスアーミーナイフです。

これら2つは道徳的に同等です:

$factory = new RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator();
$_SESSION['nonce'] [] = $generator->generate(32);

$_SESSION['nonce'] []= random_bytes(32);

ノンスの検証

ステートフル

ステートフルナンスは簡単で推奨されます:

$found = array_search($nonce, $_SESSION['nonces']);
if (!$found) {
    throw new Exception("Nonce not found! Handle this or the app crashes");
}
// Yay, now delete it.
unset($_SESSION['nonce'][$found]);

array_search()をデータベースやmemcachedルックアップなどに置き換えてください。

ステートレス(ここではドラゴン)

これは解決するのが難しい問題です。リプレイ攻撃を防ぐための何らかの方法が必要ですが、サーバーには各HTTPリクエストの後に完全な記憶喪失があります。

唯一の正しい解決策は、リプレイ攻撃の有用性を最小限に抑えるために有効期限の日時を認証することです。例えば:

// Generating a message bearing a nonce
$nonce = random_bytes(32);
$expires = new DateTime('now')
    ->add(new DateInterval('PT01H'));
$message = json_encode([
    'nonce' => base64_encode($nonce),
    'expires' => $expires->format('Y-m-d\TH:i:s')
]);
$publishThis = base64_encode(
    hash_hmac('sha256', $message, $authenticationKey, true) . $message
);

// Validating a message and retrieving the nonce
$decoded = base64_decode($input);
if ($decoded === false) {
    throw new Exception("Encoding error");
}
$mac = mb_substr($decoded, 0, 32, '8bit'); // stored
$message = mb_substr($decoded, 32, null, '8bit');
$calc = hash_hmac('sha256', $message, $authenticationKey, true); // calcuated
if (!hash_equals($calc, $mac)) {
    throw new Exception("Invalid MAC");
}
$message = json_decode($message);
$currTime = new DateTime('NOW');
$expireTime = new DateTime($message->expires);
if ($currTime > $expireTime) {
    throw new Exception("Expired token");
}
$nonce = $message->nonce; // Valid (for one hour)

注意深い観察者は、これが基本的にJSONWebトークンの非標準準拠のバリアントであることに気付くでしょう。

于 2016-03-01T05:08:33.563 に答える
2

1つのオプション(コメントで述べました)は、ゲームプレイを記録し、安全な環境で再生することです。

もう1つは、ランダムに、または特定の時間に、一見無害に見えるデータを記録し、後でサーバーで検証するために使用できるようにすることです(突然、ライブが1%から100%になる、または1から1000のスコアで、チートを示します)。 )。十分なデータがあれば、詐欺師がそれを偽造しようとするのは現実的ではないかもしれません。そしてもちろん、重い禁止を実装します:)。

于 2010-11-10T14:45:27.180 に答える
1

この非常に単純なナンスは1000秒(16分)ごとに変更され、同じアプリケーションとの間でデータを投稿するXSSを回避するために使用できます。(たとえば、JavaScriptを介してデータを投稿しているシングルページアプリケーションを使用している場合。投稿側と受信側から同じシードおよびナンスジェネレーターにアクセスできる必要があることに注意してください)

function makeNonce($seed,$i=0){
    $timestamp = time();
    $q=-3; 
    //The epoch time stamp is truncated by $q chars, 
    //making the algorthim to change evry 1000 seconds
    //using q=-4; will give 10000 seconds= 2 hours 46 minutes usable time

    $TimeReduced=substr($timestamp,0,$q)-$i; 

    //the $seed is a constant string added to the string before hashing.    
    $string=$seed.$TimeReduced;
    $hash=hash('sha1', $string, false);
    return  $hash;
}   

ただし、前のナンスをチェックすることにより、ユーザーは、最悪の場合は16.6分以上、最良の場合は33分以上待機した場合にのみ気になります。$ q = -4を設定すると、ユーザーは少なくとも2.7時間かかります

function checkNonce($nonce,$seed){
//Note that the previous nonce is also checked giving  between 
// useful interval $t: 1*$qInterval < $t < 2* $qInterval where qInterval is the time deterimined by $q: 
//$q=-2: 100 seconds, $q=-3 1000 seconds, $q=-4 10000 seconds, etc.
    if($nonce==$this->makeNonce($seed,0)||$nonce==$this->makeNonce($seed,1))     {
         //handle data here
         return true;
     } else {
         //reject nonce code   
         return false;
     }
}

$ seedは、プロセスで使用される任意の関数呼び出しやユーザー名などです。

于 2019-03-09T17:18:48.173 に答える
0

不正行為を防ぐことはできません。あなたはそれをもっと難しくすることができるだけです。

誰かがPHPノンスライブラリを探してここに来た場合:ircmaxwellによって提供された最初のライブラリを使用しないことをお勧めします。

Webサイトの最初のコメントは、設計上の欠陥について説明しています。

ナンスは、特定の1つの時間枠に適しています。つまり、ユーザーがその時間枠の最後に近づくほど、フォームを送信する時間が短くなり、場合によっては1秒未満になります。

明確に定義されたライフタイムを持つノンスを生成する方法を探している場合は、NonceUtil-PHPを参照してください。

免責事項:私はNonceUtil-PHPの作者です

于 2013-04-29T11:33:27.123 に答える