REST API呼び出しにパスワードを入れる


31

パスワードの設定/リセットにも使用されるREST APIがあるとします。また、これがHTTPS接続で機能すると仮定します。そのパスワードを呼び出しパスに入れない正当な理由はありますか、BASE64でエンコードすることもできますか?

例として、次のようなパスワードをリセットします。

http://www.example.com/user/joe/resetpassword/OLDPASSWD/NEWPASSWD

BASE64は暗号化ではないことを理解していますが、この場合はショルダーサーフィンのパスワードを保護したいだけです。


61
GETの副作用を提案していますか?それはまさにプロトコル違反です。
エスベンスコフペダーセン

27
resetpassword/OLDPASSWD/NEWPASSWDリソースではないため、これは実際にはRESTではありません。プロセスの呼び出しです。すべてをURLに詰め込む必要はありません。
usr

5
@Esben:誰がGETだと言ったの?OPはそれを言ったことはありません。
dagnelies

3
確かに、彼は質問に参加しませんでした。しかし、Netchの回答に対する彼のコメントは「結局POSTを使用する必要があると思います」と言うので、元々はGETについて意図/質問されていたと推測できます。エスベンが指摘するように、これは悪いことです。GETは読み取り専用です。
Mawg

4
パスワードリセットメカニズムの多くの落とし穴を説明するこの洞察に富んだ記事は、ケースをよりよく理解するのに役立つ可能性があります。
9000

回答:


76

適切なサーバーは、URL(多くの場合、「?」の後の可変部分なし)、ソースIP、実行時間など、送信されたすべての要求をログに記録します。パスワードとして非常に安全な情報?Base64はそれらに対するストッパーではありません。


42
これは、POSTを使用する最大の理由ではありません。これはセキュリティ上の理由です。しかし、Esbenがコメントで既に述べているように、GETで状態を変更することは、そのような休息サービスの違反です
-Pinoniq

2
@BartFriederichs:ブラウザーの履歴はURLを記憶します。そして、試してみたいすべてのパスワードへのリンクを含むWebページを作成し、Googlebotに実際のリクエストを実行させることで、パスワードの束を匿名で試します
...-RemcoGerlich

2
「しかし、Esbenがコメントですでにメモしているように、GETで状態を変更することはそのようなRestサービスの違反です」私もそのコメントに気付きましたが、これがGETリクエストであると誰が言っているのかわかりません。結局のところ、URIに情報を埋め込み、それでもPOSTすることができます。ただし、URIは実際にはリソースに名前を付けていないため、実際にはRESTfulではありません。
ジョシュアテイラー

こんにちは、良い答えですが、「 '?'の後の可変部分なし」に同意しません ...完全なURLを保存するものがたくさんあります!!!
dagnelies

2
「GETで状態を変更することは、このようなRestサービスの違反です」-RESTに追いつきすぎないようにしましょう。GETで状態を変更することは、HTTPの違反です。
ダン・エリス

69

あなたが提案しているのは、安全でもRESTfulでもありません。

@Netchはすでにログの問題について言及していますが、HTTPで送信されているパスワードを表示しているため、あらゆる種類のワイヤースニファーまたは中間者攻撃でパスワードをキャプチャするのが簡単になるという別の問題もあります。

RESTを使用してGETリクエストを行う場合、URLのさまざまな要素は、よりきめ細かい要素を表します。URLは、リセットパスワードの一部であるOLDPASSWDのNEWPASSWD部分を返しているようです。それは意味論的な意味をなさない。GETを使用してデータを保存しないでください。

次のようなことをする必要があります。

POST https://www.example.com/user/joe/resetpassword/
{oldpasswd:[data], newpasswd:[data]}

データを書き込んでいるのでPOSTし、データを盗聴したくないのでhttps。

(これは実際には低レベルのセキュリティです。絶対に最低限行うべきです。)


2
これは、クライアント側でパスワードをハッシュすることを意味しませんか?これはお勧めですか?
ローワンフリーマン

1
注:これにより、パスワード(長さなど)の要件を強制することはできません。頻繁なセキュリティ対策であり、一部のエンティティで必要になる場合もありますが、これは問題ではないかもしれません。
ポールドレーパー

8
新しいレコードを作成するのではなく、既存のレコードを更新する(通常)ため、これはPOSTではなくPUTである必要があります。

4
これはあまりRESTfulではありません。resetpasswordは、リソースではなく、サブリソースです。ただし、/user/joe/password少し優れていますが、最適ではありません。
旋風

12
@CamilStapsいいえ、べき等PUTであるため使用できませんPUT。ただし、パスワードがからsecretに正常に変更されたsupersecret場合、同じ要求は2回目に失敗するため、ここPOSTで正しいです。もちろん、@ whirlwinが言ったように、このリソースの名前はよくありません。
レジデュウム

60

提案されたスキームには、いくつかの領域で問題があります。

セキュリティ

URLパスは頻繁に記録されます。ハッシュされていないパスワードをパスに配置することは適切ではありません。

HTTP

認証/承認情報がAuthorizationヘッダーに表示されます。または、潜在的に、ブラウザベースのものの場合、Cookieヘッダー。

残り

