Skip to content

[Security] 認証: パスワードリセットとセッション管理の改善 #1336

@nobuhiko

Description

@nobuhiko

概要

パスワードリセット機能、セッション管理、CSRFトークン生成、ログイン試行制限において、セキュリティ上の不備が複数存在します。

深刻度: Critical / High / Medium

脆弱性詳細

1. [Critical] 脆弱なパスワードリセット機構

ファイル: data/class/pages/forgot/LC_Page_Forgot.php (L228-238)

$new_password = GC_Utils_Ex::gfMakePassword(8);
$sqlval['password'] = $new_password;
SC_Helper_Customer_Ex::sfEditCustomerData($sqlval, $result[0]['customer_id']);

問題点:

  • セキュアなリセットトークンを使用せず、パスワードを即時変更
  • 新パスワードをメールで平文送信
  • FORGOT_MAIL == 0 の場合、通知なしにパスワードが変更される
  • セキュリティ質問によるリセットは推測・ブルートフォースに脆弱

修正案:

  • 時限付き(1時間等)リセットトークンをメールで送信するフローに変更
  • bin2hex(random_bytes(32)) でトークン生成
  • トークン検証後にユーザー自身が新パスワードを設定

2. [High] ログアウト時のセッション固定

ファイル: data/class/SC_Customer.php (L210-232)

public function EndSession()
{
    unset($_SESSION['customer']);
    SC_Helper_Purchase_Ex::unsetAllShippingTemp(true);
    SC_Helper_Session_Ex::destroyToken();
    // session_regenerate_id() が呼ばれていない
}

修正案: SC_Session_Ex::regenerateSID() をログアウト処理に追加

3. [Medium-High] 弱いCSRFトークン生成

ファイル: data/class/helper/SC_Helper_Session.php (L189-192)

public static function createToken()
{
    return sha1(uniqid(rand(), true));
}

問題点:

  • uniqid() はマイクロ秒ベースで予測可能
  • rand() は暗号学的に安全ではない

修正案:

public static function createToken()
{
    return bin2hex(random_bytes(32));
}

4. [Medium] ログイン試行のレート制限不足

ファイル: data/class/pages/frontparts/LC_Page_FrontParts_LoginCheck.php (L145-148)

sleep(LOGIN_RETRY_INTERVAL);

問題点:

  • sleep() のみでアカウントロックアウト機構なし
  • IP ベースのレート制限なし
  • 分散ブルートフォース攻撃に対して無防備

修正案:

  • 失敗回数のDB記録とアカウントロックアウト実装
  • 指数バックオフの導入
  • 一定回数失敗後のCAPTCHA要求

影響範囲

アカウント乗っ取り、セッションハイジャック、ブルートフォース攻撃によるアカウント侵害の可能性。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions