こんにちは!ニナ(@_ninahaus_)🦆です。
昨日、C.R.E.A.M. FinanceとPancakeSwapのDNSハイジャック事件についてのまとめをアップしました。それらの記事を書く中で、DNSの仕組みと攻撃手法に関する理解がいまいち足りないなーと感じたので改めて調べてみました。
この記事で触れること
- そもそもDNSって何?
- DNSハイジャックって何?どう起こる?
- キャッシュポイズニングとは?


Domain Name System(DNS)とは
ホスト名やメールアドレスに使われる『ドメイン名』と、『IPアドレス』の紐づけを管理しています。インターネットに接続されているすべてのコンピュータは固有のIPアドレスを持っているため、IPアドレスはしばしば「インターネット上の住所」に例えられます。
私のブログのドメイン名は「ninahaus.com」で、ユーザーはURL欄にこれを入力すれば私のブログを訪問することができます。実はこの動作の裏ではDNSサーバーが仕事をしています。
- ユーザーが「インターネット町にあるニナの家に行こう」と「ninahaus.com」を入力する
- 仲介役であるネームサーバーはニナの家の住所を知る権威DNSサーバーにニナの家の住所を問い合わせる
「権威DNSサーバー」は「ニナの家がどこにあるか知っている町役場」だと思えば良いです - 権威DNSサーバーが「ニナの家の住所」をネームサーバーに回答
- ネームサーバーがユーザーに「ニナの家の住所」を回答

この一連の流れ(=名前解決)は自動で行われるため、ユーザーが「DNSサーバーの存在」「183.181.82.49番地へ移動すること」を意識する必要はありません。
DNSハイジャック
DNSレジストリの登録情報自身を書き換える攻撃をDNSハイジャックといいます。
単語がややこしいので先に解説します。
レジストリ(登録管理組織)
各ドメイン情報を持つデータベースを管理する機関。
「.com」や「.co.jp」などドメイン名の最後の部分を「トップレベルドメイン(TLD)」と言いますが、レジストリはこれらトップレベルドメイン毎にいます。本ブログの場合は「.com」でVerisignです。
レジストラ(登録事業者)
レジストリにドメインを登録する権限をもった事業者です。日本だとお名前.comが有名ですね。本ブログの場合はNetowl, Inc.です。
レジストラント(登録者)
そのドメインを登録した人です。本ブログの場合は私です。
Whois情報での表記は代理人を立てることができるため、Xserver Inc.にお願いしています。
DNSハイジャック 攻撃手法
調べてみたところ、DNSに関連する三者それぞれでのリスクがありました。ただ前例が見つかるのは①で、圧倒的にこれが多いケースのようでした。
- レジストラントになりすまし、ドメイン情報を書き換える
- レジストラになりすまし、レジストリにドメイン情報変更を申請する
- レジストリの権威DNSサーバを乗っ取って登録情報を書き換える
1.ドメイン登録者になりすまして当該ドメイン名情報を書き換える
責任の所在は2通り考えられます。
レジストラント自身の落ち度の場合
レジストラント自身のアカウント(レジストラのドメイン管理データベースにアクセスするためのもの)管理が杜撰で、第三者に認証情報が漏れてしまった。それを攻撃者に悪用されてしまうケース。
対策
- レジストラントはアカウントの認証情報管理をしっかり行うこと
- レジストラントはWhoisなどでドメイン名の登録情報を定期的にチェックすること
- レジストラントは 登録情報の変更申請に関するレジストラからの通知を見落とさないこと
レジストラの責任の場合
レジストラにセキュリティホールがあり、第三者がレジストラントの認証情報を得ることができた。そのため攻撃者がレジストラントのふりをしてレジストラのドメイン管理データベースにアクセスしたケース。
2020年におきたCoincheckのDNSハイジャックはレジストラの脆弱性を突かれたものでした。
レジストラになりすまし、レジストリにドメイン情報変更を申請する
こちらは具体例を見つけられていません。
レジストリの権威DNSサーバを乗っ取って登録情報を書き換える
こちらも具体例を見つけられていません。もしこれが起こると同じTLD全てのサイトに影響するので、主要TLDで起きたことはないのかもしれません。
DNSキャッシュポイズニング
DNSレジストリの登録情報自身を書き換えるDNSハイジャックに対し、キャッシュサーバーの保持するキャッシュを書き換えることをキャッシュポイズニング攻撃と言います。
今回のC.R.E.A.M.およびPancakeSwapへの攻撃はDNSハイジャックによるフィッシングサイトへの誘導が目的のようでした。こちらのキャッシュポイズニングは副産物でしたが、この特性によって両者がドメイン管理フルアクセス権を取り戻した後も事態の収束まで時間がかかることになったと思うので記載します。
キャッシングの仕組み
ユーザーからのリクエストを仲介処理するネームサーバーは、DNSサーバーから得たドメイン名情報を一時的にローカル保存することができます。このキャッシングを行うことで、ユーザーが再び同じリクエストを行った際にDNSサーバーに問い合わせることなくユーザーに回答することができます。
キャッシングはDNSサーバーへの問い合わせ回数をダイレクトに減らします。「ユーザーのリクエスト処理時間短縮」「DNSサーバーの負荷軽減」といったメリットがあるため、多くのネームサーバーがこのキャッシングを実施しており、このようなネームサーバーはキャッシュサーバーとも呼ばれます。
キャッシュに保存しておく期間は、権威サーバーがそれぞれのデータに対して指定することができ、これはTTL(Time To Live)と呼ばれます。

