クライアント側でパスワードをハッシュする価値はありますか


132

ログインシステムを導入するときは、常に、指定されたパスワードのMD5をサーバー側のユーザーテーブルの値と比較します。

しかし、私の友人は、「クリアな」パスワードがネットワークソフトウェアによって盗聴される可能性があると私に言った。

だから私の質問は:クライアント側でパスワードをハッシュするのは良い考えですか?サーバー側でハッシュするよりも良いですか?


1
クライアント側でパスワードをハッシュ化することを考えていましたが、クライアント側のパスワードがサーバー側にクリアテキストとして存在することはないので、実際のパスワードがわからないことを知って安心することができます。妥協した場合、簡単に諦めることはできません。私は狂っていますか?
サイクロン

1
完全を期すために、私たちはセキュリティについて話しているので、MD5はOPで言及されていました。パスワードを暗号化するときは常にソルトを使用する必要があります。 プレーンで無塩のMD5を使用する方が、データベースにプレーンテキストのパスワードを保存するよりもわずかに優れています。
sffc 2013年

1
@Cyclone Hashingはクライアント側でのみ確実に悪い考えです。攻撃者がハッシュを何らかの方法で知っている場合、クライアント側のハッシュコードをバイパスして、パスワードを知っているかのようにログインに使用できるためです。
Teejay、2016

5
@Teejay:それがハッシュを平文で送らない理由です。サーバーはランダムなソルトをクライアントに送信し、パスワードハッシュを追加し、全体を再度ハッシュしてから、同じ計算を行うサーバーにそれを送り返します。ソルトが異なるため、リプレイ攻撃は失敗します
MSalters

2
この質問はsecurity.stackexchange.comで終わりませんか?
efr4k 2016年

回答:


115

基本的に、あなたの友達は正しいです。ただし、クライアント側でパスワードをハッシュするだけの方が、プレーンテキストとしてサーバーに送信するよりも優れています。プレーンテキストのパスワードを聞くことができる人は、ハッシュされたパスワードを聞くこともでき、これらのキャプチャされたハッシュを使用してサーバーに対して認証します。

この問題に関して、より安全な認証プロトコルは通常、クライアントがランダムなビットの束を選択することを許可することにより、そのようなリプレイ攻撃が機能しないことを確認するために、多くのフープをジャンプします。 、またクリアテキストでサーバーに送信されます。

サーバー上:

  • 数ビットのランダムを生成する
  • これらのビットを(クリアテキストで)クライアントに送信する

クライアント上:

  • いくつかのランダムなビットを生成する
  • パスワード、サーバーのランダムビット、およびクライアントのランダムビットを連結する
  • 上記のハッシュを生成する
  • ランダムビット(クリアテキスト)とハッシュをサーバーに送信する

サーバーは自身のランダム情報とクライアントのランダムビット(それらをクリアテキストとして取得した)を知っているため、基本的に同じ変換を実行できます。このプロトコルは、両方の当事者が毎回異なる「ノイズビット」を生成する限り、この会話を聞いている誰もが後で情報を使用して、記録された情報を使用して誤って認証することができないことを確認します(非常に弱いアルゴリズムが使用された場合を除く)。握手が行われます。

編集これはすべてエラーが発生しやすく、面倒で、正しく理解するのがやや難しい(読み取り:安全)。可能であれば、知識のある人がすでに書いている認証プロトコルの実装を使用することを検討してください(私とは異なります。上記は、私が少し前に読んだ本のメモリからのみです。)通常、これを自分で書きたくはありません。


5
ログインシステムでハッシュ化されたパスワードは、再度ハッシュ化されるため、どのように認証できますか?
ザカリア

4
(必要に応じて)パスワードをハッシュ化された形式でサーバーに保存すると、クライアントはパスワードを2回ハッシュする必要があります。プロトコルのために。
Dirk

3
@Dirk、攻撃者は両方の方法で傍受できるため、「ランダムなビット」も傍受されます。その後、攻撃者は要求と応答のペアをオフラインで分析(読み取り:総当たり)して、元のパスワードを見つけることができます。
パセリエ2012

