6

Riyad Kalla によるこの非常に優れたブログ投稿の一部に従って、プロジェクト用の単純な RESTful API を作成しました。現在、Stack Overflow で同様の質問を何十も読んでいますが、セキュリティに関する質問に対する答えが見つからないようです。

簡単に言うと、私のリクエストは次のようになります。

  1. クライアントには公開 API キーがあります (平文で、ネットワーク トラフィックを傍受したり、コード ソースを適切にチェックしたりする人なら誰でもアクセスできます)。
  2. クライアントは公開 API キーを使用してサーバーにリクエストを送信します
  3. サーバーには秘密の API キーがあります (開発者以外には秘密です)
  4. サーバーは、クライアントのリクエスト データとシークレット API キーで構成される HMAC-SHA1 ハッシュを作成します。
  5. サーバーは、クライアントのリクエストと同じリクエストをAPIサーバーに送信しますが、結果のHMAC-SHA1が含まれます
  6. API サーバーは、受信した公開 API キーに基づいて、データベース内の秘密 API キーを検索します。
  7. API サーバーは、開発者のサーバーと同じデータを使用して HMAC-SHA1 ハッシュを再作成します。
  8. ハッシュが一致する場合、リクエストは有効であると見なされ、正常に処理されます

私のサービスを使用している誰かが公開 API キーを取得し (たとえば、ネットワーク トラフィックをスニッフィングすることによって)、クライアントが AJAX を使用してブラウザー経由で開発者のサーバーに直接行うのと同じ要求を単純に cURL することができるのではないかと心配しています。したがって、悪意のあるユーザーは正当なユーザーとして認証され、他の誰かの秘密 API キーを使用して API にアクセスする可能性があります。

具体例を挙げてみます。通常、私は次のようにします:

  1. 私のサーバーへのAJAX取得リクエスト。
  2. サーバーは、API シークレットを使用してリクエストをハッシュし、API サーバーに送信します。
  3. API サーバーはリクエストを検証し、ペイロードを返します。

しかし、私はそれが怖いです:

  1. Dr. Evil が私の公開 API キーを盗聴します。
  2. Dr. Evil は、公開 API キーを使用してサーバーへの get リクエストを cURL で送信します。
  3. 私のサーバーは Dr. Evil のリクエストを私の API シークレットでハッシュし、それを API サーバーに送信します。
  4. API サーバーはペイロードを検証して返し、Dr. Evil の悪質な計画を完了します。
  5. Dr. Evil は邪悪な笑い声を上げます。

不足しているものはありますか、それとも RESTful API ゲームの一部ですか?

更新: 私は任意の形式のタイムスタンプ検証を自発的に省略して、物事をシンプルに保ち、認証の問題だけに集中しています。

$_SERVER['HTTP_REFERER']更新 2:プロセスに検証を追加しました。ここでの目標は、クライアントがリクエストとともにリファラーを送信する必要があり、API 側のデータベースにリストされているリファラーと一致する必要があることです。残念ながら、HTTP リファラーは簡単に偽装できます。これはもう 1 つのレベルのセキュリティですが、まだ完全ではありません。

更新 3: サーバー側のコードを変更して、リファラーをリモート IP アドレスに設定しました。これにより、秘密の API キーを使用してハッシュする必要があるサーバーに送信されるすべての要求が、最終的に元の要求 IP アドレスで API サーバーに到達するようになります。その後、この IP を検証して、要求を通過させることができます。偽造することはまだ可能だと思います$_SERVER['REMOTE_ADDR']が、偽造するよりも複雑$_SERVER['HTTP_REFERER']です...まだ完全ではないと思います。

更新 4 : これらの投稿によると: $_SERVER['REMOTE_ADDR'] 変数を偽造するには? およびhttps://serverfault.com/questions/90725/are-ip-addresses-trivial-to-forge、偽造は$_SERVER['REMOTE_ADDR']困難ですが可能です。ただし、偽造されたネットワークを制御できないため、偽造されたリクエストから応答を受け取ることは不可能です。リクエストは正常に検証されますが、そのレスポンスが悪意のある手に渡ることはありません。

4

2 に答える 2

5

HMAC を使用することで、正しい軌道に乗っています。ただし、アプリケーションをより安全にする 2 つの追加事項があります。

  1. クライアント POST にタイムスタンプが必要です。サーバー時間の 5 分以内に検証する必要があります。また、HMAC 生成に含める必要があります。誰かがこれを変更しようとすると、HMAC 署名を更新するための秘密鍵を持っていない限り、HMAC 署名は無効になります。
  2. SSL を使用し、証明書を検証します。中間者攻撃を防ぎます。SSL 以外のリクエストを許可しないでください。
于 2013-01-14T19:07:16.297 に答える
0

他のスクリプトが公開 API キーを使用してサーバー側の HMAC ハッシュ スクリプトにリクエストを送信するのを防ぐために私が見つけた解決策は、元のリクエスターのIDをリクエストと共に送信することです。偽造するのは難しいため、元の要求者の身元を特定するために使用$_SERVER['REMOTE_ADDR']しています。偽造すると、通常、応答が得られなくなります。

/* $this as a class that handles requests */

// Build hash and include timestamp
$this->vars['timestamp'] = time();
$this->vars['hash'] = hash_hmac('sha1', http_build_query($this->vars).$this->vars['token'], API_SECRET);

// Send request to API
curl_setopt_array($this->curl, array(
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_URL => $url,
    CURLOPT_POST => $this->method == 'post' ? 1 : NULL,
    CURLOPT_POSTFIELDS => $this->method == 'post' ? $this->vars : NULL,
    CURLOPT_CONNECTTIMEOUT => 15,
    CURLOPT_TIMEOUT => 15,
    CURLOPT_REFERER => $_SERVER['REMOTE_ADDR'], // Referer here!
    CURLOPT_MAXREDIRS => 3,
    CURLOPT_HTTPGET => $this->method == 'get' ? true : false
));

送信されると、API はデータベースからシークレット API キーをチェックするだけでなく、$_SERVER['HTTP_REFERER']許可されているかどうかもチェックします! これにより、API はユーザーごとにサーバーを受け入れることもできます。

于 2013-01-16T17:06:50.293 に答える