hnwの日記

DNSSECを利用してゾーン情報を抜き出してみた(NSEC編)

さいきんDNSSECについて調べているのですが、普及について懐疑的な人が多いという印象を持ちました。批判点として運用の難しさを挙げる人も多く、仕様策定時に運用負荷の観点が入っていたらまた違ったのかなと感じたりもします。


また、運用面の視点以外に、技術仕様面でも批判的な人が一定数いるように思います(DJBが筆頭ですかね…)。批判の一つがゾーン情報の列挙(Zone enumeration)に関するものです。特に、初期のDNSSECの仕様では「NSEC walking」により完全なゾーン情報を第三者が取り出すことができました。これを改良するためNSEC3レコードが導入されたという経緯がありますが、今でもNSECで運用されているゾーンが一定数残っていたりもします。


本稿ではNSEC walkingによりゾーン情報を読み出す方法を紹介します。

NSECレコードとは

NSECレコードというのはDNSSECで導入された新しいレコードタイプで、問い合わせに対して不存在を回答するためのものです。


そもそもDNSSECは、公開鍵暗号を使ってDNS問い合わせの回答に署名するような仕組みです。この仕組みがあれば、存在するレコードについては署名により正当性の確認ができます。しかし、レコードが存在しない場合に従来のDNSでは何も返さない仕様だったので、署名する対象がありません。不存在に対して署名するために、存在しないことを意味するNSECレコードが新設されたというわけです。


このNSECレコードは「aaa.example.comからbbb.example.comの範囲には何もないよ」というような返事をする仕様になっています。すべての問い合わせに対して個別に「それは存在しないよ」と返事を返しているとキリがないので、キャッシュ効率を考えてこのような仕様にしたのだと思われます。しかし、このような仕様になっていることで、先ほどの例なら「aaa.example.com」と「bbb.example.com」という2つのレコードがありそうだということが外部から丸わかりになってしまいます。


もちろん、ゾーン内にどのようなレコードがあるか知られたからといって即座に危険というものではありません。とはいえ、ホスト名にミドルウェア名やアプリケーション名をつけることは珍しくないはずですし(例:redis, irc)、Webサーバのバーチャルホスト設定をしている場合など、正しいホスト名を知らないとアクセスできないサービスもあるわけです。こうした例からも明らかなようにホスト名を知られることは攻撃リスクの増加につながるため、不用意にゾーン情報を公開しないのが一般的なノウハウです。ところが、レコードの不存在に対してNSECレコードを返してしまうとゾーン情報を全世界に公開するのと同じ状態になってしまうのです。


この問題はNSECレコード導入直後から指摘されていたようで、2008年にはこの問題を解決する目的のNSEC3レコードがRFCに採択されています。また、現在では多くのDNSサーバがNSEC3レコードを利用して運用されています。実はNSEC3レコードにも問題点はあるのですが、その話題は別の記事でまとめたいと思います。

digコマンドでNSECレコードを確認してみる

現在ではNSEC3レコードで不存在を回答するDNSサーバの方が多数派ですが、まだまだNSECレコードも現役です。digコマンドで.moeドメインの問い合わせをしてみましょう。

$ dig a zunopan.moe +dnssec +nocmd

; <<>> DiG 9.10.3-P3 <<>> a zunopan.moe +dnssec +nocmd
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 21684
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;zunopan.moe.			IN	A

;; AUTHORITY SECTION:
moe.			6665	IN	SOA	ns1.dns.nic.moe. hostmaster.neustar.biz. 72673 900 900 604800 86400
moe.			6665	IN	RRSIG	SOA 8 1 7200 20160426103703 20160327093703 20989 moe. KkV+vuFD/V36pDolnSIwSXZ24bh+LZHjRBfo44g/I9XL5HbZnfoQZ6nn On0GQcVHbjPKmwKuncdBJ3YEvNP1fmmIe85tznIVm8TvVugc+fgQRe1F v+ShBeY6n84r3ZNc+IOG4vMJ6jJgWEjXPCBwfQjUOISC6cFTOCWUAioZ Ais=
ZUNKO.moe.		83996	IN	NSEC	ZUO.moe. NS RRSIG NSEC
ZUNKO.moe.		83996	IN	RRSIG	NSEC 8 2 86400 20160406151432 20160307144911 20989 moe. ab2jy3xntU87B8eSGONcspcC8yx2joTnfo7fBg445F4C8QlyIIJ8Hiqr K39JwpWcgHrekqgqdc6CGHuRbPtNM1Xq+Qclo28D3Fo5WMuajzBjzZBR DNzTMclkMSWotYP80ksA6vXp7NMbEYCRZo9mcfDKSlOojvjv12E0s4E0 7/8=
moe.			83983	IN	NSEC	0-0.moe. NS SOA RRSIG NSEC DNSKEY
moe.			83983	IN	RRSIG	NSEC 8 1 86400 20160405140613 20160306131312 20989 moe. DEmFsg1au3cB3Xr7xKJt8j+1HkqTGaIKdVXVv6AdrEyAmJooBrQ57oZb eQO+rRfyBuxLsXOaU7aLHfdepTLlphmVuw3tP3rXd4U8JzJaDWFThtZC 9AiA6/UtScSbh6QLfJpQaXFqEHXecsAGFtjmxo9IkADRG3M7tFdMeYP+ uyc=

