Ana içeriğe geç
友田 陽大
実践ネットワーク攻撃と防御
セキュリティ
ネットワーク
TCP/IP
脆弱性診断
ホワイトハッカー
倫理的ハッキング

DNSスプーフィング・キャッシュポイズニングの仕組みと防御【2026】— RFC 5452 と DNSSEC で名前解決を守る

名前解決を乗っ取る DNS スプーフィング/キャッシュポイズニングを、Kaminsky 攻撃の原理から RFC 5452・DNSSEC(RFC 4033-4035)の防御まで体系的に解説。なぜ UDP の DNS は偽答を信じてしまうのか、送信元ポートランダム化・トランザクションIDがどう推測困難性を作るのか、そして DNSSEC の署名検証・DoH/DoT による暗号化までを、型安全なコードと設定例で示します。すべて自分のリゾルバに閉じた合法手順です。

Published
Reading time
9 min read
Author
友田 陽大
Paylaş

あなたがブラウザに bank.example と打ち込んだその瞬間、最初に起きるのは名前解決——ドメイン名をIPアドレスに変換する DNS の問い合わせです。もしこの一手を攻撃者に乗っ取られたら? URL バーには正しいドメインが表示されたまま、接続先だけが攻撃者のサーバーにすり替わります。これが DNSスプーフィングであり、リゾルバのキャッシュごと毒するキャッシュポイズニングは、一度の成功で多数の利用者を巻き込む、極めて影響範囲の広い攻撃です。

この記事は、ネットワークペンテストの全体像に続き、DNS 攻撃の原理を歴史的な Kaminsky 攻撃から解き、RFC 5452 と DNSSEC による防御を設定とコードで示します。根本にあるのは、初期DNSが UDP上の「認証なき応答」を信じてしまうという、TCP/IP の信頼の前提です。

安全地帯の徹底:本記事の検証は、すべて隔離ラボの**自分が立てたDNSリゾルバ(例 BIND/Unbound のローカル実験機)**に対してのみ行います。公開リゾルバや他者のDNSへ偽答を注入する行為は、不正アクセス禁止法違反であり、社会インフラへの攻撃です。検証してよいのは自分の資産だけ——法律の記事を必ず先に。


1. DNS が騙される仕組み — 「速く・それらしい偽答」

キャッシュDNSリゾルバが bank.example の問い合わせを受け、まだキャッシュにない場合、上位の権威サーバーへ問い合わせます。攻撃者の狙いは、正規の権威サーバーの応答より先に、偽の応答をリゾルバに信じさせることです。

リゾルバが偽答を受け入れてしまうには、偽答が次をすべて満たす必要があります。

正規応答とマッチさせるべき要素:
  1. トランザクションID(16ビット)が問い合わせと一致
  2. 送信元/宛先ポートが一致
  3. 質問セクション(QNAME/QTYPE)が一致
  4. 正規応答より「速く」届く(レース)

かつてリゾルバは送信元ポートを固定し、トランザクションIDも予測しやすい実装がありました。すると攻撃者が当てるべきは実質**16ビットのID(65,536通り)**だけ。さらにキャッシュ済みなら次のTTLまで待つ必要がありますが——

1.1 Kaminsky 攻撃(2008)— DNS を作り直させた一撃

2008年、Dan Kaminsky は決定的な手法を公表しました。存在しないサブドメイン(random123.bank.example)を大量に問い合わせ、それぞれに対して「bank.example の権威サーバーは攻撃者のIPだ」という委任(NS/glue)を含む偽答を撃ち込む。存在しない名前なのでキャッシュのTTL待ちを回避でき、何度でも高速に試行できる。一度当たれば、ドメイン全体の権威がキャッシュに毒として刻まれます。

これは「16ビットIDの推測は現実的に破れる」ことを示し、DNS の防御を根本から見直させました。その答えが次の RFC 5452 と DNSSEC です。


2. 防御①:RFC 5452 — 推測を「非現実的」にする

