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


91

私は、バックエンドでいくつかの人気のあるWebフレームワークを使用する(Rails、Sinatra、Flask、Express.jsなど)休息のWebアプリケーションを開発しています。理想的には、Backbone.jsを使用してクライアント側を開発したいです。JavaScriptクライアント側のみがこれらのAPI呼び出しと対話できるようにするにはどうすればよいですか?これらのAPI呼び出しが公開curlされて、ブラウザでリンクを入力することで、または単に呼び出されることを望んでいません。


すべてのAPI呼び出しに、ページが提供されるときにクライアントに渡されるトークンが必要ですか?
hajpoj 2012

REST認証とAPIキーの公開も参照してください。
Arjan

アマゾンAWSのJavaScript SDKの用途は、オブジェクトのURLを締結した事前: - docs.aws.amazon.com/AmazonS3/latest/dev/...
rjha94

回答:


90

最初の原則として、APIがJSクライアントによって使用される場合、それがパブリックであると想定する必要があります。単純なJSデバッガーは、攻撃者を1バイトずつ同じリクエストを彼の選択のツール。

そうは言っても、私があなたの質問を正しく読んだ場合、そうではありません。あなたが避けたいことは、あなたが本当に起こしたくないことは、JSクライアントが関与せずにAPIが(定期的に)消費されることです。強制しない場合のいくつかのアイデアを次に示し、少なくともクライアントの使用を推奨します。

  • きっとあなたのAPIにはある種の認証フィールドがあります(クライアントで計算されたハッシュなど)。そうでない場合は、このSOの質問をご覧くださいセッションベースでJSクライアントに与えられたソルト(またはAPIキー)を使用していることを確認してください(ハードコードされていません)。このようにして、APIの無許可のコンシューマーは、はるかに多くの作業を余儀なくされます。

  • JSクライアントの読み込み時に、HTTPヘッダー(ユーザーエージェントが思い浮かびます)とIPアドレスを覚えて、通常の容疑者のブラックリストを使用して、それらが変更された場合は再認証を要求します。これにより、攻撃者は再び宿題をより徹底的に行う必要があります。

  • サーバー側では、最後のいくつかのAPI呼び出しを覚えておいて、別のAPI呼び出しを許可する前に、ビジネスロジックで新しいAPI呼び出しが許可されているかどうかを今すぐ確認してください。他の対策と組み合わせることで、これは乱用者を簡単に検出できるようにします。

私は、必要な明快さでそれを言ったことがなかったかもしれません:私は、虐待者があなたのサービスを消費することを完全に不可能にすることは不可能であると考えます、しかしあなたはそれをとても難しくすることができます、それは面倒の価値がないかもしれません。


これは有用な情報ですが、バックエンドAPIから別のサーバーのような別のAPIアプリに認証を行いたい場合、質問を簡単にするために、バックエンドaka node.jsから別のバックにフェッチ要求を送信したい場合はどうすればよいですか?私自身のエンドサーバー、いくつかの理由でこれが必要ですが、機密データにアクセスできるため、API呼び出しをセキュリティで保護したいと考えています。また、セッションまたはjwtを使用できないのは、ブラウザーに実際に格納できないためです。
ピラミッド

@Thepyramidサーバー側でAPI呼び出しが何をするかは重要ではありません。特にサーバー側が別の2番目のレベルのAPI呼び出しを行う場合は特に重要です。重要な部分は、サーバーをプロキシではなくアプリケーションとして扱うことです。
Eugen Rieck

プロキシではなくアプリケーションとして作成する方法について詳しく説明できますか
ピラミッド

1
つまり、適切なセキュリティを確保するには、セッション、認証データベース、ビジネスロジックなど、Webアプリケーションにあるすべてのツールを使用する必要があります。それを行わず、サーバーを別のサーバーにリクエストを渡す方法として扱う場合、そのサーバーを他のサーバーのプロキシとして使用しているだけで、他のサーバーが提供するセキュリティによって制限されます。
Eugen Rieck

1
@PirateApp攻撃者はCSRFヘッダーを簡単に無視できます。エンドデバイスがパッチが適用されていないブラウザである場合にのみ機能します
Eugen Rieck

12

何らかの認証システムを実装する必要があります。これを処理する1つの良い方法は、予期されるヘッダー変数を定義することです。たとえば、セッショントークンを返すauth / login API呼び出しを持つことができます。APIへの後続の呼び出しでは、「your-api-token」のような特定の名前を持つHTTPヘッダー変数にセッショントークンが設定されることが期待されます。

あるいは、多くのシステムが、ある種のapiアカウントシステムを使用して、予想されるアクセストークンまたはキー(youtube、facebook、twitterなど)を作成します。そのような場合、クライアントはこれらを何らかの方法でクライアントに保存する必要があります。

次に、セッションのチェックをRESTフレームワークに追加し、例外をスローするだけです。可能であれば、ステータスコード(安静にする)は401エラーになります。


8
ヘッダーを見て複製することを妨げるものは何もありません。
cdmckay 2013

1
@cdmckay-トークンは、セッションに格納されているトークンと一致する必要があります。ヘッダーを単純に複製すると、別のセッションからのものである場合、「無許可」の応答が返されます。
Andrei Volgin

3
APIに送信される前に同じセッションを使用してリクエストを変更することもできます...または実行時にコンソールを使用して、必要な部分のみを変更するヘッダー/フィールドが一致する呼び出しを生成することもできます...
Potter Rafed

