移転インジェクションとは広く行われている NS の移転作業を模倣した DNS キャッシュポイズニング手法です。(詳細はこちら)
多く用いられている実装において、あるゾーンの権威サーバが返した権威ある Answer に付随する Authority Section によってキャッシュされた NS レコードは、同じゾーンの別な名前の問い合わせに付随する Authority Section の NS レコードによって上書きされてしまいます。
これによって権威サーバで NS レコードを書き換えることにより権威サーバの移転がスムーズに行えるわけですが、それを模倣した偽応答によって NS が毒入れされることも許してしまうわけです。つまりそのようなキャッシュサーバには移転インジェクション脆弱性があると言えるわけです。
そのような脆弱性を持つかどうかを確認できるドメインを用意しました。(幽霊ドメイン名脆弱性もわかるでしょう)
flip.e-ontap.com は 5 分ごとに権威サーバが切り替わるドメインです。ns.flip.e-ontap.com (150.42.6.1) と ns.flip.internot.jp (150.42.6.5) は 5 分ごとに以下のようにゾーンデータが切り替わります。
0-5分 (正規の flip.e-ontap.com ゾーン)
flip.e-ontap.com. 3600 NS ns.flip.e-ontap.com. *.flip.e-ontap.com. 3600 A 150.42.6.1
5-10分 (移転先/あるいは悪意ある偽の flip.e-ontap.com ゾーンを指す)
flip.e-ontap.com. 3600 NS ns.flip.internot.jp. *.flip.e-ontap.com. 3600 A 150.42.6.5
なお、委譲元 (e-ontap.com ゾーン) では以下のように常に ns1.flip.e-ontap.com = 150.42.6.1 を指しています。
flip.e-ontap.com. 86400 NS ns1.flip.e-ontap.com. ns1.flip.e-ontap.com. 86400 A 150.42.6.1
このように設定された flip.e-ontap.com ゾーンの異なる名前を 5 分ごとに問い合わせて、利用しているキャッシュサーバのキャッシュがどう変化するかを観察することにより移転インジェクション脆弱性に気づくことができるでしょう。(厳密にはパケットダンプ、キャッシュダンプを確認することを推奨します)
私の実験では、unbound 1.5.5、BIND 9.10.2-P3 で脆弱性を確認しました。なお、Unbound は unbound.conf で harden-referral-path: yes とすることで、十分ではないかもしれませんが防御ができることも確認しています。なぜかはパケットダンプを観察するとわかりますので調べてみると勉強になるでしょう。
また、Google Public DNS (8.8.8.8) や OCN が顧客に提供しているキャッシュサーバにはこの脆弱性はなさそうです。ただし OCN のサーバはソースポートのレンジが 2000程度と狭いため他の手法に対して要注意でしょう。8.8.8.8 は Answer Section しか返しませんが、常に 150.42.6.1 を返してきます。つまり委譲元の NS をキャッシュし、権威サーバ側の NS では上書きされていないと推測されます。(逆に言えば移転時には委譲元の TTL を考慮する必要があるということになります)
OpenDNS、NortonDNS、Level3、Comodo、Baidu などは 150.42.6.5 を返すことがありますから脆弱性があるようです。
注意: この移転インジェクションのテストで問題がなくとも委任インジェクションの脆弱性は存在する可能性が高いので安心してはいけません。(一方でこのテストで脆弱性があるようにみえても別な防御がなされている可能性もあります)
以下に unbound 1.5.5 によるテストの例を示します。
flip.e-ontap.com ゾーンのキャッシュが空の状態で、名前を一つ問い合わせてみる。(Unbound はキャッシュにない QNAME を引くと権威サーバからの応答そのものを返すので、キャッシュを確認するために2度検索する)
% dnsqr a 1.flip.e-ontap.com ; date "+;; TIME: %H:%M:%S" 1 1.flip.e-ontap.com: 85 bytes, 1+1+1+1 records, response, noerror query: 1 1.flip.e-ontap.com answer: 1.flip.e-ontap.com 60 A 150.42.6.1 authority: flip.e-ontap.com 3600 NS ns.flip.e-ontap.com additional: ns.flip.e-ontap.com 3600 A 150.42.6.1 ;; TIME: 16:24:23 % dnsqr a 1.flip.e-ontap.com ; date "+;; TIME: %H:%M:%S" 1 1.flip.e-ontap.com: 85 bytes, 1+1+1+1 records, response, noerror query: 1 1.flip.e-ontap.com answer: 1.flip.e-ontap.com 56 A 150.42.6.1 authority: flip.e-ontap.com 3595 NS ns.flip.e-ontap.com additional: ns.flip.e-ontap.com 3596 A 150.42.6.1 ;; TIME: 16:24:27
e-ontap.com からの委譲先である 150.42.6.1 (ns.flip.e-ontap.com) が応答しているのがわかる。(150.42.6.1 は全ての名前の Aレコードとして 150.42.6.1 を応答する)
この際に NS キャッシュとして flip.e-ontap.com ゾーンの権威サーバである 150.42.6.1 が返した名前 ns.flip.e-ontap.com が入り TTL 3600 からカウントダウンしている。
(委譲元の NS 名は ns1.flip.e-ontap.com であり TTL は 86400 である / 委譲の NS キャッシュしか持っていない状態のキャッシュサーバに対してはこの動作だけでも脆弱性になりえる)
このときのパケットの流れを見ても、e-ontap.com の NS である 49.212.106.253 (ns2.e-ontap.com) に問い合わせ、次に委譲先の 150.42.6.1 (ns.flip.e-ontap.com) に問い合わせて Answer 150.42.6.1 を得ているのがわかる。
16:24:22.608826 IP 172.16.168.133.62112 > 14.192.44.1.53: 36272% [1au] A? 1.fLIP.e-ontAP.Com. (47) 16:24:22.661423 IP 14.192.44.1.53 > 172.16.168.133.62112: 36272- 0/1/1 (70) 16:24:22.661692 IP 172.16.168.133.26885 > 150.42.6.1.53: 37560% [1au] A? 1.fLiP.E-ONTAP.coM. (47) 16:24:22.712396 IP 150.42.6.1.53 > 172.16.168.133.26885: 37560*- 1/1/1 A 150.42.6.1 (85)
(unbound.conf で use-caps-for-id: yes としているため大文字小文字が混在しています)
次に25分台になってから別な名前を問い合わせる。(念のため2回)
% dnsqr a 2.flip.e-ontap.com ; date "+;; TIME: %H:%M:%S" 1 2.flip.e-ontap.com: 85 bytes, 1+1+1+0 records, response, noerror query: 1 2.flip.e-ontap.com answer: 2.flip.e-ontap.com 60 A 150.42.6.1 authority: flip.e-ontap.com 3600 NS ns.flip.internot.jp ;; TIME: 16:25:08 % dnsqr a 2.flip.e-ontap.com ; date "+;; TIME: %H:%M:%S" 1 2.flip.e-ontap.com: 85 bytes, 1+1+1+0 records, response, noerror query: 1 2.flip.e-ontap.com answer: 2.flip.e-ontap.com 57 A 150.42.6.1 authority: flip.e-ontap.com 3551 NS ns.flip.internot.jp ;; TIME: 16:25:11
この時点では NS キャッシュは ns.flip.e-ontap.com (150.42.6.1) を向いており、Answer の A レコードに 150.42.6.1 が返ってくるが、Authority Section の NS レコードとして移転インジェクションを模擬して25分に書き換わった ns.flip.internot.jp が返った結果、NS キャッシュが上書きされたことがわかる。
この際のパケットダンプ
16:25:08.243758 IP 172.16.168.133.35168 > 150.42.6.1.53: 9378% [1au] A? 2.Flip.E-Ontap.com. (47) 16:25:08.318071 IP 150.42.6.1.53 > 172.16.168.133.35168: 9378*- 1/1/0 A 150.42.6.1 (85)
ここで、別な名前を問い合わせると、150.42.6.5 (ns.flip.internot.jp) に問い合わせが送られ、Answer として 150.42.6.5 が返ってくる。
# dnsqr a 3.flip.e-ontap.com ; date "+;; TIME: %H:%M:%S" 1 3.flip.e-ontap.com: 85 bytes, 1+1+1+0 records, response, noerror query: 1 3.flip.e-ontap.com answer: 3.flip.e-ontap.com 60 A 150.42.6.5 authority: flip.e-ontap.com 3545 NS ns.flip.internot.jp ;; TIME: 16:25:17
パケットをみると 3.flip.e-ontap.com の 解決に必要な ns.flip.internot.jp の A レコードを問い合わせた後、150.42.6.5 (ns.flip.internot.jp) に問い合わせを送り、Answer として 150.42.6.5 を得ているのがわかる。
16:25:17.770381 IP 172.16.168.133.10907 > 14.192.44.1.53: 52799% [1au] A? Ns.FLIp.interNOT.Jp. (48) 16:25:17.811112 IP 14.192.44.1.53 > 172.16.168.133.10907: 52799*- 1/2/2 A 150.42.6.5 (171) 16:25:17.811460 IP 172.16.168.133.31577 > 150.42.6.5.53: 28303% [1au] A? 3.FLip.E-Ontap.COm. (47) 16:25:17.871416 IP 150.42.6.5.53 > 172.16.168.133.31577: 28303*- 1/1/0 A 150.42.6.5 (85)
30分台になってさらに別な名前の問い合わせを行うと、NS は元 (ns.flip.e-ontap.com)へ戻る。
# dnsqr a 4.flip.e-ontap.com ; date "+;; TIME: %H:%M:%S" 1 4.flip.e-ontap.com: 85 bytes, 1+1+1+1 records, response, noerror query: 1 4.flip.e-ontap.com answer: 4.flip.e-ontap.com 60 A 150.42.6.5 authority: flip.e-ontap.com 3600 NS ns.flip.e-ontap.com additional: ns.flip.e-ontap.com 3251 A 150.42.6.1 ;; TIME: 16:30:12 # dnsqr a 4.flip.e-ontap.com ; date "+;; TIME: %H:%M:%S" 1 5.flip.e-ontap.com: 85 bytes, 1+1+1+1 records, response, noerror query: 1 4.flip.e-ontap.com answer: 4.flip.e-ontap.com 57 A 150.42.6.5 authority: flip.e-ontap.com 3247 NS ns.flip.e-ontap.com additional: ns.flip.e-ontap.com 3248 A 150.42.6.1 ;; TIME: 16:30:15
このあと別な名前を引くと5分間は Answer として 150.42.6.1 が返る。(以下省略)