web-dev-qa-db-ja.com

Webアプリ(angular)、iOS、Androidで使用できるセキュアなRESTful API

将来のWebアプリ(Angularjs)やモバイルアプリ(iOS/Android)で使用できるRESTful API(Python/Flask)を開発する計画を立てる必要があります。

私は3日間調査しており、いくつかのシナリオに遭遇しました。HTTPSを使用することは、安全性を維持するための以下の方法に加えて1つの方法です。しかし、httpsは遅いため、より高速で高価なサーバーが必要になる可能性があります。

  1. APIへのすべてのリクエストに対して、Basic-Http-Authを使用し、ユーザー名/パスワードをプレーン(まだhttps)で送信します。
  2. パスワードのハッシュであるDigest-Authを使用すると、追跡は自動になりますこれはWebアプリでは機能しますが、iPhoneとAndroidがこれをサポートするかどうかを確認できませんでした彼らがそうするならば、それは簡単な解決策であるかもしれません!
  3. カスタムHTTPヘッダーを使用します。認証が成功すると、HTTPヘッダーでカスタム認証文字列を送信します。しかし、ユーザーが行うすべてのリクエストに対してこの認証コードを送信していることを確認する必要があります。これは、1)とまったく同じです。ただし、プレーンなパスワードは使用されず、認証コードはリスクなしで期限切れになる可能性があります。 2)のように自動化されなくなった認証コードの追跡も問題です。
  4. OAuthの使用はオプションですが、設定は非常に困難です。より良い方法がない場合は、それが唯一の方法でしょうか?
  5. この 素晴らしい記事 で説明されているように、Amazon S3のようなAPIを保護します。つまり、サーバーとクライアントの両方が秘密鍵を知っていて、それらを使用して通信をハッシュ化するとしている。ギャングスターのハンドシェイクを知っている場合にのみ、配達少年を信頼するのはギャングスターのハンドシェイクのようになります。さらに誰かが尋ねるコメントの下に:

純粋なHTML5アプリで秘密鍵を「安全」に保つ方法は?

あなたはまさに正しいです。純粋なHTML5(JS/CSS/HTML)アプリでは、キーを保護する方法はありません。 HTTPSを介してすべての通信を行います。この場合、HMACを使用したり複雑にすることなく、標準のAPI_KEYまたはその他のわかりやすい識別子を使用してクライアントを安全に識別できるため、鍵は必要ありません。

つまり、言い換えれば、そもそもWebアプリのメソッドを使用する意味すらありません。そして正直なところ、私はこれがモバイルデバイスでどのように機能するか理解していません。ユーザーがアプリをダウンロードし、iPhoneからサーバーに秘密キーを送信するにはどうすればよいですか?譲渡した瞬間、危うくなります。

研究すればするほど、優柔不断になります。

以前にこれを行った経験を共有できるプロに質問したいと思っていました。どうもありがとう

33
Houman

2つの異なる概念を混同または統合しているようです。トラフィックの暗号化(HTTPS)について話し始め、次に、認証されたセッションを管理するためのさまざまな方法について話し始めます。安全なアプリケーションでは、これらは相互に排他的なタスクではありません。また、セッション管理が認証にどのように影響するかについて、誤解されている可能性もあります。これに基づいて、Webアプリケーション/ Web APIセッション管理、認証、および暗号化の入門書を提供します。

前書き

セッション管理

デフォルトでは、HTTPトランザクションはステートレスです。 HTTPは、HTTPリクエストが特定のユーザー(認証済みかどうか)から送信されたことをアプリケーションに知らせるためのメソッドを指定していません。

堅牢なWebアプリケーションの場合、これは受け入れられません。複数のリクエストにわたって行われたリクエストとデータを関連付ける方法が必要です。これを行うには、サーバーへの最初の要求時に、ユーザーに「セッション」を割り当てる必要があります。通常、セッションには、クライアントに送信されるある種の一意のIDがあります。クライアントはすべてのリクエストでそのセッションIDを送信し、サーバーはすべてのリクエストで送信されたセッションIDを使用してユーザーへの応答を適切に準備します。

「セッションID」は他の多くのものと呼ぶことができることを覚えておくことは重要です。それらのいくつかの例は次のとおりです。セッショントークン、トークンなど。一貫性のために、この応答の残りの部分では「セッションID」を使用します。

クライアントからの各HTTPリクエストには、セッションIDを含める必要があります。これは多くの方法で行うことができます。一般的な例は次のとおりです。

  1. Cookieに保存できます。現在のドメインのCookieは、リクエストごとに自動的に送信されます。
  2. URLで送信できます-各リクエストはURLでセッションIDを送信できますが、セッションIDはクライアントの履歴に残るため、提案されません
  3. HTTPヘッダーとして送信できます-各リクエストはヘッダーを指定する必要があります

ほとんどのWebアプリケーションフレームワークはCookieを使用します。ただし、JavaScriptと単一ページの設計に依存するアプリケーションは、HTTPヘッダーを使用するか、サーバーが監視できる他の場所にHTTPヘッダーを格納することを選択できます。

