web-dev-qa-db-ja.com

APIシークレットをプレーンテキストで保存したり、復号化したりしても問題ありませんか?

API keysはユーザー名と見なされておらず、API secretsはパスワードと見なされていませんか?アマゾンウェブサービスのようなAPIサーバーでAPIシークレットをプレーンテキストで表示できるのはなぜですか?それは私が彼らにそれをプレーンテキストで、または少なくとも解読可能なフォーマットで保存していると思います。

APIシークレットがパスワードとして扱われ、プレーンテキストで渡されるのではなく、データベースに作成して入力するために入力する必要がある場合は、より良いでしょうか。何らかの理由でAPIシークレットデータベースが危険にさらされた場合、APIを使用している多くのアプリケーションのフラッドゲートが簡単に開かれます。ただし、復号化できない方法でハッシュされた場合、すべてが簡単に失われることはありません。

36
IMB

いいえ。APIキーはクリアテキストで保存する必要があります。

これらはパスワードではなく、暗号化キーです。これらのキーは、リクエストの認証(SHA1-HMACを使用)などに使用されます。サーバーは、暗号アルゴリズムを適用するための暗号鍵を知っている必要があります。

したがって、APIキーはサーバーにクリアテキストで保存する必要があります。サーバーがAPIキーのハッシュのみを保存している場合、サーバーはクライアントからのメッセージの信頼性を検証できなかったか、クライアントに送信されたメッセージを認証できませんでした。

17
D.W.

ハッシュはストレージではありません。データを不可逆的に破壊します。 「パスワードストレージ」としてのパスワードハッシュの呼び出しを回避できます。なぜなら、実際にパスワードが必要なときに、それを入力するのに便利な人間のオペレーターがいるからです。実際、パスワードをハッシュするときは、パスワードではなくトークンのみを保存します。入力したパスワードを確認するのに十分です。

APIキーは、無人で再び使用できるように保存する必要があります。 APIにアクセスするには正規のキーが必要なため、サーバーは実際にstoreを実行する必要があります。ゴーストを覚えるだけではありません。

13
Tom Leek

APIトークンをハッシュする方が安全ですが、使いやすさの問題があります。トークンは長くランダムであり、ハッシュする前に一度だけユーザーに通知する必要があります。これはハッシュでそれらを保護することを少し難しくします。

安全なシナリオに対する私の提案は次のとおりです。

  1. ランダムなsalt値を生成し、データベースに保存します。このソルトは、ユーザーのパスワードソルトと同じであってはなりません。
  2. ユーザーの平文パスワードを取り、KDF(password, salt)を計算します。ここで、KDFはbcryptなどの鍵導出関数です。結果の値kを呼び出します。
  3. APIキーを生成します。
  4. kをキーとして使用して、AESでAPIキー値を暗号化し、暗号文をデータベースに保存します。
  5. プレーンテキストAPIキーとkを破棄します。

ユーザーがログインすると、ウェブアプリは自分のパスワードを認識し、それを使用してkを計算します。これは、APIキーを復号化して表示するために使用されます。

ユーザーがAPIを使用する場合、SSL経由でkとプレーンテキストAPIキーを送信する必要があります。次に、webappはkを使用して保存されているAPIキー値を復号化し、指定されたAPIキーと比較できます。それらが一致する場合、それは有効です。これにより、アプリがユーザーのパスワードを保存する必要なく、APIキーを使用できます。

攻撃者がデータベースに違反した場合、kを計算するためにユーザーのパスワードを解読する必要があります。

9
Polynomial

ここと その他の場所 には少し混乱があるようですので、他のユーザーの状況が明確になることを期待してこの回答を追加します。

使用される可能性のあるAPIシークレットには2つのタイプがあります。

このページのほとんどの回答で説明されている使用例は、HMACなどのアルゴリズムを使用してメッセージに署名し、検証するために使用される秘密鍵です。この場合、メッセージの署名を作成するには、クライアントとAPIの両方にキーの実際の値が必要です。次に、サーバーは、生成した署名とクライアントが送信した署名を比較し、メッセージを検証できます。上記のように、元のキーがサーバーで再現できない場合、これは機能しません。 (暗号化されたチャネルを介して)最初にクライアントと鍵を共有した後は、鍵をクライアントとサーバー間で再度送信する必要はありません。

