HTTP経由でパスワードを安全に送信する方法は?


115

ログイン画面でユーザーがユーザー名とパスワードを使用してフォームを送信すると、パスワードはプレーンテキストで送信されます(POSTを使用していても、間違っている場合は修正してください)。

それで問題は、通信データを盗聴している可能性のある第三者からユーザーとそのパスワードを保護する正しい方法は何ですか?

HTTPSが問題の解決策であることは承知していますが、標準のHTTPプロトコル(POSTリクエスト)を使用して、少なくともある程度のセキュリティを確保する方法はありますか?(おそらくJavaScriptを何らかの方法で使用しています)

編集 私はいくつかの重要なことを省いたかもしれません。

私が言っていたのはページでした。つまり、PHPで生成されたログインページです。もちろん、HTTP GETリクエストでHTMLファイルとしてユーザーに送信されます。サーバーとクライアントの間に(@Jeremy Powel)接続が確立されていないため、このようなハンドシェイクプロトコルを作成できません。そして、私は完全なプロセスがユーザーに透過的であることを望みます-彼は暗号を扱うのではなく、パスワードを提出したいと考えています。

ありがとう。


1
おそらく、クライアントが暗号化を使用しないと、これを実現することはできませんが、ユーザーがそのようなプロセスを見る必要はありません。彼は自分のパスワードを入力するだけで、PHPが生成するコード(JavaScriptなど)がすべてを処理します。
Jeremy Powell、

13
あなたが説明する問題は、HTTPSが発明された理由です。パスワードを暗号化するためにクライアントにシークレットを送信すると、盗聴者はパスワードを盗聴し、帰路でパスワードを復号化できます。
jnoss 2009年

1
したがって、ユーザーが持っている唯一の「秘密」であるため、提案のSはパスワードのみ(またはユーザー名とパスワードを組み合わせたもの)にすることができます。私は正しいですか?したがって、解決策は次のようになります。-サーバーはHTMLページに非表示のフォームフィールドRを提供します-ユーザーはパスワードを入力し、パスワードが送信される前に、javascriptがH(R、S)を計算してサーバーに送信します。おそらくAJAXを使用して、 -サーバはH(R、S)を算出し、受信及び真偽が経過したか否か、AJAX要求に対する応答を送信するとそれを比較する- Javascriptを所望のウェブページにブラウザをリダイレクト
Kornelije Petak

2
@jeremy powell-あなたが説明することは一般的な慣行ですが、ヘッダーからCookieを盗聴し、Cookieを再利用することでユーザーになりすますことができる仲介者に対しても脆弱です。HTTPSを使用していない限り、中間者攻撃はセキュリティで保護するのが難しい
jnoss

1
将来この質問をする人のために:ログイン後、セッションCookieも保護する必要があります。(つまり、HTTPSを使用する方がはるかに簡単です。)
Arjan

回答:


66

SSLでHTTPを使用すると、生活がはるかに簡単になり、安心して休息することができます(少なくとも私よりも賢いです!)


14
...そして「SSL証明書を支払う必要があります!!」あなたは最近30ドルでそれらを得ることができるので、有効な苦情ではありません。あなたのデータは本当に保護するのに30ドルの価値はありませんか?
カフェ、

3
購読しているWebホストがSSL証明書の追加をサポートしていない場合はどうなりますか?
Calmarius 2013

89
@Calmarius-その後、実際の
Web

3
@BornToCodeこれは、技術的には専用IPが必要で、HTTPSを使用するにはサーバーハードウェア(または少なくともVPS)を所有している必要があることを意味します。サーバー全体がホスト所有者の証明書で保護されていない限り、共有ウェブホストはHTTPSを実行できません。
Calmarius 2013年

6
共有ウェブホストは確かに、en.wikipedia.org
ブライアンミントン

39

安全な認証は幅広いトピックです。一言で言えば、@ jeremy-powellが述べたように、HTTPではなくHTTPS経由で資格情報を送信することを常に優先します。それは多くのセキュリティ関連の頭痛を取り除くでしょう。

TSL / SSL証明書は最近かなり安価です。実際、お金をかけたくない場合は、無料のletsencrypt.orgがあります。自動認証局があります。

さらに一歩進んでcaddyserver.comを使用できますで、バックグラウンドでを呼び出すcaddyserver.comます。

さて、邪魔にならないようにHTTPSを取得したら...

POSTペイロードまたはGETパラメータを介してログインとパスワードを送信しないでください。代わりに、次のように構成されるAuthorizationヘッダー(基本アクセス認証スキーム)を使用します。

  • ユーザー名とパスワードは、コロンで区切られた文字列に結合されます。例:ユーザー名:パスワード
  • 結果の文字列は、Base64のRFC2045-MIMEバリアントを使用してエンコードされますが、76文字/行に限定されません。
  • 次に、認証方法とスペース、つまり「Basic」がエンコードされた文字列の前に置かれます。

