web-dev-qa-db-ja.com

REST APIを保護するにはどうすればよいですか?

詳細はここに問題があります:

私はAndroidアプリを構築しています。これは、バックエンドでREST AP​​Iを使用します。まず、登録およびログインAPIを作成する必要があります。しばらくGoogleで検索してみたところ、私にできるアプローチは2つしかないと感じました。

  • 登録時にhttpsを使用してユーザーの資格情報を取得します。ユーザー名(サーバー側)に対してデータベースに保存します。ログイン中にもhttpsを使用して、ユーザーの資格情報を尋ねます。 DBでハッシュされたパスワードを確認し、セッションIDを返します。セッションIDは、ログアウトしない限り期限切れにしないことを計画しています。さらに、ユーザーが行うその他のAPI呼び出し(GET/POST)には、このセッションIDが伴うため、ユーザーを確認できます。

しかし、上記のアプローチでは、API呼び出しにhttpsを使用せざるを得ません。それ以外の場合は、 m Man in The Middle Attack に対して脆弱です。つまり、誰かが私のセッションIDを盗聴した場合、彼は私が望まない同様のGET/POSTリクエストを再構築できます。 上記の仮定でよろしいですか?

  • 2番目のオプションは、公開キー/秘密キー認証を使用する Amazon Web Services のパスに従うことです。ユーザーが登録するとき、私はhttpsAPIを使用して彼/彼女の資格情報をDBに保存します。それ以降は、ユーザーのハッシュ化されたパスワードを秘密鍵として使用します。ユーザーが行うその他のAPI呼び出しでは、ユーザーの秘密キーを使用して、リクエストURLのハッシュされたblobが作成されます。サーバー側では、保存した秘密鍵を使用してハッシュを再構築します。ハッシュが一致する場合、ユーザーにタスクを実行させ、それ以外の場合は拒否します。このオプションでは、登録APIに対してのみhttpsを使用する必要があります。 RESTはhttpで続行できます。

しかし、ここでの欠点は、別の仮想ディレクトリで自分の登録APIをホストする必要があることです(私はIISを使用しており、httpとhttpsの両方のAPIをホストできるかどうかわかりません同じ仮想ディレクトリ)。したがって、別のプロジェクトファイルでRegistration APIを開発する必要があります。 もう一度私は上記の仮定で正しいですか?

編集:Web APIの構築にASP.NET MVC4を使用しています。

すべてのRESTにhttpsを使用するのをためらう理由API呼び出しは、軽量ではなく、より多くのネットワークペイロードを作成するので、モバイルアプリに最適ではないかもしれません。さらに暗号化/復号化と追加のハンドシェイクが必要になると、モバイルのバッテリー寿命にさらに影響を与える可能性がありますか? それとも重要ではないのですか?

上記の2つのアプローチのどちらを提案しますか?

PS:私たちはどこでもHttpsを使いましたが、それは最良の決定でした。私の blog でさらに詳しく。

84
noob Mama

私はどこでもSSL/TLSを使用します(両側を制御するため、TLS 1.2を強制することは実現可能です)。使い方は比較的簡単で、多くのセキュリティ機能を無料で利用できます。たとえば、SSLを使用しない場合は、リプレイ攻撃を心配する必要があります。

パフォーマンスが心配な場合は、サーバーとクライアントの両方でセッションの再開がサポートされていることを確認してください。これにより、後のハンドシェイクはるかが安くなります。ハンドシェイクは実際のデータの暗号化と比較してSSLで非常に高価であるため、全体的な負荷を大幅に削減します。

HTTP 2を使用する場合、単一の接続を介して複数の要求を送信することもできます。これにより、以降の要求での完全なTCPおよびSSLハンドシェイクのオーバーヘッドを回避できます。

54
CodesInChaos

OAuthの使用をお勧めします。慣れていない場合は、必ず読んでください。さらに、サードパーティのIDプロバイダーを使用できるので、ユーザーはアプリケーションにGoogle/Windows Liveなどのアカウントを使用して、登録を省略できます。

独自の認証フレームワークを導入する場合でも、有効期限のないセッションを使用することはお勧めしません。十分なアイドル時間の後にセッションが期限切れになるはずです。そうでない場合、これにより悪用の余地が増えます(セッションハイジャックなど)。

23

どれだけ安全であるかに依存します。ソリューションをより複雑にするたびに、大きなギャップを残す可能性があります。ある種の業界標準の承認および認証モジュールを使用することをお勧めします。

