「0.1秒の差」が命取り?タイミング攻撃で学ぶ、パスワード比較の落とし穴
こんにちは!セキュリティの世界へようこそ。
今日は、少しマニアックですが、非常に重要な「タイミング攻撃」というハッキング手法についてお話しします。「えっ、ハッキング?」と身構える必要はありません。まずは、私たちの身近な「家の鍵」を例にして、なぜプログラムがパスワードをチェックする時に「時間」を気にする必要があるのか、一緒に紐解いていきましょう。
1. 泥棒は「音」を聞いている?
想像してみてください。あなたは玄関の鍵を開けています。この鍵は少し特殊で、正しい鍵を差し込んで回すと「カチッ」と音がしますが、間違った鍵だと「ガリッ」という重い音がします。
もしあなたが泥棒だとしたらどうしますか?
何百種類もの鍵を試すとき、「ガリッ(失敗)」と鳴るまでの時間や音の違いを観察すれば、「あ、今の鍵は形が少し惜しかったな」とか「これは全く見当違いだ」ということが分かってしまいますよね。
プログラムの世界での「タイミング攻撃」もこれと同じです。
システムがパスワードをチェックする時、もし「1文字目が違うとすぐにエラーを返す」「3文字目まで合っていると少しだけ処理に時間がかかる」といった挙動をしていたらどうなるでしょう。攻撃者はその「わずかな応答時間の差」をストップウォッチで計るように計測し、1文字ずつ正解を導き出してしまうのです。
2. なぜ「==」で比較してはいけないのか
多くの初心者エンジニアが最初に書いてしまう、よくあるコードを見てみましょう。
// 危険な比較の例
if ($input_password == $saved_password) {
// ログイン成功!
}
この == という演算子は、プログラムにとって非常に効率的です。なぜなら、「違う文字が見つかった瞬間に、即座に比較を終了する」からです。
- 1文字目が違えば:即終了(0.001秒)
- 1文字目が合っているけど2文字目が違う:少しだけ計算して終了(0.002秒)
この「0.001秒の差」が、ネットワーク越しの何万回もの試行によって積み重なると、攻撃者には「あ、1文字目は『A』で合ってるな」とバレてしまうのです。これがタイミング攻撃の正体です。
3. 「定数時間比較」という魔法の盾
では、どうすればいいのでしょうか?
答えは簡単。「パスワードが合っていようが間違っていようが、常に同じ時間だけかけて比較する」のです。これを「定数時間比較(Constant-time comparison)」と呼びます。
「答えが分かっていても、最後までちゃんと全部計算してから結果を返す」という、非常に誠実(?)なやり方です。これなら、攻撃者がいくら時間を計っても、常に一定の結果しか返ってこないので、情報のヒントを一切与えません。
PHPで実装する場合、以下のように書くのが正解です。
// 安全な比較:hash_equalsを使う
// 常に一定の時間をかけて比較するため、時間の差で推測されることがありません
if (hash_equals($saved_password, $input_password)) {
// ログイン成功!
} else {
// ログイン失敗
}
この hash_equals という関数は、まさにこの「定数時間比較」をやってくれるセキュリティの味方です。自分でループを書いて比較しようとせず、必ず言語が用意しているこうした専用関数を使いましょう。
4. 今日からできるセキュリティの習慣
IT担当者や開発者の皆さんが、今日から現場で意識できるポイントをまとめました。
- 「失敗した理由」を詳しく教えない:
ログイン画面で「ユーザー名が違います」や「パスワードが違います」と細かく出し分けるのは、実は攻撃者にヒントを与えています。「ログインに失敗しました」とだけ返すのが鉄則です。
- 専用の関数を信頼する:
パスワードやAPIトークンの比較には、必ずその言語で「Constant-time」と書かれた比較関数(PHPなら hash_equals、Node.jsなら crypto.timingSafeEqual など)を選んでください。
- ライブラリを活用する:
認証処理をゼロから自作するのは非常に危険です。信頼できる認証ライブラリやフレームワークの標準機能を使うことが、最も安全で近道な対策になります。
最後に
「たかが0.001秒」と思うかもしれません。しかし、セキュリティの世界では、そのわずかな「隙(すき)」が大きなインシデントの入り口になります。
完璧な防御を目指すのは大変ですが、まずは「比較するときは時間を一定にする」というルールを覚えるだけで、あなたの書くコードはぐっと堅牢になります。一歩ずつ、安全な開発者への道を歩んでいきましょうね!
何か分からないことがあれば、いつでもまた聞きに来てください。応援しています!
コメント