AIセキュリティ 2025年7月15日

AIがパスワードを平文保存する問題と防止策

パスワードの平文保存は、最も基本的なセキュリティ違反の一つです。 **CodeRabbit 2025調査:** AIが生成するコードは、パスワードを安全に処理しないことが多いのです。 AIが生成しがちな危険なコードを見てみましょう。

川西智也

合同会社ロイヤルピース 代表

アンチパターン⑫「パスワード平文保存」

基本的なセキュリティ違反

パスワードの平文保存は、最も基本的なセキュリティ違反の一つです。

CodeRabbit 2025調査:

AI生成コードは不適切なパスワード処理の可能性が 1.88倍

AIが生成するコードは、パスワードを安全に処理しないことが多いのです。


【要注意】典型的な危険コードパターン

AIが生成しがちな危険なコードを見てみましょう。

危険なコード:

// ❌ 平文保存
app.post('/register', async (req, res) => {
  const { email, password } = req.body;
  
  await db.users.insert({
    email: email,
    password: password  // 平文!
  });
  
  res.json({ success: true });
});

// ❌ 弱いハッシュアルゴリズム
const hashedPassword = crypto.createHash('md5').update(password).digest('hex');
const hashedPassword = crypto.createHash('sha1').update(password).digest('hex');

// ❌ ソルトなし
const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');

なぜ危険なのか

平文保存が危険な理由を説明します。

問題1: データベース漏洩時の被害

  • データベースが漏洩すると、全パスワードが露出
  • 攻撃者はすぐにアカウントを乗っ取れる

問題2: パスワードの使い回し

  • ユーザーは同じパスワードを複数サービスで使用
  • 1つのサービスからの漏洩が、他のサービスにも影響

問題3: 内部犯行

  • データベースにアクセスできる従業員が見れる
  • 内部からの攻撃リスク

問題4: ログへの露出

  • エラーログにパスワードが記録される可能性
  • デバッグ時に平文が表示される

AI生成コードの弱いハッシュ問題:MD5, SHA1

MD5やSHA-1は、パスワードハッシュには不適切です。

理由:

  1. 計算が速すぎる

    • GPUで毎秒数十億回のハッシュ計算可能
    • ブルートフォースに弱い
  2. レインボーテーブル

    • 事前計算されたハッシュテーブルで即座に解読
  3. 衝突攻撃

    • 同じハッシュを持つ別の値を見つけられる

ベンチマーク:

アルゴリズム計算速度パスワード解読時間
MD5非常に速い数秒〜数分
SHA-1速い数分〜数時間
bcrypt遅い(意図的)数年〜数十年

実践的な解決策:正しいパスワード処理

パスワードを安全に処理する方法を解説します。

実践的な解決策1: bcryptを使用

const bcrypt = require('bcrypt');
const SALT_ROUNDS = 12;  // コストファクター

// ハッシュ化
async function hashPassword(password) {
  return await bcrypt.hash(password, SALT_ROUNDS);
}

// 検証
async function verifyPassword(password, hash) {
  return await bcrypt.compare(password, hash);
}

// 使用例
app.post('/register', async (req, res) => {
  const { email, password } = req.body;
  
  const hashedPassword = await hashPassword(password);
  
  await db.users.insert({
    email: email,
    password: hashedPassword
  });
  
  res.json({ success: true });
});

app.post('/login', async (req, res) => {
  const { email, password } = req.body;
  
  const user = await db.users.findByEmail(email);
  if (!user) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }
  
  const isValid = await verifyPassword(password, user.password);
  if (!isValid) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }
  
  // ログイン成功
});

実践的な解決策2: Argon2を使用(より新しい選択肢)

const argon2 = require('argon2');

// ハッシュ化
async function hashPassword(password) {
  return await argon2.hash(password, {
    type: argon2.argon2id,
    memoryCost: 65536,
    timeCost: 3,
    parallelism: 4
  });
}

// 検証
async function verifyPassword(password, hash) {
  return await argon2.verify(hash, password);
}

実践的な解決策3: コストファクターの設定

// bcryptのコストファクター
// 高いほど安全だが、処理時間も増加

const SALT_ROUNDS = 12;  // 推奨(約250ms)

// 参考値
// 10: 約65ms
// 11: 約130ms
// 12: 約250ms
// 13: 約500ms
// 14: 約1秒

// サーバーの性能に応じて調整

追加のセキュリティ対策

パスワードハッシュ以外の対策も重要です。

ブルートフォース対策

const rateLimit = require('express-rate-limit');

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分
  max: 5, // 5回まで
  message: 'Too many login attempts'
});

app.post('/login', loginLimiter, async (req, res) => {
  // ...
});

アカウントロックアウト

const MAX_ATTEMPTS = 5;
const LOCKOUT_TIME = 30 * 60 * 1000; // 30分

async function checkLockout(email) {
  const attempts = await db.loginAttempts.count(email);
  if (attempts >= MAX_ATTEMPTS) {
    const lastAttempt = await db.loginAttempts.getLastTime(email);
    if (Date.now() - lastAttempt < LOCKOUT_TIME) {
      throw new Error('Account locked');
    }
  }
}

プロンプトによるセキュリティ対策

AIにユーザー認証を依頼する際のプロンプト例です。

良いプロンプト:

ユーザー登録・ログイン機能を実装して:

## パスワード要件
- bcryptでハッシュ化(コストファクター12以上)
- 平文でのパスワード保存禁止
- MD5/SHA-1の使用禁止
- パスワードをログに出力しない

## 追加セキュリティ
- レート制限(5回/15分)
- アカウントロックアウト(5回失敗で30分)
- パスワード強度チェック

実装前チェックリスト

パスワード処理のチェックリストです。

コードレビュー時:

  • bcrypt/Argon2を使用しているか
  • コストファクターは適切か(12以上推奨)
  • 平文でパスワードを保存していないか
  • MD5/SHA-1を使用していないか

設定確認:

  • パスワードがログに出力されていないか
  • レート制限が設定されているか
  • アカウントロックアウトがあるか

この事例から学ぶべき教訓と実践ポイント

「パスワード平文保存」から学ぶべきことは以下の通りです。

  1. 1.88倍の不適切処理

    • AI生成コードはパスワード処理が甘い
  2. 平文保存は絶対禁止

    • データベース漏洩で全滅
  3. MD5/SHA-1は不適切

    • 速すぎてブルートフォースに弱い
  4. bcrypt/Argon2を使用

    • 意図的に遅い設計
  5. 追加対策も重要

    • レート制限、アカウントロック

まとめ:重要ポイントの振り返り

  • AI生成コードは不適切なパスワード処理が 1.88倍 (CodeRabbit)
  • 平文保存は絶対禁止
  • MD5/SHA-1は使用禁止 (速すぎる)
  • 解決策:bcrypt(コスト12以上)またはArgon2
  • 追加対策:レート制限、アカウントロック
  • プロンプトで パスワード要件を明示
  • 教訓:パスワードは必ずハッシュ化せよ

実践的なスキルを習得しませんか?

ブログで学んだ知識を、研修で実践に変えましょう。