あなたがいる限り、あなたはおそらく大丈夫でしょう:

  • パスワードの暗号化(AESやBlowfishな​​どを使用)
  • パスワードをソルトする
  • hTTPS経由でデータを送信する

代替はOAuthです。

誰かがあなたをひどくハッキングしたい場合、彼らは常に方法を見つけます。秘密は、誰かがそれをしている間、それだけの価値がないほど必要な時間と労力を増やしています。したがって、大量の顧客データや財務データがなく、知名度の高い企業でない場合は、上記のような標準的なセキュリティ実装で十分です。

4
Dan Blows

APIが安全であることを100%確信することはできません。

これの主な理由は、おそらく機能するバイナリを顧客/ユーザーに手渡すことです。したがって、彼らは世界中でいつでもそのバイナリを分析してキー/シークレットを探し、APIサーバーで安全に認証するために使用されます。クライアントAPIエンドポイントは、バイナリが実行されるデバイスを所有しているため、最も弱い点です。したがって、クライアントAPIエンドポイントは、デバイスが有効であるかどうかを判断する証明書を操作できます。

私が話していることの明確な例は この記事 です(「ソフトウェアのプライベートAPIをリバースエンジニアリングするためのチュートリアル:カウチングのハッキング」)。そして、最後の段落の1つを引用して、この回答を完成させたいと思います。

サードパーティのクライアントによるプライベートAPIの使用を完全に防ぐことは可能ですか?私はそうは思いません。 SSLピニングを使用すると、前述のように単純な透過プロキシ技術を使用してAPIリクエストを傍受できなくなります。結局のところ、バイナリを難読化したとしても、ある程度のリソースと時間を備えた意欲的なハッカーは、常にアプリバイナリをリバースエンジニアリングして秘密キー/証明書を取得することができます。クライアントエンドポイントが安全であるという前提は本質的に間違っていると思います。 APIクライアントは弱点です。

2
knocte

JEEには、コンテナー管理セキュリティーの概念があります。その場合は、基本認証を使用するように残りのサービスを設定します。これは、デフォルトでは、アプリサーバーに設定されたレルムに対してHTTPパスワード認証を使用しています。これにより、ログインするためのHTMLフォームの必要性、またはクライアント側の証明書の展開の複雑さを回避できます。

アプリケーションは、ユーザープリンシパルと、リクエストで渡される識別詳細などの他のデータが存在することを前提としています。これにはRESTful APIが含まれます。

私のセットアップでは、OAuthトークンを保存するトークンを保存する OAuth2 JASPICサーバー認証モジュール [ Source ]を実装しました。キーは cookie の有効期間が制限されているサーバーに存在し、それをアプリケーションの認証として使用します。

上記を実行することで、アプリケーションを認証セマンティクスから遠ざけ、Seleniumを使用して機能統合テストを実行したい場合のボーナスとして、OAuthプロバイダー。

また、SSLを使用して、少なくともトランスポートが安全であることを確認します。 SSLを使用しないと、アプリケーションに対する一般的な攻撃への対処が非常に複雑になります。

これはJEEですが、メカニズムはどのテクノロジーにも適用できます。

2

HTTPSのみが必須です。

アプリとAPIの両方を制御するので、証明書の固定を実装します。証明書のピン留めは無効にすることができますが、それはカジュアルな検査官に対する良い抑止力です。

ペイロード暗号化を使用して別のレイヤーを追加できます。これは、強固なキー配布とキーローテーションプロセスを構築するコストで発生します。

アプリが特定のAPIへの認証にアクセストークンまたはセッションCookieを使用している場合は、タイムアウトになるようにしてください。私は、数日、数か月、またはこれまで有効期限のないベアラトークンを頻繁に観察します。

黄金律:モバイルO/Sは敵対的な環境です。注意と信頼の欠如でそれを扱います。

1
rustyMagnet

軽量ではなく、より多くのネットワークペイロードを作成する

これはレイテンシにいくらかの影響を及ぼします。したがって、数10ミリ秒のオーダーでデータを処理する必要がある場合は、それが考慮事項になる場合があります。しかし、2012年でさえ、非常に基本的なハードウェアは、ごくわずかな影響でコンピューティングのオーバーヘッドを処理します。

これはモバイルアプリに最適ではないかもしれません

その後、上記は問題ではありません。

0
symcbean