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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions