DNSは開発されてから20年以上,基本仕様をほとんど変えないまま使われてきた。「実はこれは奇跡的なことで,そろそろDNSを見直さなければならないのかもしれない」(さくらインターネット技術部の大久保修一リーダー)。実際,2008年にカミンスキー氏が発表した新手のDNSキャッシュ・ポイズニング攻撃は,DNSの危うさを知らしめた。とはいえ,すぐにDNSを代替できる仕組みは存在せず,当面使い続けなければならないのが現実だ。何が起こっているのかを理解しておかなければならない。

UDPに起因,“古さ”が弱点もたらす

 DNSキャッシュ・ポイズニングは,DNSサーバーに一時的にキャッシュしてあるドメイン名とIPアドレスの対応情報を偽の情報に書き換える攻撃である。悪用されるとユーザーのWebブラウザは偽のWebサイトに誘導されてしまう。

 その仕組みは以下のようになる。WebブラウザからURL中のドメイン名に該当するIPアドレスの問い合わせを受けたDNSサーバー(キャッシュ・サーバー)は,さらに別のDNSサーバー(コンテンツ・サーバー)に問い合わせる。この時,キャッシュ・サーバーに何らかの方法で偽サイトの情報を埋め込む。すると,ユーザーがWebブラウザで正しいURLを指定してアクセスしても,偽の情報によって,本来のサイトとは異なる偽のサイトに誘導されてしまう。

 DNSは主要な通信にUDPを利用する。インターネットのれい明期はバックボーンの帯域幅が狭かったため,TCPよりも「軽くてシンプル」なUDPを使う必要があった。ただし,UDPはTCPと違い,通信の信頼性を保障する仕組みを省いており,TCPに比べて簡単にパケットを偽装できる。そこでDNSではやり取りの正当性を担保するために,問い合わせ時に利用した送信元IPアドレス(1)およびUDPのポート番号(2)あての通信であることを確認。さらに,問い合わせごとに異なる16ビットの識別子(トランザクションID,(3))を確認する。これらが一致しないと,正規の応答として認めない。

処理性能向上で16ビットでは不十分になる

 DNSキャッシュ・ポイズニングでは,攻撃者が(1)~(3)を破って応答パケットを偽装する。このうち,(1),(2)は比較的容易に推測できる。例えば送信元IPアドレスは専用ツールなどを使って事前に調査可能だ。

 (3)は16ビット(6万5536通り)のIDを試せば,いずれ正解にたどり着く。DNSの開発当時はこのID数でも十分だった。だが,コンピュータの処理性能向上によって,攻撃者が自らターゲットのDNSサーバーに多数の問い合わせをかけ,それに対してランダムなトランザクションIDを付けた偽の応答パケットを大量に送り返し続ければ,いずれIDを破れるようになってしまった。

通信相手を認証できない隙を突く

 従来の攻撃手法は,最初の問い合わせに「偽装したい実在のドメイン名と同じドメイン名」を使うのが主流だった。ただし,攻撃が失敗した場合はコンテンツ・サーバーからの正規応答がキャッシュ・サーバーにキャッシュされるため,次の攻撃はキャッシュの生存時間(TTL)が過ぎるまで待たなければならなかった。

 カミンスキー氏の発表した手法では,最初にキャッシュ・サーバーに送信する問い合わせに「ターゲットと同じゾーンのドメイン名を含む,実在しないドメイン名」を使う。例えば実在するドメイン「www.example.jp」に不正なIPアドレス「x.x.x.y」をひも付けたい場合,攻撃者はキャッシュ・サーバーに実在しないドメイン名を使って,「001.example.jpのIPアドレスは?」と問い合わせる。それに対して,「001.example.jpは知らないが,www.example.jpなら知っている。www.example.jpのIPアドレスはx.x.x.y」と偽の応答を返すのだ(図1)。最初に問い合わせる実在しないドメイン名を少しずつ変えれば,攻撃に失敗して正規応答の内容がキャッシュされても,すぐ次の攻撃を仕掛けられる。

図1●効率化されたDNSキャッシュ・ポイズニングの手口<br>DNSサーバーに最初に問い合わせる際,詐称したい実在のドメイン名(example.jp)にランダムな情報を付けた架空のドメイン名を要求すれば,短時間に何度も攻撃を仕掛けられる。
図1●効率化されたDNSキャッシュ・ポイズニングの手口
DNSサーバーに最初に問い合わせる際,詐称したい実在のドメイン名(example.jp)にランダムな情報を付けた架空のドメイン名を要求すれば,短時間に何度も攻撃を仕掛けられる。
[画像のクリックで拡大表示]

 対策としては,まず2008年7月公開のパッチを適用すること。このパッチは,キャッシュ・サーバーの送信元ポートをランダム化する。(3)のトランザクションIDだけでなく,(2)のポート番号もランダム化することで,攻撃の成功率を下げる。ただし,この対策は「攻撃が成功するまでに理論上必要な時間を延ばす」に過ぎない。

 そもそも,DNSが通信相手の認証手段を持たないことがこの問題の本質だ。この問題を解決できるDNSSECという拡張仕様があるものの,今のところ「業界全体で実装に向けて検討を進めている」(JPRSの民田氏)段階。DNSSECでは,公開鍵暗号方式で応答パケットの正当性を確認する。各コンテンツ・サーバーが秘密鍵を使って応答パケットに電子署名し,キャッシュ・サーバー側で公開鍵を使って署名を検証する仕組みである(図2)。ただし,運用上の課題が多く,普及にはまだ時間がかかりそうだ。

図2●DNSSECの動作例<br>DNS応答の送信元が正しいかどうかを電子署名を使って検証する。今のところはルート公開鍵の配布方法や,最上位の電子署名をどこが担当するかなど,運用上の課題が多い。
図2●DNSSECの動作例
DNS応答の送信元が正しいかどうかを電子署名を使って検証する。今のところはルート公開鍵の配布方法や,最上位の電子署名をどこが担当するかなど,運用上の課題が多い。
[画像のクリックで拡大表示]