RFC 5452(Measures for Making DNS More Resilient against Forged Answers, 2009)は、偽答を受け入れにくくする実装ルールを標準化しました。中心はエントロピーの追加です。

  • 送信元ポートのランダム化:問い合わせごとに送信元UDPポートをランダムに選ぶ。攻撃者はIDに加えてポート(最大16ビット)も当てねばならず、組み合わせのエントロピーが実質約32ビットに跳ね上がる。総当たりは非現実的になる。
  • トランザクションIDのランダム化:予測可能なIDを避け、暗号的に乱数化する。
  • 0x20 エンコーディング(補助):QNAME の英字の大小をランダム化し、応答でそれが保たれるかを追加の検証材料にする。
# 自分のリゾルバが送信元ポートをランダム化しているかを確認(自分の資産で)
# 良い例:問い合わせごとに source port がばらける(高エントロピー)
dig +short porttest.dns-oarc.net TXT @127.0.0.1
#   → "GREAT" 等(リゾルバのポートランダム性の評価が返る)

重要な限界:RFC 5452 は「推測を困難にする」確率的防御であって、「不可能にする」ものではありません。経路上にいる(MITM 済みの)攻撃者にはエントロピーが意味をなさない。だから次の DNSSEC が要ります。


3. 防御②:DNSSEC — 「言った者勝ち」を暗号で終わらせる

DNSSEC(RFC 4033/4034/4035)は、DNS 攻撃への本質的な答えです。発想は明快——権威サーバーが応答にデジタル署名し、リゾルバがその署名を検証する。偽答は正しい署名を作れないため、検証で弾かれます。

DNSSEC の信頼の連鎖(chain of trust):
  ルート(.) の鍵 ──署名──► .example の鍵 ──署名──► bank.example のレコード
       ▲                                                    │
       └──── リゾルバはルートの鍵(トラストアンカー)から ◄────┘
              署名を辿って検証。1つでも署名が合わなければ SERVFAIL(拒否)
  • RRSIG:各レコードセットへの署名。
  • DNSKEY:検証に使う公開鍵。
  • DS:親ゾーンに置かれ、子ゾーンの鍵を保証する(連鎖の輪)。

検証が成功すると、応答に AD(Authenticated Data)ビットが立ちます。偽答は署名検証に失敗し、リゾルバは結果を返しません。

# DNSSEC 検証が効いているかを確認(AD フラグが立つか)
dig +dnssec bank.example @127.0.0.1
#   ヘッダの flags に "ad" があれば、署名検証済みの真正な応答
#   RRSIG レコードが応答に含まれる

3.1 アプリ/リゾルバ側で検証を「要求」する

権威ゾーンに署名してあっても、リゾルバが検証しなければ意味がありません。検証するリゾルバを使うことが利用者側の責務です。

import { Resolver } from "node:dns/promises";

/**
 * DNSSEC 検証を行うリゾルバ(例:ローカルの validating resolver)を明示的に指定する。
 * OS のデフォルトに任せず「検証するリゾルバ」へ向けることで、毒入りキャッシュを避ける。
 * 失敗(SERVFAIL)は握りつぶさず例外として扱い、安全側(接続しない)に倒す。
 */
export async function resolveValidated(hostname: string): Promise<readonly string[]> {
  const resolver = new Resolver();
  resolver.setServers(["127.0.0.1"]); // 検証する自前/信頼リゾルバ(Unbound 等)
  try {
    return await resolver.resolve4(hostname);
  } catch (err) {
    // SERVFAIL は「署名検証に失敗した可能性」を含む。曖昧なまま接続しない。
    throw new Error(`DNS resolution failed (possible DNSSEC failure) for ${hostname}: ${(err as Error).message}`);
  }
}

4. 防御③:DoH / DoT — 経路を暗号化する