;; Query time: 129 msec
;; SERVER: 192.168.48.1#53(192.168.48.1)
;; WHEN: Sun Mar 27 19:50:31 JST 2016
;; MSG SIZE  rcvd: 664


上記のうち、下から2行目のNSECレコードが今回話題にしているレコードです。これによれば、「zunopan.moe」は存在しないけど、「ZUNKO.moe」というレコードがあり、対応するレコードタイプは「NS RRSIG NSEC」の3つだということ、その次のレコードは「ZUO.moe」であることがわかります。これを辿っていけばゾーン内の全レコードを取り出せてしまうというわけです。


ちなみに、一番最後のRRSIGレコードが対応する署名になります。参考まで。

NSEC walkingを行うツール

これまで説明してきたような性質を利用してゾーン内の全レコードを取り出すことをNSEC walkingなどと言います。これを行うツールは下記のように何種類か作られています。ちなみに3つめは筆者が今回Go言語の練習がてら書いてみたものです。


筆者の作った「go-dnssec-walker」の実行例を示します。当然ですが、他のツールでも同じような出力が得られます。

$ walker -s zunko moe
zunko.moe.
zuo.moe.
zxz.moe.
zyii.moe.
zyon.moe.
zzz.moe.


このノリで全域を調べると、たとえば.moeドメインには現時点で5075ドメインが登録されているらしい、なんてことがわかったりします。

NSEC walkingできるTLD

今回NSECについて調べてみて、現在もNSECで運用されているgTLD・ccTLDが下記の通りたくさんあることがわかりました。下記のTLD内のドメインは赤の他人が簡単に一覧を取得できるというわけです。他人に知られて困るようなドメインを持っている人は気をつけた方がいいかもしれませんね。

gTLD
  • .accountant
  • .audio
  • .auto
  • .best
  • .bible
  • .bid
  • .biz
  • .blackfriday
  • .buzz
  • .car
  • .cars
  • .ceo
  • .christmas
  • .click
  • .club
  • .cricket
  • .date
  • .diet
  • .download
  • .earth
  • .faith
  • .flowers
  • .game
  • .gift
  • .guitars
  • .help
  • .hiphop
  • .hosting
  • .how
  • .jetzt
  • .juegos
  • .link
  • .loan
  • .lol
  • .moe
  • .mom
  • .nyc
  • .osaka
  • .party
  • .photo
  • .pics
  • .property
  • .qpon
  • .racing
  • .review
  • .science
  • .sexy
  • .soy
  • .taipei
  • .tattoo
  • .trade
  • .uno
  • .webcam
  • .whoswho
  • .win
  • .みんな(.xn--q9jyb4c)
  • .世界(.xn--rhqv96g)
ccTLD
  • .ad
  • .bg
  • .br
  • .ind.br
  • .co
  • .com.gn
  • .id
  • .co.id
  • .or.id
  • .web.id
  • .kg
  • .ky
  • .lk
  • .mg
  • .com.mm
  • .org.mm
  • .na
  • .pr
  • .biz.pr
  • .com.pr
  • .net.pr
  • .org.pr
  • .se
  • .sl
  • .com.sl
  • .tn
  • .com.tn
  • .us

まとめ

  • DNSSECの不存在をNSECレコードで返すのはゾーン情報の公開と同じ
    • そういうTLDが結構ある
    • いち企業のDNSサーバでも実在する(例:paypal.com)
  • どうせDNSSECやるならNSEC3で返した方が多少はマシ


飽きていなければ次回はNSEC3編を書きます。