7
ただし、パスワードまたはパスワードのハッシュを送信する目的で、Diffie-Hellmanのような非対称プロセスを使用して、スヌーピングパーティが暗号化を解読することなく情報を交換できるようにする暗号化キーを確立することがよくあります。これはまさにSSLが行うことであり、ほとんどのサイトがHTTPS / SSLにログインページを持っている理由です。SSLはすでにリプレイアタックから保護しています。独自のプロトコルを構築するのではなく、SSLを活用することをお勧めします。パスワードをクライアント側でソルト+ハッシュすることに同意しますが、確立されたSSL接続を介してこれらを送信します。
AaronLS 2014

14
明確にするために:HTTPSを使用していない場合、クライアントで実行しているJavaScriptは関係ありません。MITMは、クライアントに到達する前にページのコンテンツを変更できます。HTTPSが唯一のソリューションです。
エイダン

60

まず第一に、これはあなたのアプリケーションのセキュリティを向上させません(それがwebappであると仮定します)。

SSL(または実際にはTLS、通称SSLと呼ばれます)を使用します。これはそれほど高価ではありません(その方法を見つけて最低賃金で乗算するために使用している時間を測定し、証明書を購入するとほぼ常に勝ちます)。

これの理由は簡単です。TLSは、暗号で非常に大きな問題(自己署名ではなく購入した証明書で使用した場合)を解決します。私が話しているサーバーが、私が話していると思うサーバーであることをどのようにして知ることができますか?TLS証明書は言い方です。「ブラウザーによって信頼されている認証局である私は、[url]のWebサイトがこの公開鍵を持っていることを証明します。対応する秘密鍵は、サーバーだけが知っています(秘密鍵)ドキュメント全体に署名しました。誰かが変更した場合、あなたは見ることができます。」

TLSがなければ、暗号化は無意味になります。私がコーヒーショップであなたの隣に座っていると、私はあなたのラップトップ/スマートフォンに私がサーバーであり、MiTM(Man in The Middle)だと思わせることができるからです。TLSを使用すると、あなたのサイトに一致する認証局の署名付き証明書がないので、ラップトップ/スマートフォンは「信頼できない接続」と叫ぶでしょう。(暗号化と認証)。

免責事項:ユーザーはこれらの警告を右クリックする傾向があります:「信頼できない接続?何ですか?子猫の写真が欲しいだけです!例外を追加 してくださいクリックして 確認 してください YAYをクリックしてください!子猫!」

ただし、本当に証明書を購入したくない場合でも、クライアント側のJavaScriptハッシュを実装してください(そのためにスタンドフォードライブラリ(SJCL)を使用し、CRYPTO YOURSELFを絶対に実装しないでください)。

どうして?パスワードの再利用!HTTPSなしで簡単にセッションCookieを盗むことができます(これにより、私があなたのサーバーであるかのように見せかけることができます)(firesheepを参照)。ただし、送信前にパスワードをハッシュするJavaScriptをログインページに追加した場合(SHA256を使用するか、SHA256を使用し、SHA256を使用し、生成した公開鍵を送信し、それを使用してパスワードをハッシュ化して暗号化すると、saltを使用できませんこれで)、次に、ハッシュ/暗号化されたパスワードをサーバーに送信します。サーバー上のハッシュをソルトでハッシュし直し、それをデータベースに保存されているものと比較します(パスワードを次のように保存します

(SHA256(SHA256(password)+salt))

(ソルトをプレーンテキストとしてデータベースにも保存します))。次のようにパスワードを送信します。

RSA_With_Public_Key(SHA256(password))

次のようにパスワードを確認してください:

if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok

、のでIF誰かがあなたのクライアントを盗聴され、彼らはあなたのクライアント(セッションハイジャック)としてログインすることができますが、彼らはなりますNEVER(平文パスワードを見ていない、彼らはあなたのJavaScriptを変更しない限り、しかし、ハッカーはおそらくHOWTO知ることができません/興味があるスターバックスこのため、)彼らはあなたのウェブアプリにアクセスできますが、彼らのメール/フェイスブック/その他にはアクセスできません (ユーザーが同じパスワードを使用する可能性があります)。(メールアドレスは、ログイン名であるか、Webアプリケーションのプロファイル/設定にあります)。