DNSSEC は応答の**真正性(改ざんされていないか)**を守りますが、機密性(誰が何を引いたかを盗み見られない)は守りません。また、利用者からリゾルバまでの経路はなお平文です。ここを埋めるのが通信路の暗号化です。

  • DoT(DNS over TLS, RFC 7858:DNS を TLS(853番)で運ぶ。
  • DoH(DNS over HTTPS, RFC 8484:DNS を HTTPS(443)で運ぶ。検閲・盗聴に強い。
役割分担(両方が要る):
  DNSSEC  … 応答の真正性(偽答を弾く)        ← 権威〜リゾルバの「中身」を守る
  DoH/DoT … 経路の機密性・完全性(盗聴/改ざん) ← 利用者〜リゾルバの「経路」を守る

DNSSEC と DoH/DoT は競合ではなく補完です。前者は「答えが本物か」、後者は「経路が覗かれないか」。本番では両方を組み合わせます。


5. 設計者のためのチェックリスト

自社ドメインと名前解決を守るために、設計・運用で確認すべき点です。

  • 自社の権威ゾーンを DNSSEC 署名しているか(ドメインレジストラ/DNSサービスで DS を親に登録)。
  • アプリが向くリゾルバが DNSSEC 検証を行うか(マネージドリゾルバなら検証ポリシーを確認)。
  • リゾルバが送信元ポートをランダム化しているか(RFC 5452 準拠)。
  • クライアント〜リゾルバ間で DoH/DoT を使えているか。
  • DNS 解決失敗(SERVFAIL)を握りつぶさず、安全側(接続中止)に倒しているか。
  • そもそも最終防壁は TLS の証明書検証——名前解決が毒されても、正規証明書を持たない攻撃者サーバーには TLS が繋がらない(MITM 記事参照)。

多層で考える:DNS が毒されても TLS で守られ、TLS を狙う MITM は mTLS とゼロトラストで守られる。単一の防御に依存しないのがネットワークセキュリティの一貫した姿勢です。


6. まとめ

  • DNSスプーフィング/キャッシュポイズニングは名前解決を乗っ取る。Kaminsky 攻撃が16ビットID推測の危険を現実化し、DNS の防御を作り直させた。
  • RFC 5452:送信元ポート+IDのランダム化でエントロピーを約32ビット級へ。推測を非現実的にする確率的防御(経路上の攻撃者には無力)。
  • DNSSEC(RFC 4033-4035):署名と信頼の連鎖で偽答を弾く本質的防御。AD ビットが真正性の証。
  • DoH/DoT(RFC 7858/8484):経路の暗号化。DNSSEC(真正性)と補完関係で両方要る。
  • 最後はやはり TLS:名前解決が毒されても、証明書検証が攻撃者サーバーを拒む。多層防御。

次は、確立済みのTCP接続そのものを奪う**TCPセッションハイジャック / RSTインジェクション / IPスプーフィング**を、RFC 5961 の防御まで扱います。


私(友田 陽大)は、本番システムの DNS 設計(DNSSEC・プライベートDNS・解決失敗時のフェイルセーフ)と、TLS/証明書運用を含む“名前解決を信頼しきらない”設計を実装してきました。「自社ドメインを DNSSEC 署名したい」「DNS 解決の失敗が障害につながっている」「DoH/DoT を導入したい」——こうした名前解決の堅牢化を、攻撃者の視点で診断し、真正性と機密性の両輪で実装します。お気軽にご相談ください。

友田

友田 陽大

Bakanlık (METI) Ödülü kazanan bir ürünün geliştiricisi. TypeScript + Python + AWS ile SaaS, endüstriyel dijital dönüşüm ve üretime hazır üretken yapay zekâyı (RAG) gereksinimlerden altyapıya ve işletmeye kadar tek başıma uçtan uca sunuyorum.

Could this attack succeed on your network?

Network / infrastructure penetration testing & hardening

The L2–L4 attacks covered here — ARP spoofing, DNS poisoning, session hijacking, SYN flood, sniffing — I diagnose where your configuration breaks from an attacker's perspective, and design and implement RFC-compliant defenses (DAI, DNSSEC, RFC 5961, BCP 38, TLS/mTLS, WAF/DDoS protection). With experience building multi-layered networks on AWS multi-account (VPC, least-privilege IAM, GuardDuty, WAF), I help minimize the attack surface and move toward zero trust.

Hem proje bazlı işler hem de teknik danışmanlık için uygunum. 30 dakikalık ücretsiz bir görüşmeyle başlayın.

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

Bunlar da ilginizi çekebilir