クライアントにセッションIDを通知するHTTP応答と、セッションIDを含むクライアントの要求は完全にプレーンテキストであり、100%安全ではないことを覚えておくことは非常に重要です。これに対抗するには、すべてのHTTPトラフィックを暗号化する必要があります。そこで登場するのがHTTPSです。

また、システム内の特定のユーザーにセッションをリンクすることについて話していないことを指摘することも重要です。セッション管理は、システムにアクセスする特定のクライアントにデータを関連付けるだけです。クライアントは認証済みの状態と未認証の状態のどちらでもかまいませんが、どちらの状態でも通常はセッションがあります。

認証

認証は、システム内の特定のユーザーにセッションをリンクする場所です。これは通常、ユーザーが資格情報を提供し、それらの資格情報が検証され、システム内の特定のユーザーレコードにセッションをリンクするログインプロセスによって処理されます。

次に、ユーザーは、アクセス制御リストおよびアクセス制御エントリ(ACLおよびACE)を介したきめ細かいアクセス制御の特権に関連付けられます。これは一般に「承認」と呼ばれます。ほとんどのシステムは常に認証と承認の両方を備えています。一部の単純なシステムでは、認証されたすべてのユーザーが等しい場合、単純な認証を通過した後の承認はありません。これに関する詳細情報はこの質問の範囲外ですが、ACE/ACLについて読むことを検討してください。

特定のセッションは、認証されたユーザーを表すものとしてさまざまな方法でフラグを立てることができます。

  1. サーバー側に保存されたセッションデータには、ユーザーIDや、特定のユーザーとして使用が認証されたことを示すその他のフラグが保存されます。
  2. 別のユーザートークンは、セッションIDと同じようにクライアントに送信できます(暗号化されていないHTTP経由では、セッションIDを暗号化せずに送信するのと同じくらい安全ではありません)。

どちらのオプションでもかまいません。一般的には、使用しているテクノロジーと、そのテクノロジーがデフォルトで提供するものに関係します。

クライアントは通常、認証プロセスを開始します。これは、特定のURL(例:yoursite.com/api/login)に認証情報を送信することで実行できます。ただし、「RESTful」になりたい場合は、通常、名詞でリソースを参照し、「作成」のアクションを実行します。これは、yoursite.com/api/authenticatedSession /への資格情報のPOSTを要求することで実行できます。ほとんどのサイトは、POST/api/loginなどへの認証情報。これは「真の」または「純粋な」RESTfulな理想からの逸脱ですが、ほとんどの人はこれを「認証されたセッションの作成」と考えるのではなく、より単純な概念だと考えています。

暗号化

HTTPSは、クライアントとサーバー間のHTTPトラフィックを暗号化するために使用されます。認証されたユーザーと認証されていないユーザーに依存するシステムでは、認証されるユーザーに依存するすべてのトラフィックをHTTPSで暗号化する必要があります。これを回避する方法はありません。

これは、ユーザーを認証し、シークレット(セッションIDなど)を共有し、プレーンシークレットでそのシークレットをパレードし始めると、中間者攻撃によってセッションがハイジャックされる可能性があるためです。ハッカーは、トラフィックが監視対象のネットワークを通過するのを待ち、秘密を盗み(HTTP経由のプレーンテキストであるため)、元のクライアントになりすましてサーバーへの接続を開始します。

これに対処する1つの方法は、要求のリモートIPアドレスを認証されたセッションに関連付けることです。ハッカーは偽のリクエストでリモートIPアドレスのリクエストを偽装し、サーバーが送り返している応答を観察できるため、これだけでは効果がありません。ほとんどの人は、履歴データを追跡して特定のユーザーのログインパターンを特定するために(Googleのように)使用しない限り、これを実装する価値はないと主張します。

サイトをHTTPセクションとHTTPSセクションに分割する必要がある場合は、HTTPトラフィックがセッションIDまたはユーザーの認証ステータスの管理に使用されるトークンを送受信しないことが不可欠です。重要なアプリケーションデータを非HTTPSリクエスト/レスポンス内で送信しないことも重要です。

Webアプリケーション/ API内のデータを保護する唯一の方法は、トラフィックを暗号化することです。

トピックを1つずつ

Basic-Http-Auth

  • 認証:はい
  • セッション管理:いいえ
  • 暗号化:いいえ

これは、Webリソースのみによる認証方法です。基本認証は、URLで識別されるリソースによって使用を認証します。これは、.htaccessベースのディレクトリ/ロケーション認証を使用してApache HTTP Webサーバーによって最も一般的に実装されました。資格情報はリクエストごとに送信する必要があります。通常、クライアントはこれをユーザーに対して透過的に処理しました。

基本認証は、認証のモードとして他のシステムで使用できます。ただし、Basic-Http-Authを利用するシステムは、Basic-Http-Auth自体ではなく、認証とセッション管理を提供します。

  • これはセッション管理ではありません。
  • これは暗号化ではありません。コンテンツと資格情報はほぼ100%プレーンテキストです
  • これは、アプリケーションのHTTP要求/応答の内容を保護しません。

ダイジェスト認証

  • 認証:はい
  • セッション管理:いいえ
  • 暗号化:いいえ