これは良い答えだと思いますが、おそらく適切にソルトする方法についてさらに多くの情報が必要であり、サーバーにパスワードを保存する前に(低速)ハッシュ関数を使用することをお勧めします(bcryptなど)。
Neyt

24

このことを心配しなくても大丈夫でしょう。Dirkが言及しているように、悪意のあるユーザーがネットワーク上にいる可能性があるパスワードをハッシュし、ハッシュが送信されるのを見て、同じハッシュを自分で送信することもできます。

それは少しそれはパスワードが何であるかを知っているから、悪意のあるユーザーを防ぐことで、より良い、しかし、彼らはまだログイン(または潜在的にすることができますので、元のパスワードを再構築する)、その有用ではないということ。

一般に、ユーザーのパスワードとデータの安全性が心配な場合(そして安全である必要があります!)、安全なSSLサーバーを使用することをお勧めします。なんらかの理由でこれが問題にならない場合は、ハッシュを使用する必要はありません。それはあいまいさによる単なるセキュリティです。


2014年8月を編集:通信自体を保護することがネットワークスニッフィング攻撃を防ぐ唯一の方法であるため、GoogleはWebサイトがどこでもHTTPS切り替わることをますます強く求めています。送信されたデータを難読化しようとすると、専用の攻撃者が妨害されるだけで停止することはなく、開発者に危険な誤った安心感を与える可能性があります。


ユーザーのパスワードの取得と単一のサービスへのアクセスのみに集中している場合、クライアント側のハッシュは「わずかに優れている」だけだとのあなたの意見は正しいと思いますx。集合的な効果を考えると、「はるかに良い」と言えます。複数のサービス間でソルトハッシュをブルートフォースするために使用されるパスワードの大規模なルックアップデータベースの構築を防ぐためです。IMO。参考として、AWS Cognitoがクライアントで実行する内容を確認してください。
f1lt3r 2018

17

この場合、クライアント側のハッシュの方が安全であることに私は反対です。安全性は低いと思います。

実際のパスワード(または暗号化されたパスワード)とは対照的に、データベースにパスワードのハッシュを格納することの全体的なポイントは、ハッシュから元のパスワードを取得することは数学的に不可能であることです(理論的には衝突を取得することは可能です)ハッシュ入力。難易度はハッシュアルゴリズムのセキュリティ強度に依存します)。ここで考えられる攻撃の方法は、潜在的な攻撃者が何らかの方法でパスワードストレージデータベースを侵害した場合でも、ユーザーの元のパスワードを取得できないことです。

認証メカニズムがパスワードのハッシュを送信する場合、このセキュリティ違反のシナリオでは、攻撃者は実際のパスワードを知る必要はありません。攻撃者は自分が持っているハッシュを送信するだけで、特定のユーザーのアカウントにアクセスできます。ひいてはシステム全体。これは、ハッシュされたパスワードを最初から保存するという点を完全に無効にします!

これを行うための本当に安全な方法は、クライアントにパスワードを暗号化するための1回限りの公開鍵を送信し、それを復号化してサーバー側で再度ハッシュすることです。

ちなみに、この種の質問は、おそらくSecurity StackExchangeに関するより専門的な回答を得るでしょう。


3
これに完全に同意します。クライアント側のアプローチが機能するためには、saltをクライアントに送信する必要もあります。これは、saltの目的全体を無効にします。
James Wright

@JamesWright:ポイントは、使用ごとにランダムなソルトを送信することで、ログインメッセージの不正な再利用を防止します。(再生攻撃の一種)。毎回同じソルトを送るのは実に無意味です。
MSalters 2017年

あなたがする必要があるのは「ノンス」を使用することです(en.wikipedia.org/wiki/Cryptographic_nonce)。このようにして、サーバーはソルトも制御し、これを安全にします。挿入されたJSコードが後で簡単に見つけることができないように、クライアント側でのハッシュも重要です。詳細:stackoverflow.com/a/21716654/43615
Thomas Tempelmann

:ログイン認証プロセス中の塩+ナンスを使用するために、この答えを参照stackoverflow.com/a/24978909/43615
トーマスTempelmann