ソース:ウィキペディア:承認ヘッダー

少し複雑に見えるかもしれませんが、そうではありません。すぐに使えるこの機能を提供する優れたライブラリがたくさんあります。

Authorizationヘッダーを使用する必要がある理由はいくつかあります

  1. 目安です
  2. 簡単です(使用方法を学んだ後)
  3. 次のように、URLレベルでログインできるようになります:(https://user:password@your.domain.com/loginたとえば、Chromeは自動的にAuthorizationヘッダーに変換します)

重要:
以下のコメントで@zaphが指摘しているように、機密情報をGETクエリとして送信することは、サーバーログに記録される可能性が高いため、お勧めできません。

ここに画像の説明を入力してください


11
GETパラメーターとして資格情報(パスワード)を送信する場合の問題は、ユーザーとパスワードのペアがサーバーログに記録される可能性があることです。POSTで資格情報を送信することをお勧めします。
zaph 16

ああ...全然。表示されているスクリーンショットは、ブラウザーで何が起こっているかを示すために変更されています。Enterブラウザーを押すと、URLが変換されてAuthorizationヘッダーが作成されます。試してみてください。ログはきれいに思い出させます。もちろん、サーバーから呼び出しを行う場合(それが問題になるシナリオの場合)、プログラムでヘッダーを生成する必要があります。
FullStackForger 2016

見えないものはログに記録できません。username:password@urlブラウザーからの変換:url+ Authorization要求ヘッダー。GETクエリについては、私が言ったようにAuthroziationヘッダーを使用します。それはさらにいいです。
FullStackForger 2016

2
機密性の高いデータを中間者盗聴から保護するという質問の要点に対処しません。焦点は、資格情報を渡すための代替および/またはより標準化された方法を見つけることではなく、安全でないチャネルを介してそれらを保護することです。
グーの主

3
このソリューションは、TLS / SSLを使用して接続をすでに暗号化している場合にのみ機能することを強調しておく必要があります。base64は暗号化ではありません。
スコット

14

チャレンジ/レスポンス方式を使用できます。クライアントとサーバーの両方が秘密のSを知っているとしましょう。次にサーバーは、クライアントがパスワードを(それを明かすことなく)知っていることを確認できます。

  1. サーバーは乱数Rをクライアントに送信します。
  2. クライアントはH(R、S)をサーバーに送信します(HはSHA-256のような暗号化ハッシュ関数です)
  3. サーバーはH(R、S)を計算し、それをクライアントの応答と比較します。それらが一致する場合、サーバーはクライアントがパスワードを知っていることを認識しています。

編集:

Rの鮮度とHTTPがステートレスであるという事実に問題があります。これは、サーバーだけが知っている秘密をQと呼ぶサーバーに作成させることで処理できます。次に、プロトコルは次のようになります。

  1. サーバーは乱数Rを生成します。次に、サーバーはクライアントH(R、Q)に送信します(クライアントは偽造できません)。
  2. クライアントはR、H(R、Q)を送信し、H(R、S)を計算してすべてをサーバーに送信します(HはSHA-256のような暗号化ハッシュ関数です)。
  3. サーバーはH(R、S)を計算し、それをクライアントの応答と比較します。次に、Rを受け取り、(再度)H(R、Q)を計算します。クライアントのH(R、Q)およびH(R、S)のバージョンがサーバーの再計算と一致する場合、サーバーはクライアントが認証されたと見なします。

H(R、Q)はクライアントによって偽造できないため、H(R、Q)はCookieとして機能します(したがって、実際にはCookieとして実装できます)。

別の編集:

H(R、Q)を観察した人は誰でも正しいハッシュでそれを再生できるように見えるので、プロトコルの以前の編集は正しくありません。サーバーは、どのRが最新でないかを覚えておく必要があります。私はこの答えをCWしているので、皆さんはこれを編集して、良いものを見つけ出すことができます。


+
1-

10
中間者またはなりすまし攻撃を阻止しません。たとえば、wifiを介して。これは、IMOに誤った安心感を与えるだけのようです。
トム・ホーティン-

2
これはパッシブ攻撃から保護しますが、中間者は依然として攻撃できます。
ダグラスリーダー

7
また、サーバーは元のパスワードを知っている必要があります。
ダグラスリーダー

3
暗号を再発明しないでください!(製造中)
ブライアンフ2015

11

ウェブホストで許可されている場合、または機密データを処理する必要がある場合は、HTTPSを使用してください。(これは法律のafaikによってしばしば要求されます)。

それ以外の場合は、HTTP経由で何かを実行する必要があります。私はこのようなことをします。

  1. サーバーはその公開鍵をログインページに埋め込みます。
  2. クライアントはログインフォームを入力し、[送信]をクリックします。
  3. AJAXリクエストは、サーバーから現在のタイムスタンプを取得します。
  4. クライアント側のスクリプトは、資格情報、タイムスタンプ、ソルト(マウスの動き、キーを押すイベントなどのアナログデータからハッシュ化)を連結し、公開キーを使用して暗号化します。
  5. 結果のハッシュを送信します。
  6. サーバーはハッシュを復号化します
  7. タイムスタンプが十分に新しいかどうかを確認します(5〜10秒の短いウィンドウのみを許可します)。タイムスタンプが古すぎる場合、ログインを拒否します。
  8. ハッシュを20秒間保存します。この間隔の間、ログインの同じハッシュを拒否します。
  9. ユーザーを認証します。

したがって、この方法ではパスワードが保護され、同じ認証ハッシュを再生できません。

セッショントークンのセキュリティについて。それは少し難しいです。しかし、盗まれたセッショントークンの再利用を少し難しくすることは可能です。

  1. サーバーは、ランダムな文字列を含む追加のセッションCookieを設定します。
  2. ブラウザは、次のリクエストでこのCookieを送り返します。
  3. サーバーはCookieの値をチェックし、異なる場合はセッションを破棄し、それ以外の場合はすべて問題ありません。
  4. サーバーは、Cookieを別のテキストで再度設定します。

そのため、セッショントークンが盗まれ、リクエストが他の誰かによって送信された場合、元のユーザーの次のリクエストでセッションが破棄されます。そのため、ユーザーが頻繁にサイトを閲覧し、リンクをクリックすることが多い場合、盗まれたトークンを盗むことはできません。このスキームは、重要な操作(アカウントの削除など)に別の認証を要求することで強化できます。

編集:攻撃者が別の公開鍵を使用して独自のページを設定し、サーバーへのリクエストをプロキシする場合、これはMITM攻撃を防止しないことに注意してください。これを防ぐには、公開鍵をブラウザのローカルストレージまたはアプリ内に固定して、この種のトリックを検出する必要があります。

実装について:RSAはおそらく最もよく知られているアルゴリズムですが、長いキーの場合は非常に遅くなります。PHPまたはJavascriptの実装がどれほど高速になるかわかりません。しかし、おそらくより高速なアルゴリズムがあります。


この場合、パスワードは本当に保護されていますか?誰かが送信されたものを傍受し、公開鍵を使用してそれを復号化し、後でそれを使用するときにタイムスタンプを更新することはできませんか?何か不足していますか?
michaellindahl 14年

@michaellindahl非対称暗号化とは、サーバーを離れることのない秘密鍵のみを使用して復号化できることを意味します。公開鍵は暗号化にのみ使用できます。
Dan Pantry、2015年

2
ブラウザとサーバーの間のコンピュータがログインページの公開鍵を変更する可能性があります。
Antti、2017年

あなたの方法を共有してくれてありがとう、私は非常に興味深いものを見つけました。クレデンシャルの送信時に追加されるタイムスタンプは良いキャッチです!値がランダムな文字列である追加のセッションCookieの使用に関する1つの質問:次のリクエストのみのトークンのようなものですか?
ビクター

4

サーバー側とクライアント側のDiffie-Hellman鍵交換システムをAJAXまたは複数のフォーム送信(前者をお勧めします)で使用しますが、インターネット上での適切な実装は見られません。JSライブラリはMITMによって常に破損または変更される可能性があることに注意してください。ローカルストレージを使用して、ある程度これに対抗することができます。


4

あなたは使用することができますSRPを安全でないチャネルを介して安全なパスワードを使用します。利点は、攻撃者がトラフィックを盗聴したり、サーバーを危険にさらしたりしても、別のサーバーでパスワードを使用できないことです。https://github.com/alax/jsrpは、ブラウザーまたはサーバー側(ノード経由)でHTTPを介した安全なパスワードをサポートするJavaScriptライブラリです。


1

HTTPSは非対称暗号化を使用しているため、非常に強力です。このタイプの暗号化では、暗号化されたトンネルを作成できるだけでなく、ハッカーではなく適切な人物と話していることを確認できます。

これは、非対称暗号RSA(PGPで使用)を使用して通信するJavaソースコードです。http//www.hushmail.com/services/downloads/


0

ホストにsslを使用できます。letsencrypthttps : //letsencrypt.org/のようなsslの無料プロジェクトがあり ます。


2
問題の3番目の文を確認してください。(また、詳細の少ない重複を追加しないように、必ず他の回答を読んでください。)
Nathan Tuggy '26

0

ここでhttpsを使用するのが最善の方法です(現在、証明書はそれほど高価ではありません)。ただし、httpが必要な場合は、いくつかの暗号化を使用できます-サーバー側で暗号化し、ユーザーのブラウザーで暗号化します(キーを個別に送信します)。

safevia.netを実装する際にこれを使用しました -暗号化はクライアント(送信側/受信側)側で行われるため、ユーザー層のデータはネットワーク層でもサーバー層でも利用できません。

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