2
@PotterRafed:ユーザーが自分の有効なセッションにアクセスした場合、それは攻撃せずにアプリを使用して呼び出されます。認証の目的は、他のユーザーのセッション/データへのアクセスを防ぐことです。
Andrei Volgin 2017

@AndreiVolginはまあまあですが、それでも脆弱性です
Potter Rafed

9

現在「JSON Web Token」と呼ばれるオープンスタンダードがあり、

https://jwt.io/およびhttps://en.wikipedia.org/wiki/JSON_Web_Tokenを参照してください

JSON Web Token(JWT)は、いくつかのクレームを主張するトークンを作成するためのJSONベースのオープンスタンダード(RFC 7519)です。たとえば、サーバーは「adminとしてログイン」というクレームを持つトークンを生成し、それをクライアントに提供できます。その後、クライアントはそのトークンを使用して、管理者としてログインしていることを証明できます。トークンはサーバーのキーによって署名されるため、サーバーはトークンが正当であることを確認できます。トークンは、コンパクトでURLセーフで、特にWebブラウザーのシングルサインオン(SSO)コンテキストで使用できるように設計されています。JWTクレームは、通常、IDプロバイダーとサービスプロバイダーの間で認証済みユーザーのIDを渡すために使用できます。または、ビジネスプロセスで必要とされるその他の種類のクレームを渡すこともできます。[1] [2] トークンは認証および暗号化することもできます。[3] [4]


ユーザーがトークンをコピーして他の応答でそれを使用するのを妨げるのは何ですか?
Ulad Kasach 2017

1
@UladKasach正直言って、私はそれらに深く入り込んだことはありませんが、失効していて、ユーザーにとって一意であり、SSLで暗号化されている(もちろん実践しています)、それはoauth afaikの背後にあるまったく同じアイデアです
bbozo

3

すみません、@ MarkAmeryとEugeneですが、それは誤りです。

ブラウザで実行されているjs + html(クライアント)アプリは、次のようにAPIへの不正な直接呼び出しを除外するように設定できます。

  1. 最初のステップ:認証を要求するようにAPIをセットアップします。クライアントは、最初のサーバ(またはいくつかの他のセキュリティ・サーバ)を介して自身を認証する必要があり、正しいパスワードを提供するために、人間のユーザに尋ねる例えば。

認証前は、APIの呼び出しは受け入れられません。

認証中に「トークン」が返されます。

認証後、認証「トークン」を持つAPI呼び出しのみが受け入れられます。

もちろん、この段階では、パスワードを持つ承認されたユーザーのみがAPIにアクセスできますが、アプリをデバッグするプログラマーであれば、テスト目的で直接APIにアクセスできます。

  1. 2番目のステップ:次に、追加のセキュリティAPIを設定します。これは、クライアントのjs + htmlアプリがサーバーから最初にリクエストされた後、短時間で呼び出されます。この「コールバック」は、クライアントが正常にダウンロードされたことをサーバーに通知します。クライアントが最近かつ正常に要求された場合にのみ機能するようにREST API呼び出しを制限します。

APIを使用するには、まずクライアントをダウンロードし、実際にブラウザーで実行する必要があります。APIは、コールバックを正常に受信した後、短い時間内にユーザー入力を行うと、APIが呼び出しを受け入れます。

そのため、これが資格情報のない無許可のユーザーである可能性を心配する必要はありません。

(「REST API呼び出しをセキュリティで保護するにはどうすればよいですか?」 )


5
2番目の点は意味がありません。攻撃者がアプリをロードする必要がある場合、それを実行します(コールバックは表示されます)。そして攻撃します。
Andrei Volgin

ポイント2はポイント1に追加されます。攻撃者は依然として認証を必要とします。ポイント2は、承認を受けるために実際にhtmlアプリをダウンロードする必要性を追加するだけです。そのため、アプリなしでAPIを直接呼び出すこと(おそらく認証後にのみアクセスおよびダウンロードされること)は不可能です。これはこの質問で要求されたものです。
pashute

ドメインからのリクエストのみを許可することができます。
Andrei Volgin

これはドメイン内への呼び出しのみを制限するので、JavaScriptブラウザーアプリのユーザーはドメイン内にいる必要があり(おそらく何も必要ない)、それらのユーザーはcurlを介してAPIを直接呼び出すことができます。
2016年

2
見落としているように見えるのは、ユーザーのブラウザに要求することは、攻撃者によって複製される可能性があることです。ブラウザにそれを実行させるには、読み取り可能である必要があります。
Eugen Rieck 2016

1
  1. クライアントが最初にindex.htmlbackbone.jsなど)をロードするときに、サーバーにSESSION変数を設定します。

  2. すべてのAPI呼び出しでサーバー側でこの変数を確認してください。

PSこれは「セキュリティ」ソリューションではありません!!! これは、サーバーの負荷を軽減して、他のWebサイトやアプリから他のユーザーがAPIを悪用したり、「ホットリンク」したりしないようにするためのものです。


0

これが私がすることです:

  1. X-APITOKENなどの呼び出しを使用して、HTTPヘッダーでAPIを保護します。

  2. PHPでセッション変数を使用します。ログインシステムを用意し、ユーザートークンをセッション変数に保存します。

  3. PHPへのAjaxでJSコードを呼び出し、curlでセッション変数を使用してAPIを呼び出します。このように、セッション変数が設定されていない場合は呼び出されず、PHPコードにAPIへのアクセストークンが含まれます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.