これはBasic-Http-Authとまったく同じで、いくつかの単純なMD5ダイジェストが追加されています。暗号化を使用する代わりに、このダイジェストを信頼すべきではありません。

  • これはセッション管理ではありません。
  • これは暗号化ではありません。ダイジェストは簡単に壊れます
  • これは、アプリケーションのHTTP要求/応答の内容を保護しません。

OAuth

  • 認証:はい
  • セッション管理:いいえ
  • 暗号化:いいえ

OAuthでは、外部サービスに認証情報を検証させるだけです。その後は、OAuthプロバイダーへの認証リクエストの結果を管理/処理する必要があります。

  • これはセッション管理ではありません。
  • これは暗号化ではありません。サイトのトラフィックはまだプレーンテキストです。 HTTPSの制限により認証プロセスは安全ですが、アプリケーションは依然として脆弱です。
  • これは、アプリケーションのHTTP要求/応答の内容を保護しません。

ギャングハンドシェイク/カスタムHTTPヘッダー

  • 認証:はい、可能性あり
  • セッション管理:はい、可能性あり
  • 暗号化:いいえ

「カスタムHTTPヘッダー」は「ギャングハンドシェイク」の一種です。そのため、同じセクションを使用してそれらについて説明します。唯一の違いは、「カスタムHTTPヘッダー」が、hanshake(セッションID、トークン、ユーザー認証トークンなど)が格納される場所(つまり、HTTPヘッダー)を指定していることです。

これらは認証の処理方法を指定しておらず、セッション管理の処理方法も指定していないことに注意してください。これらは基本的に、セッションID /認証トークンが保存される方法と場所を記述します。

認証は、アプリケーションまたはサードパーティ(OAuthなど)を介して処理する必要があります。セッション管理も実装する必要があります。興味深いのは、必要に応じて2つのマージを選択できることです。

  • これは暗号化ではありません。サイトのトラフィックはまだプレーンテキストです。 OAuthを使用する場合、HTTPS制限により認証プロセスは安全になりますが、アプリケーションはまだ脆弱です。
  • これは、アプリケーションのHTTP要求/応答の内容を保護しません。

するべきこと

...安全な堅牢なWebアプリケーションには次のものが必要であることを理解しておくことを強くお勧めします。

  1. 暗号化(HTTPSがほとんど唯一の選択肢です)
  2. セッション管理
  3. 認証/承認

認可は認証に依存しています。認証はセッション管理に依存し、暗号化はセッションがハイジャックされないこと、および資格情報が傍受されないことを確認します。

Flask-Login

ホイールの再実装を回避する方法として、 flask-login を検討する必要があると思います。私はそれを個人的に使用したことがありません(PythonでWebアプリケーションにピラミッドを使用しています)。ただし、Webアプリケーション/ Pythonボードでこれが言及されているのを見ました。認証とセッション管理の両方を処理します。 HTTPSを介してWeb API /アプリケーションをスローすると、3つすべて(暗号化、セッション管理、ユーザー認証)が手に入ります。

フラスコログインを使用しない、または使用できない場合は、独自に作成する準備をしてください。ただし、安全な認証メカニズムを作成する方法について最初に調査してください。

可能であれば、認証手順の記述方法がわからない場合は、ハッカーがパターンベースの攻撃やタイミング攻撃などをどのように使用するかを最初に理解しない限り、認証手順を試さないでください。

トラフィックを暗号化してください

...「巧妙な」トークンの使用でHTTPSを使用しないようにすることができるという考えを超えてください。 「遅い」ため、プロセス集約型など、HTTPS /暗号化の使用は避けるべきだという考えを超えてください。暗号化アルゴリズムであるため、プロセス集約型です。ユーザーのデータとアプリケーションのデータの安全性を確保する必要性は、常に最優先事項です。データが危険にさらされていることをユーザーに通知するという恐怖を経験したくありません。

67
Andrew Martinez

Httpsそれは遅いですが、そうではありません。ハンドシェイクだけが遅くなります。私たちにとって最大の問題は、サーバーモバイル側のキーペアと権利を維持することです。メッセージダイジェストも実装しました。問題は、php-Android-iosバージョンを適切に設定するのが難しいことです。これが実行された後(パラメーターは、Googleの最初の結果を変更する必要がありますAndroid側)でのみ問題が発生します)問題はローエンドデバイスで発生します:CPU使用率が非常に高く、復号化が遅い-暗号化プロセス。特に10kb文字列を変換する必要がある場合はhttpsよりもかなり遅くなります(数分かかる場合があります)。

Nasaのデータをハマスに転送しない場合は、単純なHTTPを介した非常に単純な暗号化を使用します。

1
user529543

HTTPSを使用します。 (わずかに)遅いですが、比較的短い投資時間(SSL証明書を購入し、URLをhttpからhttpsに変更するだけ)から得られるセキュリティは価値があります。 HTTPSがないと、ユーザーのセッションがセキュリティで保護されていないパブリックネットワークでハイジャックされる危険性があります。これは非常に 誰かが行うのは簡単です です。

1
Andrew Theis