3

これは、MVC 4 でスキャフォールディングされたデフォルトの AccountController でパスワードを変更するためのコードです。

// ChangePassword will throw an exception rather 
//than return false in certain failure scenarios.
bool changePasswordSucceeded;
try
{
    string userName = User.Identity.Name;    
    changePasswordSucceeded = WebSecurity.ChangePassword(userName, 
                                                         model.OldPassword,
                                                         model.NewPassword);
}
catch (Exception)
{
    changePasswordSucceeded = false;
}

if (changePasswordSucceeded)
{
    return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
}
else
{
    ModelState.AddModelError("",
    "The current password is incorrect or the new password is invalid.");
}

私の問題は、メッセージが不明確であることです。現在のパスワードが正しくない場合は問題ありませんが、新しいパスワードが無効な場合は、ユーザーに何が問題なのかを伝えるより良いメッセージを提示したいと思います。また、「失敗のシナリオ」をよりよく理解し、調整できるようにしたいと考えています。メッセージ。

ここのドキュメントは例外に関するものであり、これらがアクションに飲み込まれ、無効なパスワードとして報告されるべきではないと思います。

では、なぜ「新しいパスワードが無効です」という可能性があるのでしょうか? アプリケーションで OAuth なしで SimpleMembershipProvider のみを使用している場合、それを削除できますか?

編集: NBこのデータ注釈は「RegisterModel」クラスにも表示されるため、ここでもパスワードの有効性チェックがあります

[StringLength(100, 
ErrorMessage = "The {0} must be at least {2} characters long.", 
MinimumLength = 6)]
4

1 に答える 1

5

概要

これは長い答えになったので、セクションに編集しました。私はrookのようなユーザーと比較してセキュリティの専門家ではありません。彼でさえ、自分のセキュリティの回答や他の人のセキュリティの回答を信頼しないように言っています。常に自分でテストして理解してください。これを読んでいる Web 開発者は、OWASP のトップ 10 の Web セキュリティの欠陥を読み、 Trustworthy ComputingやもちろんBruce Schneier 氏などのオンライン ガイダンスを使用する必要があります。セキュリティは複雑で、誰にとっても大きすぎるため、できる限りベスト プラクティスに従って機能するフレームワークを使用してください。何よりも、すべてを視野に入れておいてください。

これらの要約回答の詳細については、以下を参照してください。

  1. ユーザーへのメッセージは意図的にあいまいです。これはセキュリティ上の理由によるものであると主張できます (以下を参照)。
  2. 参考文献 「失敗のシナリオ」。主に、モデルの検証によってすでにキャッチされているはずの無効な入力、誤った現在のパスワード、またはエッジケースの例外が原因です。
  3. 元の開発者が怠け者だったか、すべてのケースに対して単一の戻りメッセージがあるべきだと信じていたため、例外は飲み込まれ、1 つとして表示されます (上記の 1 を参照)。
  4. 「新しいパスワードが無効です」は、属性が一致している限り、または ChangePassword 内の長さ制限よりも制限が厳しい限り、強調表示したコードの可能性はおそらくありません。ただし、上記の (1) を参照してください。
  5. 削除できますか? 上記 (1) を参照してください。
  6. 良い点です。議論については以下を参照してください。

元の回答 - 概念的な攻撃ベクトル

セキュリティの観点から考えてみてください。

  • 私はあなたのモバイル/タブレット/ラップトップをバー/コーヒー ショップのテーブル (または自宅/オフィスのデスクトップ コンピューター) に置きます。
  • 私はあなたのパスワードを知っているかもしれないと思います
  • 「パスワードの変更」に行き、あなたのパスワードではないと思われるものを入力します
  • 私は意図的に1文字の新しいパスワードを入れました

機械が教えてくれる

「現在のパスワードが正しくありません」

今、あなたの現在のパスワードは次のとおりだと思います。

「新しいパスワードが無効です」

私はあなたのパスワードを知っています。

脚注: ロジックの最初のセットを間違えて削除し、編集して再投稿しましたが、私はブルースではありません

似たような攻撃

この攻撃には多くの組み合わせがありますが、不正なログイン システムから電子メールを収集するようなものです。メールアドレスを使用して「パスワードを回復」しようとすると、次の 2 つの異なるメッセージが表示されたらどうなるか考えてみてください。

  • あなたのアドレスに電子メールが送信されました(データベース内の電子メールの場合)
  • あなたのメールアドレスが見つかりませんでした (明らかに偽のメールアドレスの場合)