明らかに、クライアント側でハッシュする場合は、サーバー側でもう一度ハッシュして、目的を達成しないようにする必要があります。ただし、他の人が指摘しているように、プライバシーのためには、クライアント側の暗号化がすでに必要です。
Daniel Methner

5

パスワードを第三者に対して安全に保つことだけがすべてではないことに注意してください。

すぐに、プライバシーとして関与している(そして今までそれがないときは、これらの日は?)あなたは、パスワードを知っている必要はありません。あなたが持っていないものを悪用したり漏らしたりすることはできません。そのため、クリアテキストのパスワードを決して見なければ、あなたもクライアントもよりよく眠ることができます。

したがって、ハッシュ/暗号化クライアント側は理にかなっています。


同意しました!多くの人がこの点を見逃しています。ソルトハッシュされたパスワードのパスワードデータベースをダウンロードし、ハッシュルックアップデータベースを使用して1つだけをクラックできる場合、それらすべてをクラックできる可能性があります。元のパスワードが5万個になったら、サーバー上でのみ暗号化するサービスのxユーザーへの鍵が手に入りnます。各サービスがクライアントを離れる前にパスワードを一意にハッシュする場合、クロスサービスパスワードの大規模なデータベースははるかに小さくなります。AWSのログイントラフィックを確認し、何を行うかを確認します。それは私の愛するワトソンの確率です。
f1lt3r 2018


1

私は最近これについて多くの作業を行ってきましたが、IRLはクライアント側のハッシュ/ 対称暗号化に2つの問題があり、本当にアイデアを殺します:1.サーバーに塩を戻す必要がありますSOMEHOW ...そして暗号化するにはクライアント側ではパスワードが必要です...これは目的に反します。2.ハッシュ実装を公開します(ほとんどのサイトは3つまたは4つのハッシュアルゴのいずれかを使用するため、大規模な取引ではありません)。これにより、攻撃が容易になります(nではなく1つだけ試す必要があるため)。

私が最終的に行ったのは、OpenPGP.jsなどを使用したクライアントでの非対称暗号化でした...これは、クライアントでインポートまたはクライアント側で生成された鍵と、サーバーがその公開鍵を送信することに依存しています。クライアントの公開鍵のみがサーバーに送り返される場合があります。これはMIM攻撃から保護し、デバイスと同じくらい安全です(私は現在、クライアントの秘密キーをデフォルトでlocalStoreに保存しています。これはデモです)。

これの主な利点は、ユーザーデータをサーバーやデータストアの暗号化されていないメモリに保存する必要がないことです(サーバーの秘密キーは物理的に独立しています)。

これの基本は、HTTPSが制限されている場所(Iran / N. Korea atc​​ ...など)で安全に通信する方法を人々に提供することと、単なる楽しい実験を提供することでした。

これを最初に考えたのはFARです。http://www.mailvelope.com/はこれを使用します


1

誰かがあなたの接続でデータを見ることができれば、認証はあなたを救うことはありません。代わりに、私は超秘密のもののために次のことをします。

パスワードは、サーバーに送信される前にクライアント側でハッシュ化されています。(サーバーは、ブラウザーから送信されたハッシュの別のハッシュ値とソルト値を保存します)。

そのため、中間者攻撃では、同じハッシュ値を送信してログインすることを許可する可能性がありますが、ユーザーのパスワードは不明です。これにより、他の場所にログインするために同じ資格情報を使用して他のサービスを試行するのを阻止します。

ユーザーのデータもブラウザー側で暗号化されます。

ああ、そのため、中間者攻撃は暗号化されたデータを取得しますが、ログインに使用された実際のパスワードなしではデータを復号化できません。(ログイン時にブラウザのDOMに保存されているユーザーパスワード)。したがって、実際のユーザーは復号化されたコンテンツを見ることができますが、仲介者は見ることができませんでした。これはまた、NSAまたは他の機関があなた/会社/ホスティングプロバイダーにこのデータの復号化を要求できないことも意味します。

これらの両方の方法のいくつかの小さな例が私のブログにあり ますhttp://glynrob.com/javascript/client-side-hashing-and-encryption/


