DNSキャッシュポイズニングは、
DNSキャッシュサーバに偽のDNS情報を記憶させ、利用者を誤った宛先へ誘導する攻撃
です。
この説明だけでも概要は分かりますが、
- そもそもDNSキャッシュサーバは何をしているのか
- なぜ偽の応答を受け入れてしまうのか
- なぜ送信元ポート番号のランダム化が対策になるのか
- DNSSECを使うと何が変わるのか
まで理解するには、DNSの名前解決から順番に整理すると分かりやすいです。
この記事では、DNSキャッシュポイズニングの仕組みを、DNSの基本から順番に見ていきます。
まず、DNSは何をしているのか
ブラウザで、
example.com
と入力しても、実際の通信ではドメイン名ではなくIPアドレスが必要になります。
そこでDNSを使って、
example.com
↓
203.0.113.10
のように、ドメイン名からIPアドレスを調べます。
この処理を名前解決といいます。
名前解決の流れをかなり単純化すると、次のようになります。
ここで登場するものを整理します。
再帰DNSリゾルバ
利用者の代わりにDNSを調べて、最終的な答えまで取得してくれるDNSサーバです。
利用者からすると、
example.comのIPアドレスを調べてきて
と依頼する相手になります。
TLD
TLDは Top-Level Domain の略です。
例えば、
example.com
↑
.com
の .com や、
example.jp
↑
.jp
の .jp がTLDです。
権威DNSサーバ
そのドメインについて、
このドメインの正式なDNS情報はこれです
と回答するDNSサーバです。
例えば example.com の権威DNSなら、
example.com → 203.0.113.10
という正式なDNSレコードを管理しています。
なぜDNSはキャッシュするのか
毎回、
再帰DNSリゾルバ
↓
ルートDNS
↓
TLD DNS
↓
権威DNS
まで問い合わせるのは効率がよくありません。
そこで再帰DNSリゾルバは、一度取得したDNS情報を一定時間保存します。
これがDNSキャッシュです。
これによって、
- 名前解決が速くなる
- 権威DNSへの問い合わせを減らせる
というメリットがあります。
DNSリゾルバは、DNSレコードに設定されたTTLなどに従って回答をキャッシュします。
しかし、ここに問題があります。
もし偽のDNS情報をキャッシュしてしまったら、その偽情報まで再利用されてしまいます。
DNSキャッシュポイズニングとは
DNSキャッシュポイズニングとは、
偽のDNS応答をDNSキャッシュに記憶させる攻撃
のことです。
poisoning は「毒を盛る」という意味なので、
DNSキャッシュに偽情報という毒を入れる
と考えると名前も理解しやすくなります。
例えば、本来、
example.com
↓
203.0.113.10
であるところに、
example.com
↓
192.0.2.66
という攻撃者のサーバのIPアドレスを覚え込ませます。
実際の攻撃成立条件はもっと複雑ですが、重要なのは、
本物のDNS応答に見える偽応答をリゾルバに受け入れさせる
という点です。
一度キャッシュが汚染されると、そのリゾルバを使っている複数の利用者が誤ったIPアドレスを受け取る可能性があります。
なぜ偽のDNS応答を受け入れてしまうのか
DNSリゾルバは、
このDNS応答は、さっき自分が送った問い合わせに対する回答か?
を判断する必要があります。
そのための識別情報の一つに**トランザクションID(問い合わせID)**があります。
かなり単純化すると、
DNS問い合わせ
ID: 12345
example.com は?
を送ったなら、
DNS応答
ID: 12345
example.com = 203.0.113.10
のように、対応するIDが付いた回答を受け取ります。
攻撃者が偽応答を成功させるには、こうした問い合わせ情報を正しく推測する必要があります。
なぜ送信元ポート番号のランダム化が対策になるのか
仮にDNSリゾルバが、権威DNSへの問い合わせに毎回同じUDPポートを使っていたとします。
毎回
送信元ポート: 12345
これでは攻撃者からすると予測しやすくなります。
そこで、
1回目 → 38192
2回目 → 52013
3回目 → 24781
のように、問い合わせごとに送信元ポートをランダム化します。
すると攻撃者は、少なくとも概念上、
問い合わせIDは何か?
+
送信元ポートは何番か?
の両方を当てる必要があります。
つまり送信元ポートのランダム化は、
偽応答を成立させるために攻撃者が当てなければならない情報を増やす
対策と考えられます。
ただし、これは偽応答を当てにくくしているのであって、
受け取ったDNS情報そのものが本物である
と証明しているわけではありません。
そこで出てくるのがDNSSECです。
秘密鍵と公開鍵はどういう仕組みなのか
DNSSECを理解するには、秘密鍵と公開鍵の役割を先に整理しておくと分かりやすくなります。
この2つは、公開鍵暗号方式で使われる対になる鍵です。
秘密鍵
→ 所有者だけが持つ
公開鍵
→ 他の人に公開してよい
2つの鍵には数学的な関係がありますが、公開鍵を知っていても、そこから秘密鍵を現実的な時間で求めることは困難になるように設計されています。
暗号化と電子署名は目的が違う
公開鍵と秘密鍵は、暗号化だけでなく電子署名にも使われます。
DNSSECで重要なのは電子署名の方です。
暗号化の場合
「他人に内容を読まれたくない」という目的なら、典型的には受信者の公開鍵を使って暗号化し、受信者が秘密鍵で復号します。
この場合、秘密鍵を持っている受信者だけが内容を読めるようにすることが目的です。
電子署名の場合
電子署名では目的が変わります。
そのデータを本当にその所有者が作ったのか
途中で改ざんされていないか
を確認します。
署名を作る側は秘密鍵を使い、検証する側は公開鍵を使います。
ここで重要なのは、
秘密鍵
→ 署名を作るために使う
→ 外部には公開しない
公開鍵
→ 署名を確認するために使う
→ 公開してよい
という役割です。
なぜ公開鍵で検証できるのか
電子署名では、まず元データからハッシュ値を計算します。
元データ
↓
ハッシュ関数
↓
固定長のハッシュ値
ハッシュ値は、元データが少しでも変わると大きく変化します。
例えば、
example.com → 203.0.113.10
というDNS情報が、
example.com → 192.0.2.66
に書き換えられれば、計算されるハッシュ値も変わります。
署名する側は、このデータに対応する電子署名を秘密鍵を使って生成します。
検証する側は、
- 受け取ったデータから自分でもハッシュ値を計算する
- 公開鍵を使って電子署名を検証する
- 署名がそのデータに対して正しいか確認する
という処理を行います。
そのため、攻撃者がDNSレコードを書き換えても、正しい秘密鍵を持っていなければ、その変更後のデータに対する有効な署名を作ることができません。
DNSSECではどう使われるのか
DNSSECでは、権威DNS側が秘密鍵を保持し、DNSレコード群に対する電子署名を作ります。
権威DNS
├─ DNSレコード
├─ 秘密鍵
└─ 電子署名を生成
一方、検証するDNSリゾルバは公開鍵を使って署名を確認します。
DNSSEC対応リゾルバ
├─ DNSレコードを受信
├─ 電子署名を受信
├─ 公開鍵を取得
└─ 署名を検証
DNSSECでは、公開鍵は DNSKEY レコードとして公開され、署名は RRSIG レコードとして提供されます。
概念的には、
DNSKEY
→ 公開鍵
RRSIG
→ DNSレコードに対する電子署名
という対応です。
ただし、
「その公開鍵自体が本当に正しいものなのか」
という問題も残ります。
そのためDNSSECでは、親ゾーンに登録された DS レコードなどを使って、
ルート
↓
TLD
↓
example.com
↓
DNSKEY
↓
DNSレコード
という**信頼の連鎖(Chain of Trust)**を作ります。
つまりDNSSECは、
秘密鍵で署名を作り、公開鍵で検証する
という公開鍵暗号の仕組みに、
その公開鍵自体を上位のDNSから信頼できるようにつなぐ
仕組みを組み合わせたものです。
秘密鍵と公開鍵で最低限覚えること
| 項目 | 秘密鍵 | 公開鍵 |
|---|---|---|
| 誰が持つか | 所有者だけ | 公開してよい |
| 電子署名 | 署名を作る | 署名を検証する |
| DNSSECでの役割 | DNSレコードへの署名 | 署名の検証 |
| 漏えいしたら | 非常に危険 | 公開前提 |
特にDNSSECでは、
秘密鍵で署名
↓
公開鍵で検証
と覚えておけば、役割を取り違えにくくなります。
DNSキャッシュに入る情報は、誰が署名するのか
ここで少し混乱しやすいのが、
「DNSキャッシュサーバ自身が、キャッシュした情報に秘密鍵で署名するのか?」
という点です。
答えはいいえです。
DNSSECでは、キャッシュを持つ再帰DNSリゾルバが署名を作るのではなく、そのドメインを管理している権威DNS側が署名を用意します。
流れを単純化すると、次のようになります。
つまり、役割は次のように分かれます。
権威DNS
↓
秘密鍵を持つ
↓
DNSレコードに対する署名を作る
再帰DNSリゾルバ
↓
公開鍵を使う
↓
署名を検証する
↓
正しいと確認できた情報をキャッシュする
ここで大事なのは、
「キャッシュそのものにリゾルバが署名する」のではなく、「権威DNS側で署名されたDNS情報を、リゾルバが検証した上でキャッシュする」
という点です。
例えば、本来のDNS情報が、
example.com → 203.0.113.10
だとします。
権威DNS側では、このDNS情報に対する電子署名が用意されています。
一方、攻撃者が、
example.com → 192.0.2.66
という偽のDNS応答を送り込んだとしても、攻撃者は example.com の正しい秘密鍵を持っていません。
そのため、正しい電子署名を作ることができません。
DNSSEC対応リゾルバが公開鍵を使って検証すると、
偽のDNS情報
+
不正な署名
↓
公開鍵で検証
↓
検証失敗
となり、その情報を正しいDNS情報として受け入れないようにできます。
一度検証した後は毎回権威DNSまで取りに行くのか
毎回取りに行くわけではありません。
一度DNSSECの検証に成功した情報は、TTLの範囲内でキャッシュを利用できます。
1回目
権威DNS
↓
DNSレコード + 電子署名
↓
再帰DNSリゾルバ
↓
署名を検証
↓
正しいと確認
↓
キャッシュ
次の問い合わせでは、
2回目以降
ユーザー
↓
再帰DNSリゾルバ
↓
キャッシュ
↓
回答
という形で、権威DNSまで毎回問い合わせずに回答できます。
このときの感覚としては、
「このキャッシュ内容は、権威DNSが用意した署名を検証して正しいと確認できた情報か?」
と考えると分かりやすいです。
ただし、DNSSECを使っていないドメインまで「署名がないから不正」と扱うわけではありません。
DNSSECでは、上位ゾーンからの信頼の連鎖を使って、
- DNSSECで保護されていて、署名検証に成功した状態
- DNSSECで保護されているはずなのに、署名検証に失敗した状態
- そもそもDNSSECを導入していない状態
を区別します。
そのため、
DNSSEC対応ゾーンなのに署名を正しく検証できない
場合は問題になりますが、
DNSSECを導入していないゾーン
まで一律に不正扱いする仕組みではありません。
DNSSECでは何が変わるのか
DNSSECは Domain Name System Security Extensions の略です。
DNSレコードに電子署名を付けて、
- 本当に正しい送信元から来た情報なのか
- 途中で改ざんされていないか
を検証できるようにします。
かなり単純化すると、
攻撃者が、
example.com → 攻撃者のIP
という偽のDNSレコードを作ったとしても、正しい秘密鍵を持っていなければ、有効な電子署名を作れません。
そのため検証側で、
DNS情報
+
署名
↓
検証失敗
として検知できます。
ポートランダム化とDNSSECの違い
ここは混同しやすいところです。
| 対策 | 考え方 |
|---|---|
| 送信元ポートのランダム化 | 偽応答を当てにくくする |
| DNSSEC | DNS応答が本物か検証する |
つまり、
ポートランダム化
↓
攻撃成功の難易度を上げる
に対して、
DNSSEC
↓
受け取った情報の正当性を電子署名で確認する
という違いがあります。
DNSSECはDNS通信を暗号化するものではない
ここも混同しやすい点です。
DNSSECの主目的は、
真正性
「正しいところから来た情報か」
完全性
「途中で改ざんされていないか」
を確認することです。
DNS問い合わせの内容そのものを、
第三者から読めないようにする
仕組みではありません。
DNS通信を暗号化するものには、DoH(DNS over HTTPS) や DoT(DNS over TLS) があります。
DNSSEC・SPF・DKIMの違い
DNSを利用するセキュリティ技術には、DNSSEC以外にもSPFやDKIMがあります。
| 技術 | 何を確認するか |
|---|---|
| DNSSEC | DNSレコードの真正性・完全性 |
| SPF | メール送信元IPが許可されているか |
| DKIM | 電子メールの電子署名 |
DNSSECとDKIMはどちらも、
秘密鍵で署名
+
公開鍵で検証
という仕組みが登場します。
違いは何に署名しているのかです。
DNSSEC
→ DNSレコードに署名
DKIM
→ 電子メールに署名
と整理すると分かりやすくなります。
まとめ
DNSキャッシュポイズニングは、
DNSキャッシュサーバに偽のDNS応答を記憶させ、利用者に誤った名前解決結果を返させる攻撃
です。
流れとしては、
対策については、
送信元ポートランダム化
→ 偽応答を当てにくくする
DNSSEC
→ DNS情報が本物か電子署名で検証する
という違いがあります。
DNSキャッシュポイズニングだけを単独で覚えるより、
再帰DNSリゾルバ
↓
キャッシュ
↓
権威DNS
↓
偽応答
↓
ポートランダム化
↓
DNSSEC
までつなげて理解すると、DNS全体の仕組みも見えやすくなります。