このキャッシング機能を悪用するのがDNSキャッシュポイズニングです。攻撃者がDNSからの回答を偽装することでキャッシュサーバーに「不正なURLとIPアドレスの対応関係」キャッシュを残します。
従ってDNSハイジャックに遭ったC.R.E.A.M.およびPancakeSwap両陣営が「正しいURLとIPアドレスの対応関係」に復旧しても、このキャッシュを返すサーバーがどこかに残っている限りユーザーは偽サイトに誘導されてしまいます。
これが両者ともに「DNSが完全に伝播され、すべてのユーザーにとって正常状態に復旧」と締めくくっていた理由です。伝播(でんぱん)は「伝わり広がって行くこと」です。ネームサーバーや権威DNSサーバーはひとつずつではないため、”毒された”キャッシュがクリアされ正しいものに浄化されるまで時間がかかったのです。
以降はキャッシュポイズニング攻撃に興味のある人用です。良かったらどうぞ。
キャッシュポイズニング攻撃の流れ
- 攻撃者は、ターゲットサイトのURLをキャッシュサーバーにリクエストする
- このリクエストに対する回答がキャッシュされていなければ、キャッシュサーバーは権威DNSサーバーに問い合わせを実施する
- 攻撃者は、権威DNSサーバーが正しい回答を送信する前に偽の回答をキャッシュサーバーに送りこむ
- キャッシュサーバーを騙せれば攻撃成功。キャッシュサーバーに不正なキャッシュが残る
なぜこれが可能なのか
名前解決において、キャッシュサーバーと権威DNSサーバー間でやり取りされる問い合わせは「ID (TXID)」で識別されます。先ほどの流れにIDを追加して書くと以下のようになります。
- キャッシュサーバーは問い合わせ内容にIDを付与して権威DNSサーバーに送信する
- 権威DNSサーバーからの回答を受けた際、回答メッセージ内のIDと問い合わせ送信時のIDを比較する
- IDが一致する回答を正しいものとして処理する。一致しない場合、不正回答として破棄する。
つまりキャッシュサーバーが騙せるか騙せないかのポイントはIDチェックのみで、IDさえ合えば「偽の回答」は「正しい回答」に成りすますことができます。このIDが16ビット=65536通りしかなく、情報工学においては十分推測・総当たり可能な範囲であることが根本原因です。
キャッシュポイズニングによって起こる被害
URLとIPアドレスの対応が不正なものに書き換わっているため、ユーザーは「意図しないサイト」を訪問することになります。多くの場合接続先が有害サイトであり、キャッシュポイズニング自体は実攻撃に誘導するための仕込みです。
従来の対策
DNSキャッシュポイズニングの古典手法は、ターゲットサイトの名前解決を何度も実施して偶然TXIDが犯人の偽回答と合致する値になる事を狙う、というものでした。
これに対する鉄板の防止策は「TTLを伸ばすこと」です。
攻撃できるタイミングは「TTLが切れ、キャッシュサーバーが権威DNSサーバーにリクエストを出す時」に限られるため、攻撃成功確率を下げることができました。
これに対応すべく新たに編み出された攻撃手法がカミンスキー攻撃です。
カミンスキー攻撃
DNSキャッシュポイズニングの進化系で、ターゲットサイトと同じドメインの存在しない名前をリクエストするのがカミンスキー攻撃です。
例えば、攻撃したいサイトのドメイン名がwww.example.comであれば、001.example.com、002.example.com、…をキャッシュサーバーにリクエストします。キャッシュサーバーからするとそれぞれ別の新しいリクエストとなるため、都度権威DNSサーバーに問い合わせを行います。
攻撃者はキャッシュの有効期限が切れるタイミングを待たなくて良くなり、前述の「TTLを伸ばす」対策は無意味になります。
DNSキャッシュポイズニング対策
ソースポートランダマイゼーション
キャッシュサーバーがDNSサーバーにと問い合わせる際に利用するポート番号を従来の固定値ではなくランダムな値にする。
ポート番号も16ビットのため65536通りあります。一部ポートは使途が決まっており自由に使えないため、それらを除いておよそ64000通りの可能性があるとしましょう。
ポート番号をランダムにすることで一度の試行による攻撃成功確率を 1÷(65536×64000) にすることができます。毎秒100万回の試行を行っても、全ての場合を試すには 65536×64000÷1000000=約4194秒かかることになり、その間に権威DNSサーバーから正規の回答が戻ると考えられます。このため、ソースポートランダマイゼーションでカミンスキー攻撃成功確率を下げることができます。
DNS Security Extensions (DNSSEC)
権威DNSサーバーが回答に電子署名を施し、キャッシュサーバーがその署名を検証することで、応答が偽装・改竄されているかどうかを確認します。電子署名の偽装はほぼ困難であるため、これは他の対策のように「攻撃成功確率の軽減」ではなくキャッシュポイズニング攻撃に対するほぼ完璧な防御になり得ます。
Secure Socket Layer (SSL)
Webに限って言えば、偽装キャッシュにより意図しないサイトに誘導されたとしても、通信接続時にSSLによる認証を行っていれば通信相手が偽のホストかどうか検知できます。ただしWebブラウザの警告を無視してしまうユーザーに対してはSSLは有効な手段になりません。
終わりに
C.R.E.A.M. FinanceとPancakeSwapへの攻撃に利用されたDNSハイジャックと副産物のキャッシュポイズニングについて紹介しました。DNS絡みの攻撃は他にもドライブバイファーミング、不正リクエストによるサービス停止攻撃、ゾーン転送要求による攻撃、DNSリフレクション攻撃…など多岐に渡ります。
今回のDNSハイジャックの場合、ユーザー側で事前防止するのが不可能な点が泣き所ですが、DeFiのDeはDecentralized(分散)です。どんなに気に入っていても特定のプロジェクトのみに全資産を預けるのではなく、必ず分散させましょう!
1月に起こったVenus CAN事件の際にソフィさん(@sophy_cherie)が言っていた言葉をいつも心に留めていてください。

参考
- https://en.wikipedia.org/wiki/DNS_spoofing
- https://www.nic.ad.jp/ja/newsletter/No40/0800.html
- https://www.atmarkit.co.jp/ait/articles/1501/05/news015.html
- https://www.nic.ad.jp/ja/basics/terms/dom-hijack.html