1

最近、GitHubとTwitterの両方が、パスワードが内部ログに保存されることを発表しました。バグ報告や、splunkに侵入したその他のログで不注意にこれが発生したことがあります。Twitterの場合、トランプのパスワードがそこにあった場合、管理者が「確認」するのは大変であり、他のサイトではおそらく管理者はそれをあまり使用しないため、大きな問題になります。管理者とは関係なく、パスワードを見ることは好きではありません。

したがって、問題は、セキュリティのためにクライアント側でハッシュを実行する必要があるかどうかですが、最終的にハッシュされてサーバー側で比較される前にパスワードを保護して、なんらかの方法でログに記録されないようにする方法です。

暗号化は悪い考えではありません。少なくとも開発者はいくつかのフープを飛ばさなければならないので、パスワードがログに記録された場合、暗号化キーを変更するだけで元のキーを破壊でき、そのデータは役に立たなくなります。しかも、キーを毎晩ローテーションすると、ウィンドウが大幅に縮小される可能性があります。

ユーザーレコードのハッシュをハッシュすることもできます。漏洩したパスワードは、ハッシュされたプレーンテキストのパスワードになります。サーバーは、ハッシュされたバージョンのハッシュを格納します。確かにハッシュはパスワードになりますが、写真の記憶がなければ、60文字の文字列を思い出すことはできません。ユーザー名でソルトします。ログインプロセス中にユーザーについて何かを収集できた場合(ユーザーレコードが存在することを公開していない場合)、それを加味して、サイト間で共有できないより堅牢なハッシュを作成できます。真ん中の人は、サイト間でキャプチャされたハッシュをカットアンドペーストすることはできません。

サーバーに送信されないCookieと組み合わせると、何かにアクセスする可能性があります。最初のリクエストで、キーを使用してCookieをクライアントに送信します。次に、Cookieがログインサービスに戻らないようにして、ログに記録される可能性がほとんどないようにします。キーをセッションストアに保存し、ログインが発生した直後またはセッションが期限切れになったときに削除します。これには、JWT担当者の状態が必要ですが、おそらくnosqlサービスを使用するだけです。

そのため、管理者は、splunkまたはバグ報告ツールでこれらのハッシュ化および暗号化されたパスワードのいずれかに遭遇します。彼らが暗号化キーを見つけることができなくなったとしても、彼らは役に立たないはずです。たとえ彼らが見つけたとしても、彼らはブルートフォースハッシュをしなければなりません。さらに、エンドユーザーは平文を何も送信しなかったため、途中の人は少なくとも苦労し、別のサイトにアクセスしてログインすることはできません。


まさに私の懸念。実装の悪さや悪意のせいで何らかの理由でサーバーが偶然にログに記録した場合、パスワードを再利用すると、ユーザーの他のアカウントが侵害される可能性があります。
Dan

0

このことを考慮:-

クライアントがサーバーにリクエストを送信します「検証するパスワードがあります」。

サーバーはクライアントに1回限りのランダムな文字列を送信します。R $

クライアントはこの文字列にユーザーのパスワードを埋め込みます(適用したい(変数)ルールに基づいて)。

クライアントは文字列をサーバーに送信し、パスワードがOKの場合、サーバーはユーザーをログインさせます。

サーバーがR $を使用して別のログイン要求を受信すると、ユーザーはログアウトされ、アカウントは調査が保留されるまで凍結されます。

明らかに、他のすべての(通常の)セキュリティ対策が取られます。


0

このクライアント側ハッシュの考え方は、サイトではなくユーザーを保護することです。すでに何度も述べたように、プレーンテキストまたはハッシュ化されたパスワードはどちらもサイトへのアクセスが等しくなります。セキュリティ上のメリットはありません。

しかし、ユーザーの実際のプレーンテキストのパスワードは、ユーザーだけが知っているべきです。彼らがパスワードとして選択したものを知ることは、他のサイトやシステムでそれらに対して使用できる情報です。サーバー開発者やサードパーティによってパスワードの選択が発見されるのを防ぐことで、顧客中心のサイトになっています。

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