web-dev-qa-db-ja.com

HTML5 sessionStorageにパスワードを保存しても安全ですか?

他のフィールドでの検証が失敗した場合にユーザーにパスワードの再入力を要求しないようにすることで、登録時のユーザーエクスペリエンスを改善しようとしています。これを実装するにはいくつかの方法があります。たとえば、セッションCookieを使用して、サーバー側でパスワードのハッシュを保存します。私は、サーバーに追跡させずにユーザー・パスワードをクライアント・サイドに一時的に保管するこの代替案を模索しています。この方法は実行可能ですか?関連するリスクは何ですか?

16

原則として、sessionStorageに保存される値は、同じスキーム+ホスト名+一意のポートに制限されます。ブラウザに正常な出口がある場合、これらの値はセッションの最後に削除する必要があります。ただし、 この投稿 によると、クラッシュ後にユーザーが「セッションを復元」することを選択した場合、ブラウザーの再起動後も存続する可能性があります(つまり、値が消去されるまでその値も永続メモリに存在するため、念頭に置いて)。うまく実装されていれば、特にCookieを使用する代替手段(私が考慮しない多くの落とし穴がある)と比較して、それは十分に安全だと思います。 W3C仕様には、Web Storage 実際に機密データを格納するために使用される可能性があります (その手法が承認されているかどうかは不明ですが)も記載されています。

リスクに関しては、それは単にトレードオフの問題です。つまり、サイトがユーザーにとって少し便利になると同時に、パスワードが(XSSの脆弱性を利用して)キャプチャされる機会を少し増やします。意図したよりも長い間、またはユーザーが登録を完了する前にコンピューターを無人のままにしておくことで、永続的ストレージに永続的に残る値。理想的には、パスワードがRAMから出てはならないのが理想的ですが、これは通常、非現実的であるため、ある程度の妥協が必要です。登録が成功したらすぐにsessionStorageからパスワードを消去し、最終的に明らかになる可能性のあるsessionStorage実装の脆弱性を監視することをお勧めします。

14
mgibsonbr

別のアプローチを提案します。フォームをサーバーに送信する代わりに、XMLHttpRequestを使用してアカウントを作成します。サーバー側の検証が失敗した場合でも、フォームとそのすべてのコンテンツは引き続き使用できます。成功した場合は、ターゲットページにリダイレクトします。

これにはJavaScriptが有効になっている必要がありますが、それでも通常のフォーム送信にフォールバックできます。いずれにしても、SessionStorageへのアクセスにはJavaScriptも必要です。

8

格納されている2つの値のどちらをユーザーの意図したパスワードとして使用するか(ローカルストレージにあるものか、入力フィールドにあるもの)を決定するのは困難です。

これにより、ソーシャルエンジニアリングの攻撃ベクトルが提供される可能性があります。攻撃者は、登録フォームを開き、ローカル/セッションストレージに入力して独自のコードを使用し、後でそのトレース(入力エラー通知)をDOMで削除することにより、トラップを準備します。エディター、またはローカル/セッションストレージに目的のパスワードを直接入力し(両方とも一部のブラウザーでサポートされており、非常に簡単に実行できます)、後で被害者にWebサイトへの登録を依頼し、それを使用します。コードを簡単に検査/テストして、そのような場合の処理​​方法を確認できるため、攻撃者はこれを私が説明したものとは少し異なる方法で行う可能性があります(ローカル/セッションストレージに直接スクリプトインジェクションする場合でも、後で処理する場合は問題外ではありません)その値はローカルでフォームPOST)にありますが、同じ効果があります。

被害者はログアウトして再度ログインしようとするまで何も疑いません。ユーザーセッションの持続性によっては、このログアウトとログインのプロセスは必要ない場合があり、被害者は彼女に気付かなかったでしょう。 passwordは、パスワードフィールドに入力したパスワードではなく、攻撃者が選択したパスワードを使用して新しいアカウントを作成しました。

言うまでもなく、攻撃者は被害者が新しく作成したアカウントと被害者が入力したすべてのデータにアクセスできるようになりました。被害者が慎重で、ショルダーサーフィンが関与していないことを確認した場合でも同様です。

したがって、ここでの要点は、システムの同じ登録データに対して2つの異なる場所を処理する必要がある可能性があるということです。これは、何らかの理由で異なる場合があり、システムと、システムの両方に対して安全な方法で使用する場所を決定する必要があります。登録するエンドユーザー。これは適切に行うにはかなりトリッキーになるかもしれませんので、お勧めしません。

代わりに、登録フォームがHTTPS経由で提供されていることを確認し、ユーザーのPOSTリクエストで最後に入力されたため、パスワードフィールドに入力してください。他の入力フィールドのうち、正しく入力されていないため、フォームに再投稿する必要があります。

6
TildalWave

パスワードを永続ストレージ(cookie、localstorageなど)に保存する代わりに、いくつかのタブ間通信を使用してパスワードを配布します。解決策は無数にあります。evercookieを確認してください)。これにより、実際のドメインの最後のタブを閉じるまで、パスワードがブラウザに残ります。

BroadcastChannel または SharedWorker または postMessage を使用してタブ間通信を安全に行うことができます私が知らない他の方法ですが、それらは常に車輪を再発明しています。最初の2つはすべてのタブにメッセージを送信し、最後の1つは同じ親タブから開いたタブにのみ送信するため、多少制限がありますが、より多くのブラウザーでサポートされています。

パスワードをjsメモリに保存する場合は、 特別なヘッダー を使用してXSSを防止する必要があります。そしてofc。 HTMLタグの表示されたコンテンツを確認する必要があり、JavaScriptに変数として直接注入するデータを常にJSONエンコードする必要があります。

TildalWaveの投稿は興味深いものです。同期はほぼ瞬時に行われ、ログインやログアウトなども同期できるため、これらの方法は脆弱ではないと思います。

とにかくlocalstorageを使用する場合は、パスワード自体ではなく、署名されたユーザーID、タイムアウト、ソルトを使用することをお勧めします。資格情報をサーバーに送信してサーバーで検証し、署名付きのデータを送信することができます。これらは、Cookieまたは必要な永続ストレージに保存できます。これらのトークンは、ブラウザクライアントが存在する場合、REST APIによって使用されることがあります。これは、このソリューションがステートレスであり、クラシックセッションを持っている感覚を与えるためです。ユーザーだけでなく、すべてのリクエストに署名することもあります。セキュリティを強化するためのID。

0
inf3rno