utsuroi auth labs Lab 05 / 5 — Practitioner
05

予測可能なパスワードリセット token

Password reset token is built from predictable values

うつろい EC のパスワードリセット機能は、リセット token を base64(timestamp + user_id) で生成している。一見ランダムに見えるが、構造を解析すれば予測可能。

// PHP - 脆弱な token 生成
function generate_reset_token($user_id) {
    $payload = time() . ':' . $user_id;
    return base64_encode($payload);
}
// 例: base64('1720000123:42') = 'MTcyMDAwMDEyMzo0Mg=='

攻撃者は自分のリセットを実行して時刻を確認 → 被害者の user_id を推測 → 被害者の token を予測できる。

① 攻撃者として自分のリセット token を取得し、構造を解析
② 被害者(user_id=42 の store_admin)の token を予測して生成
③ その token でリセットページにアクセスして、被害者のパスワードを書き換える

01
攻撃者として自分のリセットを実行

攻撃者は自分のアカウント(user_id=109)でリセット要求を出し、生成された token を確認する。

02
被害者の token を予測して生成

攻撃者は構造を理解した。被害者の user_id(=42)を入れて、現在時刻と組み合わせれば被害者の token が作れる。

03
その token でリセットページにアクセス

予測した token でリセット完了画面にアクセス。サーバは「token と user_id が一致する」ことだけを見ているので、攻撃者でも被害者のパスワードを設定できてしまう。

脆弱な token 生成 vs 正しい token 生成
// 脆弱:予測可能な値を base64 エンコードしただけ
$payload = time() . ':' . $user_id;
$token = base64_encode($payload);
// → 攻撃者は構造を知れば再現可能
// 正しい:暗号論的にランダムな値
$token = bin2hex(random_bytes(32));  // 64文字の HEX
// または
$token = base64url(random_bytes(32));
// → 攻撃者は推測できない