WIDE Technical-Report in 2007 定期的なUDPポートの変更によるBIND9サーバへのキャッシュ汚染防止 wide-tr-dns-bind9-portpool-00.txt WIDE Project: http://www.wide.ad.jp/ If you have any comments on this document, please contact to ad@wide.ad.jp. ^L Title: 定期的なUDPポートの変更によるBIND9サーバへのキャッシュ汚染防止 Author(s): 神明達哉(jinmei@isl.rdc.toshiba.co.jp) Date: 2007-02-07 1. DNSのキャッシュ汚染攻撃 DNSのキャッシュサーバに対する攻撃として、キャッシュ汚染(cache poisoning)と呼ばれる手法がある[1]。この攻撃は一般に、キャッシュサーバ が送信する問い合わせに含まれるパラメータと一致する偽の応答を正当なサー バより先に返すことによって実現される。問い合わせのパラメータの中で、攻 撃者が(一般には)制御できず、したがって推測、盗聴、総当たり探索等によっ て一致させる必要があるものは、問い合わせID、送信元のポート番号、問い合 わせ先のサーバのアドレスである。 与えられた問い合わせ名に対し、問い合わせ先サーバのアドレスは通常数個か ら高々十数個であるため、総当たり探索にかかるコストは小さい(なお、アド レスについてはさらにソースアドレスを詐称したパケットがフィルタされるこ となく攻撃先に到達できるという条件も必要になるが、この点は本稿での議論 の本質から外れるので考えないことにする)。一方、IDおよびポート番号はと もに16ビット整数値であり、この双方を総当たり探索によって一致させること は現実的ではないため、問い合わせパケットを盗聴してパラメータを取得でき ない限りキャッシュ汚染攻撃を成立させることは理論上は困難だといえる。 ところで、広く普及しているISCのBINDキャッシュサーバは、起動している期 間中は固定の問い合わせ元ポート番号を用いるため、キャッシュ汚染攻撃を成 功させるために一致させる必要があるパラメータは実質的に16ビット整数値で ある問い合わせIDのみとなる(アドレスの個数についてはこれより十分に小さ いので議論を簡略化するためにここでは無視する)。この仕様がキャッシュ汚 染攻撃に対する潜在的な脆弱性となっていることは以前から指摘されていた。 ただし、この「脆弱性」を突いて実際に攻撃を成功させることは簡単ではない。 まず、16ビットの空間でも単純な推測に基づく方法では一致させることは困難 である。また、総当たり探索による攻撃は、それ自体は成立しても、そのため に生じる大量の応答パケットによって攻撃が検出されやすくなるという欠点が ある。 ところが、TTLが十分に小さい問い合わせ名に対しては、より検出されにくい 形でこの攻撃を成立させられる場合がある[2]。TTLが小さく、また頻繁にクラ イアント(スタブリゾルバ)からの問い合わせがあるような著名な名前であれば、 キャッシュサーバからの問い合わせもTTLに応じて頻繁に送信される。したがっ て、攻撃者側は、検出されない程度の頻度で問い合わせIDを総当たり探索し、 比較的短時間のうちに高い確率で攻撃を成立させることができる。[2]では、 TTL 30秒、問い合わせ先サーバ数2、キャッシュサーバとサーバ間の通信にか かる時間が20ミリ秒、攻撃側の送出レートが毎秒10パケットという条件で、 100台のキャッシュサーバに並行して攻撃をかけた場合、38時間後には50%の確 率でどれか一台のサーバへの攻撃が成功するという計算結果を示している。 この問題を軽減するためのもっとも単純な対策は、問い合わせのポート番号を より推測されにくく、あるいは総当たり攻撃への耐性が高くなるように変更す ることである。実際、BIND以外のDNSサーバの一部、たとえばdjbdns[3]や PowerDNS recurser[4]は問い合わせごとに異なるポート番号を利用している。 筆者は、広く使われているBIND実装においてもこのキャッシュ汚染攻撃に対す る耐性を高めることが実運用上重要であると考え、BINDの最新版であるBIND9 のキャッシュサーバ上で同様の機能を実現するパッチを作成した。本稿ではこ の機能の概要を紹介する。 2. BIND9キャッシュサーバへのパッチ このパッチを適用すると、問い合わせ用に複数個のUDPソケットを開き、それ ぞれを異なるポートにbindする。また、各ポートは一定時間ごとに更新される。 問い合わせ時には、複数のソケットのうちの一つをランダムに選んで利用する。 問い合わせごとにポートを変更する方法を採らなかったのは、その際のソケッ トの廃棄と生成にかかるオーバヘッドを回避するためである。このため、短時 間内の総当たり攻撃に対する効果は限定的(探索対象がソケット数の分増える のみ)であるが、前述の通り、この場合には大量の応答パケットによって攻撃 を検出できると考えられるので、実用上の効果は同等であると判断した。 本パッチは以下のURLにて公開されている: http://www.kame.net/~jinmei/bind-9.4.0b2-portpool.patchhttp://www.kame.net/~jinmei/bind-9.4.0b2-portpool.patch なお、パッチを作成した時点で対象としていたBIND9のバージョンは9.4.0b2で あるが、執筆時点での最新版である9.4.0rc2にもそのまま適用可能である。 また、本パッチはBINDの開発元であるISCにも送付し、リリース版に採用して もらうように働き掛けている。 2.1 利用方法 本パッチを利用するには、新規オプション "use-queryport-pool" をyesに指 定する: options { ... use-queryport-pool yes; }; (既定値ははno, per viewでも指定可能) この機能が有効な場合、各viewについて queryport-pool-ports (既定値は8) 個のUDPソケットを同時に開き、それぞれをランダムな(non reserved)ポート にbindする。また、IPv4/v6デュアルスタックの場合には、それぞれについて queryport-pool-ports個のソケットが生成される。 また、queryport-pool-updateinterval (既定値は15)分ごとにこれらのソケッ トを一つづつ更新する。すなわち、新しいソケットを開き、ランダムなポート にbindし直す。古いソケットはclose()する。したがって、既定値を利用した 場合、どのソケットも最大2時間で入れ替わることになる。 queryport-pool-ports および queryport-pool-updateinterval の値について も設定ファイル内で指定可能である。 2.2 実装上の論点 以下は、本機能の実装に関する主要な論点である。これらについては、今後の 議論・試験運用の結果等を通じて方針を定める予定である。 1. queryport-pool-portsとqueryport-pool-updateintervalの妥当な既定値は 何か。現状の実装で利用している値にはとくに根拠はなく、実際の攻撃シ ナリオや問い合わせパターンによってはよりよい値が他にある可能性もあ る。たとえば、本パッチが想定しているような、比較的低レートの攻撃を 防止するためには、queryport-pool-ports は1でも十分ということも考え られる。 2. IPv4とIPv6では挙動を変える(こともできるようにする)べきか。現在の実 装では、queryport-pool-ports および関連するパラメータはIPv4/IPv6共 通に作用する。 3. 異なるviewで用いるソケットを共有可能にすべきか。現在の実装では、 use-queryport-pool を有効にしているBIND9 viewにおいては、どのviewの どのソケットも異なるポートを利用するようになっているため、多数の viewを利用する設定ではその分多くのソケットが必要となる。一方、 BIND9の実装ではviewごとに異なるキャッシュを持つため、複数のviewで同 一のソケット(ポート)を共有していてもキャッシュ汚染防止という目的に は支障はなく、システム資源の有効利用という観点からは共有する方が望 ましい。ただし、そのためには実装が多少複雑化すると予想される。 参考文献 [1] D. Atkins and R. Austein, "Threat Analysis of the Domain Name System (DNS)", RFC3833, August 2004. [2] 民田雅人「短いTTLのリスク」Internet Week 2006 DNS DAY, 2006年12月. [3] djbdns, http://cr.yp.to/djbdns.html [4] PowerDNS, http://www.powerdns.com/ Copyright Notice Copyright (C) WIDE Project (2007). All Rights Reserved.