3

私の会社の CRM システムは、特定の管理機能を利用するために、ログインのたびにキャプチャ システムを利用しています。元の実装では、現在のキャプチャ値がサーバー側のセッション変数に格納されていました。

これを再開発して、必要なすべてのキャプチャ検証情報をハッシュされたクライアント側 Cookie に保存する必要があります。これは、アプリケーションに対してまだ認証されていないユーザーのセッションの使用を許可しないことでオーバーヘッドを削減することを目的とした親 IT ポリシーによるものです。したがって、認証プロセス自体は、サーバー側のストレージまたはセッションを使用できません。

このデザインはちょっとしたグループ作業でしたが、全体的な有効性については疑問があります. 私の質問は、以下に示す実装で明らかなセキュリティ上の問題を誰でも見ることができますか?それは過剰または不十分ですか?

編集: さらなる議論が更新された実装につながったので、元のコードを新しいバージョンに置き換え、このリビジョンに対応するように説明を編集しました。

(以下のコードは一種の疑似コードです。元のコードでは、読みにくい独特のレガシー ライブラリと構造が使用されています。うまくいけば、このスタイルで十分に理解しやすくなります。)

// Generate a "session" cookie unique to a particular machine and timeframe
String generateSessionHash(timestamp) {
    return sha256( "" 
        + (int)(timestamp / CAPTCHA_VALIDITY_SECONDS)
        + "|" + request.getRemoteAddr() 
        + "|" + request.getUserAgent() 
        + "|" + BASE64_8192BIT_SECRET_A
    );
}

// Generate a hash of the captcha, salted with secret key and session id
String generateCaptchaHash(captchaValue, session_hash) {
    return sha256( ""
        + captchaValue
        + "|" + BASE64_8192BIT_SECRET_B
        + "|" + session_hash
    );
}

// Set cookie with hash matching the provided captcha image
void setCaptchaCookie(CaptchaGenerator captcha) {
    String session_hash = generateSessionHash(time());
    String captcha_hash = generateCaptchaHash(captcha.getValue(), session_hash);
    response.setCookie(CAPTCHA_COOKIE, captcha_hash + session_hash);
}

// Return true if user's input matches the cookie captcha hash
boolean isCaptchaValid(userInputValue) {
    String cookie = request.getCookie(CAPTCHA_COOKIE);
    String cookie_captcha_hash = substring(cookie, 0, 64);
    String cookie_session_hash = substring(cookie, 64, 64);
    String session_hash = generateSessionHash(time());
    if (!session_hash.equals(cookie_session_hash)) {
        session_hash = generateSessionHash(time() - CAPTCHA_VALIDITY_SECONDS);
    }
    String captcha_hash = generateCaptchaHash(userInputValue, session_hash);
    return captcha_hash.equals(cookie_captcha_hash);
}

概念:

  1. 「session_hash」は、同じ Cookie が複数のマシンで使用されるのを防ぐことを目的としており、無効になるまでの期間を強制します。
  2. 「session_hash」と「captcha_hash」の両方に独自の秘密ソルト キーがあります。
  3. これらの BASE64_8192BIT_SECRET_A および _B ソルト キーは、サーバーに格納されている RSA 秘密キーの一部です。
  4. 「captcha_hash」は、シークレットと「session_hash」の両方でソルトされます。
  5. スプライシング攻撃を回避するために、クライアント提供のデータが使用される場所に区切り文字が追加されます。
  6. 「captcha_hash」と「session_hash」はどちらもクライアント側の Cookie に保存されます。

編集: re:Kobi フィードバックありがとうございます!

(コメントで返信しますが、質問で機能するフォーマットを受け入れないようですか?)

ログイン ページにアクセスするたびに、キャプチャが置き換えられます。ただし、これは、ログイン フォーム ページをリロードせずに単純に再送信しないことを前提としています。セッションベースの実装では、有効期限を使用してこの問題を回避します。ログイン ページに nonce を追加することもできますが、そのためにもサーバー側のセッション ストレージが必要になります。

Kobi の提案によると、ハッシュ化されたデータに有効期限の時間枠が含まれるようになりましたが、セッションにタイムアウトがあることは直感的であるため、代わりにそれを session_hash に追加することがコンセンサスです。

一部のデータをハッシュし、そのデータに別のハッシュを含めるというこの考えは、私には疑わしいようです。それとも、関連するすべてのデータ (時間、IP、ユーザー エージェント、Captcha 値、および秘密鍵) を含む単一のハッシュを使用する方がよいのでしょうか。この実装では、基本的にハッシュ化された平文の一部をユーザーに伝えています。

質問:

  1. 明らかな欠陥はありますか?
  2. 微妙な欠点はありますか?
  3. より堅牢なアプローチはありますか?
  4. ハッシュを別のハッシュでソルトすることは何かを助けていますか?
  5. よりシンプルで同等に堅牢なアプローチはありますか?

新しい質問:

個人的には、サーバー側のセッションのままにしておく方がよいと思います。すべての検証データをクライアント側のみに送信することの固有のリスクを証明または反証する論文または記事を誰か教えてもらえますか?

4

1 に答える 1

4

ここに記載されている以外のセキュリティがないと仮定する
と、攻撃者はキャプチャを一度解決し、Cookie を保存できるようです。
彼女は定数session_hashとを持っていcaptcha_hashます。彼女が同じハッシュ データを含む同じ Cookie を送信することを妨げるものは何もありません。システムが壊れる可能性があります。これは、の一部として
使用することで回避できます (偶数時間、場合によっては数分に丸める必要があります。現在の時間と以前の時間の 2 つのオプションを確認します)。timecaptcha_hash

冷静に、あなたは言いました:

「session_hash」は、同じ Cookie が複数のマシンで使用されるのを防ぐことを目的としています。

本当?
あなたisCaptchaValidがやっているString session_hash = substring(cookie, 64, 64);- つまり、 Cookie のデータに依存しています。別のコンピューターからコピーされたものではないことをどのように判断できますか? -確認のためにクライアントデータを再度ハッシュしていません(実際、そこには乱数があるため、不可能な場合があります)。それが新しいリクエストであり、使用されていなかったとどのように判断できますか?

ログインごとにキャプチャが置き換えられることは承知していますが、リクエストがいつ行われたかをどのように知ることができますか? 新しい captcha をチェックしていません。isCaptchaValid表示された captcha と一致しない場合でも、コードはリクエストを検証します。
次のシナリオを検討してください (自動化できます)。

  1. ログインページを開きます。
  2. 新しい Cookie と新しいキャプチャを取得します。
  3. 彼女の古い cptcha のハッシュ化されたデータを使用して、古い Cookie に置き換えます。
  4. 古い Cookie とuserInputValue古いキャプチャ ワードを送信します。
  5. この入力を使用isCaptchaValidして、リクエストを検証します。 captcha_hashsession_hashuserInputValueおよびBASE64_8192BIT_SECRETはすべて、最初のリクエストと同じです。

ちなみに、ほとんどのシステムでは、XSS を回避するために nonce が必要であり、nonce があれば問題も解決します。

于 2009-10-26T06:40:48.533 に答える