他の一般的なAPIクライアントシークレットは、単なるシークレット認証情報です(一般的なOAuth2アクセストークンリクエストで確認できます)。この資格情報は要求ごとに送信されるため、暗号化されたチャネル(HTTPSなど)を介してのみ送信する必要があります。この場合、サーバーは、クライアントから提供されたシークレット値が正しいことを確認するのに十分な情報を保持するだけでよいので、シークレットをハッシュできます。この場合、シークレットは事実上パスワードとして機能しているため、同じ予防策を講じる必要があります。

免責事項:私はセキュリティリサーチャーではありません。このStackExchangeに関するアドバイスを盲目的に実行する前に、これとすべてのテーマについて徹底的に調査する必要があります。

tl; dr最も重要なことは、異なるAPIが異なる方法でシークレットを使用する可能性があることです。 APIがクライアントシークレットを使用する方法を理解して、それを保存するためのベストプラクティスを評価することが重要です。

8
Nick Sloan

まだ言及されていない問題のために、自分の2セントを投入する。特に、@ NickSloanの発言には同意しますが、もう1つ注意点があります。

APIキーとパスワードの間にはもう1つの重要な違いがあります。 APIキーはサイトに固有です。パスワードのセキュリティを非常に重要にする部分は、パスワードの共有です。ユーザーがサイトに保存したパスワードを誰かが手に入れたら、侵害されているのはサイトだけではありません。ユーザーがそのパスワード(および電子メール/ユーザー名)を使用したのは他のすべてのサイトです。重要なサイト(銀行、ソーシャルメディア、電子メールなど)全体でパスワードを再利用する人が多いため、優れたパスワードセキュリティは、他のサイトのユーザーを保護することと同じくらい、サイトへのアクセスを保護することではありません。ユーザーがセキュリティを強化するように強制することはできないため、ユーザーが自分のプライバシーを保護するために、最悪の事態を想定し、追加の手順を実行する必要があります。

APIキーはサイトに固有であるため、完全に異なるシナリオです。その結果、それが盗まれた場合、攻撃者はあなたのサイトにアクセスできますが、その人の銀行/電子メールなどに対して攻撃できるものは何も得られません。つまり、APIキーのリスクレベルは実際にはパスワードのリスクレベルよりも低くなります。 APIは、パスワードよりもセッションIDに似ています。

これらがパスワードよりもセッションIDに似ていることを理解すると、そのようなキーを適切に保護する方法についての実用的な洞察が得られます。以下の説明は、OAuth資格情報などのAPIキーに適用でき、暗号化資格情報ではありません(@NickSloanの回答で説明))。

パスワードに対する最大の脅威はフィッシング攻撃とデータベースのハッキングです。そのため、パスワードをハッシュ化してデータベースに保存しています。 APIキーに対する最大の脅威はセッションキーの場合と同じです。XSSの脆弱性、MIMなどのフロントエンドアプリケーションの弱点です。フロントエンドアプリケーションは暗号化されていない形式のパスワードを必要とするため、APIキーをハッシュしても、盗まれる可能性が最も高い人物がプレーンテキストでそれを必要とする場合、実際には何も得られないことに注意することが重要です。

代わりに、主にクライアントを追跡することにより、セッション識別子(またはOAuthトークン、またはクライアント固有のAPIキー)を保護します。セッション識別子がクライアントからXSSまたはその他の手段を介して盗まれた場合、典型的な結果は、攻撃者が新しいデバイスでその識別子を使用することです。つまり、突然、古いユーザーキーが新しいユーザーエージェントで表示されるようになります。このような変更は、簡単に検出して修正できます。すべてのAPIキーをただちに無効にします。特にOAuthリクエストの場合、これはユーザーにとって非常に簡単です。キーを盗んだだけのユーザーが再びログインしてすぐに新しいキーを取得します。 (パスワードがありません)は、設計図に戻っています。

