- ブラウザURL入力
- DNS名前→IP今ここ
- ルータ経路選択
- ロードバランサ振り分け
- Nginx受け口
- アプリ処理
- DB保存
第43週『なぜ盗み見できるのか — 平文と経路上の第三者』で、攻撃者が書き込むかどうかの線を見ました。今回はその書き込む先が、経路上ではなくキャッシュである場合です。
まず結論
リゾルバは自分が出した問いへの答えを待っています。UDPに接続の概念は無く、「正しい相手から来た」と確かめる材料は宛先ポートとQuery IDだけ。本物より先にそれらしい応答が届けば、受け入れてキャッシュに入れます。
RFC 5452 が示す措置の本質は、暗号ではなく**当てる対象を増やすこと**です。RFC が書くのは「成功しなくなる」ではなく「成功までの時間が延びる」ことです。
偽のDNS応答を送り込む攻撃者は、本物より先に応答を届ける必要があります。それ以外に当てなければならないものは何でしょうか。
当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。
待っている側は、何を材料に相手を確かめるか
第43週『なぜ盗み見できるのか — 平文と経路上の第三者』で、RFC 3552 §3.1 を見ました。
Any attack which requires the attacker to write to the network is known as an ACTIVE ATTACK.
キャッシュポイズニングも書き込む攻撃ですが、書き込む先が経路上ではなくキャッシュである点が違います。
問い合わせを出した瞬間、リゾルバは「自分が出した問いへの答え」を待ちます。素のDNSはUDPで、接続もハンドシェイクもなく、届いたパケットの中身だけが手がかりです。照合できるのは次に限られます。
- 応答が届いた宛先ポート番号(問い合わせに使った送信元ポート)
- 応答ヘッダのQuery ID — RFC 1035 §4.1.1 の定義で 16ビット
- 問い合わせた名前・タイプ・クラスとの一致
送信元ポートが毎回同じなら、そこは当てる必要すらありません。
キャッシュに入ると何が起きるか
なぜ「キャッシュに入る」ことが効くのか。RDビットを落として公開リゾルバへ問い合わせた実測(macOS 26.5.2、DiG 9.10.6、2026-09-17 22:41 JST)です。
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7770;; flags: qr ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1;; QUESTION SECTION:;example.com. IN A;; ANSWER SECTION:example.com. 115 IN A 104.20.23.154example.com. 115 IN A 172.66.147.243
読みどころは2つ。まず flags: に rd がありません。再帰を望まないと指定しても、回答が2件返る。次にTTLが 115 という半端な値で、キャッシュに入ってから経過したぶんだけ減っている。外へ問い合わせずに箱の中身を出したものです。
これが、書き込む先としてキャッシュが選ばれる理由です。 一度偽の値が入れば、TTLが切れるまで全利用者へ確認なしに配られ続けます。
リゾルバがUDPの応答を「正しい相手から来た」と判断する材料に、含まれないのはどれですか。
対策の本質は、当てる対象を増やすこと
RFC 5452 が示す措置は暗号ではなく、当てなければならないものを増やす、それだけです。§9.2 は MUST を3項目並べます。
o Use an unpredictable source port for outgoing queries from the range of available ports (53, or 1024 and above) that is as large as possible and practicable;
o Use multiple different source ports simultaneously in case of multiple outstanding queries;
o Use an unpredictable query ID for outgoing queries, utilizing the full range available (0-65535).
ポートのランダム化、複数ポートの同時使用、Query IDのランダム化。この後に、複数のIPアドレスも予測困難に使うべきという SHOULD が別段落で続きます。MUST は3つ、SHOULD は別です。
§9.2.1 は、出口が少数のリゾルバは送信元アドレスとポートに "effectively using constants" を使っており予測しやすい、と述べます。
§5 は別の増え方を扱います。同一のQNAME・QTYPE・QCLASSの未応答の問い合わせが複数あると、攻撃者のパケットはそのいずれかに一致すればよいので確率が上がる。原文は "rises linearly with the number of outstanding queries" の直後に "For larger numbers, this effect is less pronounced." と置きます。比例だけを引くと原文より強くなります。
同じ構造は、第16週にも出ていた
表を偽の情報で汚す構造は初出ではありません。第16週『MACアドレスとスイッチ — 同じ部屋の中の配達』で、MACアドレステーブルが溢れると、スイッチは既知だったはずの宛先まで未知として扱いフラッディングを始めることを見ました。偽の送信元MACでこの状態を作るのがMACフラッディング攻撃です。
要点は「スイッチは壊れてもいないし設定ミスもない。設計どおり動いている」でした。今回も同じで、リゾルバは照合できる材料を照合して受け入れているのです。
RFC 5452 §9.2 が MUST として求めている項目はいくつありますか。
リゾルバのキャッシュ
UDP上の1往復で応答を受け取り、宛先ポート・Query ID・問いとの一致だけを照合してキャッシュへ入れます。RFC 5452 が増やすのはこの幅です。
照合の材料 宛先ポート・Query ID・問いとの一致IDの幅 16ビット(0-65535)出所の証明 無い汚れた影響 TTLが切れるまで全利用者へ
MACアドレステーブル(第16週)
スイッチは通過したフレームの送信元から表を埋めます。エントリは「誰かがそこから喋った」という過去の証拠にすぎません。偽のMACで表を溢れさせるのがMACフラッディングです。
照合の材料 フレームの送信元MACと受信ポート埋まり方 通過したフレームから自動で(観測駆動)出所の証明 無い溢れた影響 未知扱いになり全ポートへ複製
どちらも「表を汚す」攻撃です。共通しているのは、何が信用されていることでしょうか。
表を埋めるとき「この情報は本当にその相手から来たのか」をどう確かめているでしょうか。
1回の書き込みが決めるもの
- ・RFC 5452 が増やすのは照合できる値の幅。ゼロにはならず、延びるのは所要時間(§8.1)
この章のまとめ
- 照合の材料は宛先ポートとQuery ID、問いとの一致だけ。IDは16ビット(RFC 1035 §4.1.1)。
- 書き込む先がキャッシュだから効く。1回の書き込みがTTLぶんの応答を決める。
- RFC 5452 §9.2 の MUST は3項目。複数IPアドレスは別段落の SHOULD。
- §8 は問題空間が64000倍、285Gb/s 超が要ると述べ、§8.1 では50%到達が7秒から約116時間へ。延びるのは時間で、ゼロにはならない。
- 「カミンスキー攻撃」は RFC 5452 に無い通称。VU#800113 は指摘を Dan Kaminsky に、原案を Daniel J. Bernstein に帰属させる。
- 表を汚す構造は第16週のMACアドレステーブルと同型。どちらも設計どおり動いたまま誤る。
自分の現場で確かめる
読んだだけでは身につきません。手元の環境で実際に見てみてください。
理解度チェック
読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。
RFC 5452 §8 が、宛先ポートも推測が要る場合について述べているのはどれですか。
用語集(4語)
- キャッシュポイズニング
- リゾルバのキャッシュに偽の応答を入れ込むこと。書き込む先が経路上ではない点が特徴で、一度入ればTTLが切れるまで全利用者へ配られる。
- Query ID
- DNSヘッダの16ビットの識別子。RFC 1035 §4.1.1 は、問い合わせを生成したプログラムが割り当て、応答へ複写され、突き合わせに使える、と定義する。
- ソースポートのランダム化
- 送信元ポートを広い範囲から予測できない形で選ぶこと。RFC 5452 §9.2 の MUST の1つ。当てる対象を増やし、成功までの時間を延ばす。
- off-path 攻撃者
- 本物の経路上に居らず、やり取りを読めない位置から偽の応答を送り込む攻撃者。RFC 7873 の DNS Cookie が対象とするのはこの種で、経路上の攻撃者は射程の外。