そうすれば、そのユーザーに対する標的型フィッシング攻撃のためにあなたのサイトから有効なメンバーの電子メールを簡単に見つけることができます。または、スパム用の有効な電子メール アドレスのリストを作成することもできます。

可能な解決策

どちらの場合も、よりユーザーフレンドリーで安全なパスワード変更のエラー メッセージは次のようになります。

「現在のパスワードが正しくないか、新しいパスワードが無効です。パスワードは大文字と小文字が区別されることに注意してください。また、新しいパスワードには [ 64 文字 / 5 つの数字 / 4 文字/ ギリシャの神の名前 3 つ] が必要です」

正気を保つために、これはアプリケーションの使用状況にとどめておいてください。ただし、より大きなエコシステムでは責任があり、ユーザーは好むと好まざるとにかかわらず、ウェブサイト間でパスワードを共有することを忘れないでください。

ChangePassword が false を返すのはいつですか?

ChangePassword がいつ false を返すかについての質問部分について:

本質的にWebSecurity.ChangePassword

要約すると、次の場合に返されますfalse

  1. 引数のいずれかが null、空、または長さのチェックに失敗しました。また
  2. データベース接続が失敗します。また
  3. UserIdデータベースに存在しなくなりました。また
  4. 現在のパスワードが正しくありません。また
  5. (そして、明らかに、changePasswordSucceeded = false他の例外が発生した場合に設定されます)。
  6. への呼び出し内に有効性チェックはありません。 newPasswordChangePassword

したがって、理論的には、検証属性が適切に配置されていて、エッジ ケースを無視しているreturn false場合は、エッジ ケース (ユーザーが Get と Post の間で削除された、またはデータベースにアクセスできない) がある場合にのみ可能です。 、または現在のパスワードが無効です)。

IsValidこれは、アクション自体がモデルを呼び出すときに、攻撃者がブラウザの UI をバイパスする場合でも当てはまります。

クライアント側のメッセージ

ここで重大な免責事項があります。私はセキュリティに一生を費やしているわけではありません。私はセキュア・バイ・デザインの原則に従っており (例えば、OWASP トップ 10 プロジェクトについていくなど)、最も重要なセキュリティー原則を十分に認識していると信じています。したがって、このロジックの一部が間違っている可能性があります。

クライアント側の「パスワード要件」の検証がない場合、どうなりますか? ユーザーは、何が起こったのかを知るために Post が戻るのを待つ必要があります。

クライアント側の「パスワード要件」の検証ある場合、インターフェースが弱まりますか? 私はそうは思わない.:

  • サーバーは引き続き要件と現在のパスワード検証の両方を実行します
  • サーバーは 2 つの障害シナリオを区別しません (実際には違います。以下を参照してください)。
  • したがって、サーバーは、現在のパスワードが有効な場合にのみ有効であり、パスワードが変更された場合にのみ通知します。
  • うまくいけば、サイトも:
    • 古いパスワードに戻すのを防ぎます
    • パスワードが変更されたことを知らせる電子メール通知を送信します (おそらく 15 分間待って、攻撃者が開いたままの電子メールからパスワードを削除しないようにします。私たちのメールも開いています)

私の知る限り、MVCはこれらのことのいずれも行わないため、これが崩壊し始めるところです。

またModel.IsValid、アクション内のテストによりサーバーから別のエラーとメッセージが返されるため、別のエラーとメッセージが返されるため、この失敗に対して新しいパスワードの検証と別のエラー メッセージが強制されます。したがって、現在の実装では、単一エラー メッセージのアプローチには欠陥があります。

概要

それで、これがすべて行われる方法を変更できますか?時間内に他の部分を改善することを期待して、返信メッセージをもう少し長く、より有益なものに変更する以外は、おそらくそうしません。

これは個人的な意見であり、反対の意見もあるかもしれません


詳細:

実際のプロバイダーの実装は複雑になります。たとえばSimpleMembershipProvider

  • まだ初期化されていない場合は、「前のプロバイダー」に呼び出しを渡す可能性があります。
  • そうしないと、パスワード/ユーザー名が空、null、長すぎるなどの場合に(およびでArgumentExceptionsバブルアップ) がスローされる可能性があります。catchreturn falseMembershipUser.ChangePassword
  • それが起こらなければ、そうなるでしょう
    • データベースからを取得しようとUserIdします (失敗した場合は false を返します)。
    • 現在のパスワードが正しいことを確認します (失敗した場合は false を返します)。
    • そして最後に UPDATE クエリでパスワードを更新し、PasswordChangedDate進行中に設定します
  • 次に、MembershipUser
于 2013-05-14T18:26:05.620 に答える