resetpassword通常、URL などの動詞は、非代表的な状態転送パラダイムの明確な兆候です。URLはリソースを表す必要があります。GETとはどういう意味resetpasswordですか?または削除しますか?

API

このスキームでは、常に以前のパスワードを知っている必要があります。おそらくもっと多くのケースを考慮したくなるでしょう。たとえば、パスワードが失われます。


基本認証またはダイジェスト認証を使用できます。これはよく理解されているスキームです。

PUT /user/joe/password HTTP/1.0
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: text/plain
Host: www.example.com

NEWPASSWD

パスに超機密情報を配置せず、HTTPおよびRESTの規則に従います。

他の認証モード(パスワードをリセットするために検証済みのチャネルを介して送信されるトークンなど)を許可する必要がある場合は、他の認証ヘッダーを変更せずに使用できます。


4

セキュリティとは別に、これに関する問題は、あまりRESTfulなアプローチではないことです。

OLDPASSWDさらにNEWPASSWD、リソース階層内の何も支持しないでください。さらに悪いことに、操作はi等ではありません。

そのためPOST、動詞としてのみ使用でき、リソースパスに2つのパスワードを含めないでください。


1
新しいレコードを作成するのではなく、既存のレコードを更新する(通常)ため、これはPOSTではなくPUTである必要があります。

2
@CamilStapsパスワードを設定するだけの場合は、可能性があります。ただし、おそらく古いパスワードも検証する必要があるため、操作が-等でないためPUT、動詞としての資格がありません。動作するように調整することもできますPUTが、現在の形式では動作しません。
-biziclop

OLDPASSWDは認証情報であり、URLに含めないでください。

必ずしもそうではありませんが、認証の上に古いパスワードを明示的に要求することは一般的な習慣です。
biziclop

3

問題は、リクエストにプレーンテキストのパスワードを使用しないことです。安らかなWebサービスの要件を満たすには、2つのオプションがあります。

1.クライアント側のハッシュ

  • たとえば、hash(password + salt)のようなパスワードを保存していると思います
  • クライアント側でソルトを使用して新しいパスワードをハッシュできます
  • つまり、クライアント側で新しいソルトを作成し、hash(newPassword + newSalt)などのハッシュを作成します
  • 新しく作成したハッシュとソルトを安らかなWebサービスに送信します
  • 古いパスワードもハッシュとして送信します(oldPassword + oldSalt)

2.暗号化

  • / otk / johnなどのユーザー用の「ワンタイムキー」(otk)リソースを作成する
  • このリソースは、kbDlJbmNmQ0Y0SmRHZC9GaWtRMW0ycVJpYzhMcVNZTWlMUXN6ZWxLdTZESFRsと一意のID(例:95648915125)を含む、安全でランダムな一意のワンタイムキーを返します。
  • ID 95648915125との次の安全な通信のために、安らかなWebサービスはこのランダムotkを保存する必要があります
  • AESなどのotkを使用して新しいパスワードと古いパスワードを暗号化します(セキュリティ上の理由から、古いパスワードと新しいパスワードには2つの別のotkを使用する必要があります)
  • ID 95648915125のパスワード変更リソースに暗号化されたパスワードを送信します
  • 1つのotkとIDの組み合わせは1回しか機能しないため、パスワードを変更した後にその組み合わせを削除する必要があります
  • 考えられるより良いオプション:Basic-Authで現在/古いパスワードを送信します。

注:両方のオプションにHTTPSが必要です!


1
パスワード交換を二重暗号化(OTKによる暗号化スキームとHTTPS)するのはなぜですか?HTTPSでカバーされていない攻撃ベクトルとは何ですか?
バートフリーデリヒ

1
唯一の目的は、サーバーログの可能性を回避することです。HTTPSが使用されている場合でも、HTTP要求の本文(たとえば、プレーンテキストの新しいパスワード)を記録できます。他の考えられる攻撃は、特に内部目的で使用される自己署名証明書の使用です。
maz258

2

パスワードリセット操作の機能は何ですか?

  1. それは何かを変えます。
  2. 設定されている値があります。
  3. 一部のユーザーのみが許可されています(ユーザー、管理者、またはそのいずれか、おそらくそのどちらかを行う方法に関して異なるルールを持っています)。

ここでのポイント1は、GETを使用できないことを意味します。パスワード変更操作を表す何かをパスワード変更を処理するリソースを表すURIにPOSTするか、新しいパスワードを表す何かをパスワードまたは何かを表すURIにPUTする必要があります(例:そのパスワードが機能であるユーザー)。

通常、POSTを行います。特に、後で取得できないものをPUTするのが面倒な場合があり、もちろんパスワードを取得できないためです。

したがって、ポイント2は、POSTされる新しいパスワードを表すデータになります。

ポイント3は、リクエストを承認する必要があることを意味します。つまり、ユーザーが現在のユーザーである場合、現在のパスワードを証明する必要があります(ただし、ハッシュベースのチャレンジの場合、必ずしも現在のパスワードを受け取る必要はありません)送信せずにその知識を証明するために使用されました)。

URIは、そのためのようなものでなければなりません<http://example.net/changeCurrentUserPassword><http://example.net/users/joe/changePassword>

使用されている一般的な認証メカニズムだけでなく、POSTデータでも現在のパスワードを受け取りたいと判断するかもしれません。

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