パケットを誤解釈する実装があった時、違うプロトコルのパケットに対して応答してしまうのではないのか。そんなことが実際にあるのか考察してみる。
今回は、DNSサーバとNTPサーバで、そのような通信を意図的に引き起こせるかのか検討していく。

先に結論を書いておくと、その様なパケットを構成することは出来そう。
目次
誤解釈をするシチュエーション
この様な思考実験をするにあたって、それを考えるきっかけを補足する。
NTPサーバに対してDNSのパケットが届くというシチュエーションがあるのか?誤解釈をしてしまって問題になるのか?という疑問は当たり前にある。その、一つの例として反射攻撃が思いつく。。
反射攻撃(アンプ攻撃)は、攻撃者が送信元IPアドレスを偽装してパケットを送信することで、応答がVictim宛に届くという手法である。
(レスポンスサイズ>リクエストサイズ という通信特性を応用して大量のトラフィックを生み出す)
反射攻撃は通常であれば、図①、②で終わりますが さらに③の応答パケットを生み出すことができてしまう。

なお、ネタバレをすると今回の構成は、反射攻撃として手法として有用かというとそんなことはないように思う。
(反射攻撃に対してさまざま防御手段があります。偽装したIPアドレスは不正な経路から届くためブロックしたり、Victim側ではウェルノーンポートが送信元IPになるためそれでブロックするなど防御手法があります。)今回は、送信元IPを偽装するところは本論ではないので、実際に試したりはしません。
実験構成
DNSパケットをNTPパケットとして誤解釈する事を実証する。
ローカルにBindサーバ・ntpdサーバを起動し、①実験者から正規のDNSパケットを送信する。②応答としてDNSパケットが得られる、それを③NTPサーバにそのまま送信する。中継しているが、正規のDNSパケットがNTPサーバで誤解釈され④NTPレスポンスが発生することが確認できる。

- bind9 1:9.18.39-0ubuntu0.24.04.7
- ntp 1:4.2.8p15+dfsg-1ubuntu2
今回は簡易的な実験として、bindサーバには細工したレコードをプリセットしている。
おさらい
DNSレスポンスと、NTPリクエストのパケットの構造をおさらいする。(なお、構成図②に相当する、同じバイナリからなるパケットにて例示している)。
まずはDNSレスポンスから。

下記などからなる
- Transaction ID
- Flags
- Queries
- Answer
NTPリクエスト

下記などからなる
- Flags
- 時刻用パラメータ
- 時刻情報
- オプショナルである拡張領域 (length+valueからなる)
パケットの細工
NTPリクエストとして受理されるためには次の条件を満たさなければならない。
- NTPバージョンが正しい (1~4)
- Modeがクライアントモード
- パケット長が整合する
- NTPパケットとして固定長の48バイト
- 拡張フィールドのLenght および 実際のバリューの長さ
実験者は、①DNSリクエストを工夫することで、これらが守られるようなDNSレスポンスを意図的に作ることを目指す。
- NTPパケットとしての冒頭のバージョンやModeは、①で送るDNSリクエストのTransaction IDを任意に設定することでコントロールできる。
- 拡張フィールドに含まれるLength及び、パケット長が整合することは運ゲーである。が、DNSリクエストでRDフラグを有効にしつつ、任意のTXTレコード(TXTレコードはバイナリ値も許可されている)を引かせることで、多少生成するDNSレスポンスのコントロールすることが出来る。今回はシンプルにAAAAレコードのIPアドレス部分でLength長を調整している。
↓NTPリクエストとしての拡張フィールドにおいて、このLengthとパケット長が整合しないとエラー扱いになる。

(実際のDNSサーバでは長さが変わる要因が複数あるが、今回は実証としての一例まで。)
実際行われた通信
構成図で示した通りの通信が、実際に成功している例

[再掲] 構成図。

(④で返されるNTPレスポンスとしては小さいパケットになるので、アンプ攻撃で有用とは思えない。あくまで思考実験として試したというぐらいの結果)
サーバ実装上の問題点
今回は、実際にはntpdが不正なパケットを受理してしまっているのが一つの要因としてある。
一部のパラメータは、仕様上の不正な値になってしまっている。これらを不受理にスべきである。
サーバを実装する人は不正なパラメータをエラーにスべきです。
終わりに
今回はDNSパケットとNTPパケットの、誤解釈をテーマに扱ったが、UDPプロトコル同士であれば発生しうる。
プロトコルを設計するうえで、このような誤解釈を本質に防ごうと思ったら、DTLSやQUICを用いることで暗号処理として誤解釈を防げるので、それが良さそうではある。