これは、より賢いハッカーが盗まれたキーに関連付けられたユーザーエージェントを記録し、今後のすべてのリクエストでそれを使用しようとする一般的な十分な防御手段ですが、同じユーザーがリクエストを送信しているときに、何か怪しいことが起こっていることを簡単に確認できます複数のIPアドレスから。世界の他のすべてのものと同様に、これは猫とマウスのゲームの一部になる可能性がありますが、いくつか重要なポイントがあります。

  1. APIキー/ OAuthトークン/セッションIDは、実際には特定のデバイスのユーザーを覚えておくための方法にすぎないため、すべてのページにパスワードを入力する必要はありません。その結果、疑わしい場合は、許可されたすべてのキーを強制終了して、ユーザーに強制的に再度ログインさせることができます。
  2. 3つのケースすべてで、キー/トークン/ IDを失うとアカウントが侵害されるため、これらのことに関してアクティブなセキュリティを確保し、怪しいことが発生した場合に検出/応答することが重要です。メキシコからあなたのアカウントにログインしようとしている誰かについてfacebook/google/etcから通知を受け取ったことがある場合、それはどこかのセキュリティ担当者が自分の仕事を正しく行っているためです。
  3. キー/トークン/ IDの主な攻撃経路は、パスワードの攻撃経路とは異なります。それでもデータベースでハッシュ化したい場合があります(ここでも、プレーンテキストである必要がある暗号化資格情報については触れていません)が、データベースでハッシュ化して安全に呼び出すことはできません。まったく新しい範囲の攻撃経路に対してそれらを確実に保護する必要があります。それらをパスワードとしてのみ考えると、全体像の重要な部分を逃してしまいます。
5
Conor Mancone

パスワードを保存する前にハッシュ化する主な理由の1つは、攻撃者がデータベースへの読み取り専用アクセスを取得するのを防ぐためです。このようにして、攻撃者がログイン資格情報リストを手に入れても、パスワードがハッシュ化/塩漬けされているため、攻撃者はそれらを直接使用することはできません。

そして、これは私たちがここで解決しようとしている理論上の問題だけではなく、これらのタイプの攻撃は実際に起こります業界 )、そして適切なハッシュは攻撃の影響を軽減するのに役立ちます。

APIシークレットを使用してユーザー認証を許可している場合、APIシークレットは事実上パスワードになっていますしたがって、セキュリティの観点から、ユーザーは同じ通常のパスワードと同じ保護メカニズム。

Amazon自体 APIシークレットを取得することはできません 。それを忘れた場合は、新しいものを要求する必要があります。

2
Pedro Rodrigues

いいえ、それはある種のサービスでは大丈夫ではありません。

実装

1。ユーザーがログインパスワードを使用して接続するときに、ユーザーのパスワードから派生したキーを生成して、このユーザーのデータを暗号化し、サーバー上のセッションに保持します。

このようにして、各ユーザーは一意のキーを持ちます。この派生キーはリバーシブルであってはなりません。これが主なポイントです。これは、sashやマスターキーでhash_macなどのハッシュ方式を使用することで可能になります。

2。このキーを使用して、ユーザーごとにランダムなivでAES 256を使用し、生成されたAPIシークレットを暗号化します。

または

2.bisこのキーを使用して、最後の瞬間に実際の暗号化キーを生成し、2。と同じ方法でAPIメソッドを暗号化して、メモリ内のフローティングパスワードを回避します。

ユーザーIDとアプリIDとともに専用のテーブルにデータベースにivを保存します

4。暗号化されたAPIシークレットをデータベースの適切なテーブルに保存します。

使用方法

ユーザーが自分のコントロールパネルに接続すると、キーを再作成し、ivをフェッチし、このユーザーのAPIシークレットを解読して、クリアテキストで表示できます。また、キーを表示し、API呼び出しを行うときに両方を要求して、アプリの秘密を確認できるようにします。

キーの表示を避け、API呼び出しでそれを要求する必要がない場合は、認証にもログインと同じ方法を使用できます。つまり、別のテーブルを作成して、クライアントアプリごとにランダムなキー/塩を格納し、APIシークレットのhash_macバージョンを格納できます。したがって、APIリクエストを認証するには、API IDとAPIシークレットのみが必要です。しかし、それはより多くの仕事です。

これは、@ Polynomialの回答と実質的に同じです。

この方法では、サーバーとデータベースをハッキングしている誰かがユーザーの資格情報を盗み、ユーザーに代わってapiを呼び出すのは非常に困難です。これで、APIクライアントからのリクエストが受け入れられた場合、それが適切なクライアントであるか、または漏洩であるかを評価できます。

ユーザーがパスワードを紛失した場合は、新しいパスワードから新しいAPIシークレットとキーを再生成します。

0
Nicolas Manzini