dnsmasqの脆弱性の概要: DNSキャッシュポイズニングの危険性

By

Category: Unit 42

Tags: , , , , ,

This post is also available in: English (英語)

概要

DNSマスカレード(dnsmasq)は、広く使用されているオープンソースのDNSリゾルバです。その名に聞き覚えがなくても、これはKubernetesからルーターやその他の製品に至るまで世界中の多くのプロジェクトやハードウェアファームウェアで使用されています

長年にわたりdnsmasqには複数の重大な脆弱性が発見されてきました。最近、セキュリティ研究者たちはdnsmasqを脆弱にし続ける新たな問題を発見しました。これらの脆弱性は、DNSキャッシュポイズニング、Denial of Service (サービス拒否 - DoS)、場合によってはリモートコード実行(RCE)につながる可能性があります。このブログでは、DNSキャッシュポイズニングについて詳しく説明し、dnsmasqのこれらの脆弱性について確認します。また、このような問題がKubernetesなどのクラウド製品に及ぼす影響についても説明します。

パロアルトネットワークスのお客様は、次世代ファイアウォールDNSセキュリティ、およびPrisma Cloudにより、このブログで概説される攻撃から保護されtています。

DNSの脆弱性の背景

以前のブログ「DNSの脆弱性の歴史とクラウド」で詳しく説明したように、ポートとトランザクションIDのランダム化は、キャッシュポイズニングから保護するために最新のDNSリゾルバが使用する重要な方法の1つです。

キャッシュポイズニングは、悪意のある応答を送信することにより、DNSリゾルバのキャッシュを汚染(ポイズニング)する攻撃です。この攻撃は、DNSリゾルバが要求を上位サーバーに送信した後に発生します。この時点で、攻撃者は、被害者の組織が接続したサーバーから送信されたように見える偽の応答を送信します。DNSリゾルバは悪意のある応答を受信してそれらをキャッシュします。それ以降、被害者の組織がDNSリゾルバにこのドメインを要求すると、攻撃者の制御下にあるサーバーのIPアドレスで応答します。この結果リダイレクトが発生すると検出が非常に困難になることがあります。たとえばユーザーが銀行のWebサイトを参照してURLを正しく入力した場合でも、キャッシュポイズニング攻撃によってDNSリゾルバが銀行のIPアドレスを返さずユーザーを攻撃者のIPアドレスへ向けてしまう可能性があります。これがもたらす深刻な影響のためDNSの脆弱性は重大なものが多くなっています。

この攻撃に対する緩和策の1つはリゾルバから上位サーバーへの要求のトランザクションIDと送信元ポートをランダム化することです。これらの2つの値をランダム化すると、それぞれ16ビット長になります。そして各要求には32ビットキーがあり、DNSリゾルバによって悪意のある応答が受け入れられるようにするためには、攻撃者がこのキーを照合する必要があります。

図1.DNSキャッシュポイズニング攻撃のまとめ

CVE

dnsmasqには最近2種類の脆弱性が見つかりました。

DNSキャッシュポイズニング攻撃に利用可能な、検証問題などのDNSプロトコルの実装におけるバグ

DoS攻撃につながる可能性のあるバッファオーバーフローバグ

これまでのところ、バッファオーバーフローの脆弱性の影響は、DoS攻撃に限定されているようです。

ただし、脆弱性の最初のグループは、壊滅的なキャッシュポイズニング攻撃を実行するために悪用される可能性があります。このため本稿ではこれらに焦点を当てます。

dnsmasqに固有のいくつかの重要な設計実装があります。これらの実装がどのように機能するかを知ることは、最近の脆弱性についての理解を深めるのに役立ちます。

CVE-2020-25684: トランザクションIDとポートのランダム化の不正実行

dnsmasqはトランザクションIDとポートのランダム化を実装しています。デフォルトでは、同時に最大64ポートまでをサポートしています。これは、dnsmasqが64ポートのオープンソケットを同時に保持し、これらの各ポートソケットで応答を待機できることを意味しています。攻撃者は送信元ポート(開いている64ポートのいずれか)を正しく推測する必要があります。そうでないと悪意のあるパケットがdnsmasqサーバー上で単にドロップされます。

これはよい緩和策のように思われますが、ここでの問題は、dnsmasqがトランザクションIDを送信元ポートと照合していないという事実にあります。攻撃者は、正確なトランザクションID正確な送信元ポートを推測しなければならないのではなく、トランザクションIDと、64個のポートのいずれかだけを推測する必要があります。これにより、ポートのランダム化による緩和策の強度は64分の1に弱まってしまいます。

つまり、dnsmasqはトランザクションIDを特定のポートと照合しないため、オープン要求をヒットさせる可能性が64倍高くなります。攻撃者は64個のオープンポートのいずれかに攻撃をヒットさせることで成功する可能性があります。

dnsmasqは応答と要求をどのように照合するか

frec (転送レコード)は、dnsmasqで受信したがキャッシュ内に存在しないレコードであるため、dnsmasqは要求を上位サーバーに転送する必要があります。要求が満たされない限り、つまり、dnsmasqが関連付けられている要求に対する応答をまだ受信していない限り、これはfrecと呼ばれます。dnsmasqをポイズニングしたい攻撃者は、frecに対して偽の応答を送信する必要があります。frecは、要求が満たされるか、または特定の時間が経過(タイムアウト)すると、削除されます。

しかし、dnsmasqは、各応答と正しいfrecをどのように照合するのでしょうか。dnsmasqは、DNSクエリの質問セクションのハッシュのみを保存し、残りは破棄します。各DNSクエリには「質問」セクションがあります。これは、クエリが実際の質問を保持する場所です。例: where is www.example.com

これが可能なのは、各DNS応答には応答している質問も含まれているため、要求と応答の両方にこのセクションがあるためです。このセクションは両サイドで完全に同じであるため、キーとして使用するのが便利です。dnsmasqは要求を送信する前に質問をハッシュし、受信した応答の質問をハッシュして、それをfrecを意味する質問と照合します。

これは、上位サーバーから受信した場合にfrecを照合するためのdnsmasqアルゴリズムの簡略化されたバージョンです。

1.0 応答の宛先ポートがオープンポートのいずれかに一致するかどうかを確認します

1.1 一致しない場合、応答をドロップします

2.0 キーの設定 = (応答の質問のハッシュ、トランザクションID)

3.0 キーで一致するfrecを検索します

3.1 見つからない場合、応答をドロップします

4.0 応答を処理します

デフォルトでは、dnsmasqは同時に最大150 frecまでサポートします。これは、所定の期間に150のオープンfrecが存在する可能性があることを意味します。これらの各frecは、前述した64のランダム化ポートのいずれかを使用します。

この行動を悪用する2つの方法がありますが、どちらも同じ結果になります。次のセクションでこの両方について説明します。

CVE-2020-25685: 弱いハッシュアルゴリズム

dnsmasqは、キーのハッシュ関数としてカスタムCRC32関数を使用します。残念ながら、CRC32は、暗号化された安全なハッシュ関数ではありません。すなわち、入力が異なっても同じ出力になる可能性があります。この場合、質問セクションが異なっていても同じ出力になる可能性があります。攻撃者はそれを悪用して、すべて同じCustom-CRC32ハッシュを生成する特別なドメインリストを作成し、そのリストを使用してdnsmasqに150個のクエリを送信することができます。

CVE-2020-25686: 保留中のクエリが確認されない

dnsmasqは、同じドメインに対して複数のクエリを許可します。これは、dnsmasqが任意の要求の結果を受信できるようになる前に、攻撃者がwww.example.comに150回クエリを実行できることと、150のクエリに対して150のオープンfrecが存在する期間があるということを意味します。

攻撃者がWebブラウザから攻撃を仕掛けた場合は、最新のほとんどのWebブラウザは同じドメインへの追加の要求をブロックするため、この方法は機能しません。このような場合、攻撃者は少し複雑な、以前の方法を使用しなければならないでしょう。

成果

これらの問題は両方とも同じ結果になる可能性があります。偽の応答を送信したい攻撃者は、dnsmasqが150のfrecを保持し、まったく同じハッシュされた質問キー、150の異なるトランザクションID、64の異なるポートを使用する時間枠でこれを実行することを選択できます。

攻撃者は、この時間を正しく設定し、開いている150のfrecがすべて同じドメインにあるときに、その小さな時間枠で偽の応答を送信する必要があります。攻撃者の偽の応答は、そのドメインに対しても行われます。このような場合、攻撃者が開いているfrecのいずれかで攻撃をヒットさせる可能性は、通常の攻撃の150倍になります。

応答が検証されない

dnsmasqは上位DNSサーバーからの応答を受信するさい、それを検証しません。ここで問題を理解するには、CNAMEレコードに精通している必要があります。

正規名またはCNAMEレコードは、エイリアス名を実際のドメイン名または正規のドメイン名にマップするDNSレコードの一種です。CNAMEレコードは通常、wwwmailなどのサブドメインをそのサブドメインのコンテンツをホストするアドレスにマップするために使用されます。たとえば、CNAMEレコードは、ドメインmail.example.comをドメインexample.comのメールサーバーにマップできます。

ただし、dnsmasqでは、CNAMEレコードの後に任意のAレコードを送信することができますが、dnsmasqはその応答を検証せずに、信頼するのみです。それらのAレコードについて誰も尋ねなかったため、dnsmasqはそれらのレコードをクライアントに転送しません。代わりに、指定されたすべてのAレコードをキャッシュするだけです。それだけではなく、dnsmasqはすでにキャッシュされているアドレスも上書きします。例:

www.example.com  CNAME  www.bank[.]com

www.bank[.]com     A      13.37.13[.]37

上記の例では、dnsmasqがwww.example.comに対するオープン要求に対する応答を受信し、攻撃者が正しいトランザクションIDと送信元ポートを取得した場合、以前にキャッシュされたアドレスのTTL (Time to Live)に関係なく、dnsmasqはwww.bank[.]comのキャッシュされているアドレスを上書きします。今後、銀行のWebサイトにアクセスしようとする組織は、攻撃者が管理するWebサイトにアクセスすることになります。

これはおかしな話だと思われますが、そうではありません。dnsmasqがCNAMEの後のすべての行を検証しなければならなかった場合、パフォーマンスが大幅に低下するからです。CNAME応答の各ドメインに接続し、指定されたAレコードが実際にそのアドレスであることを確認する必要があります。これにより、CNAMEの概念全体が冗長化されます。

したがって、その代わりに、dnsmasqは、トランザクションIDと送信元ポートのランダム化の緩和策に打ち勝つことはほぼ不可能であるという前提に立って、応答の送信元を信頼します。

攻撃シナリオの説明

理論

DNSキャッシュポイズニング攻撃を成功させるには、トランザクションIDと送信元ポートを正しく推測する必要があります。通常、これは32ビットキーを推測することを意味します。つまり、ポートに16ビット、トランザクションIDに16ビットです。

今まで示してきたように、CVE-2020-25684は攻撃者が正しいポートに攻撃をヒットさせる可能性を64倍高めることで攻撃者を支援しているため、キーのポート部分は16-log264=10ビット長に削減されています。トランザクションIDキーと組み合わせると、キーの長さはまだ26ビットです。これまでのところfrecで攻撃をヒットさせる可能性は1回の応答で1~226 = 67,108,864です。

CVE-2020-25685またはCVE-2020-25686のいずれかを使用して、同じドメインまたは特別なリストを持ち、同じ質問のハッシュを持つ150件の要求を使用することで、正しいfrecに攻撃をヒットさせる可能性が150倍高くなると結論付けました。これをCVE-2020-25684と組み合わせると、frec64 * 150 = 9,600倍攻撃をヒットさせる可能性が高くなります。これまでのところfrecに攻撃をヒットさせる可能性は1~232/9600 = 447,392倍です。

もう1つの問題は、ポイズニングを行うには、通常、攻撃者がDNSエントリのTime to Live値が期限切れになる(キャッシュから削除される)まで待つ必要があるということです。そうしない場合、DNSリゾルバはキャッシュからの結果をすぐに提供し、ポイズニングは発生しません。ただし、弊社のケースでは、必要なエントリをポイズニングするため、攻撃者はCNAMEレコードを悪用する可能性があります。

攻撃シナリオ

攻撃者はwww.bank[.]comをポイズニングしようとします。通常、これにはwww.bank[.]comがキャッシュからなくなるのを待ち、ポートを正しく推測し、トランザクションIDを正しく推測する必要があります。攻撃者が実際に成功する可能性があるのは、その場合だけです。

DNSリゾルバがdnsmasqの場合、攻撃者は最初の部分をスキップして、キャッシュに存在しない任意のドメインを照会するだけです。通常のAレコード応答で応答する代わりに、前述のように、攻撃者はCNAMEで応答します。

攻撃者は、ポートとトランザクションID (32ビット長のキー)を推測する必要があります。


図2.dnsmasqに対するキャッシュポイズニング攻撃。

上記の脆弱性を使用して、攻撃者は同じドメインに対して、または同じcustom-CRC32ハッシュを持つドメインのリストを使用して、150件の要求を発行できます。このように、攻撃者は推測可能な150のトランザクションIDを持ち、そのうちの1つのみに攻撃をヒットさせる必要があります。上記で計算したように、攻撃者はこの方法を使用することで、各応答で成功する可能性が9,600倍高くなります。

攻撃者が偽の応答の1つで攻撃をヒットさせる場合、dnsmasqはCNAME応答を受信し、その中のAレコードをすべてキャッシュします。

攻撃が成功する可能性

DNSについての私の最新ブログでは、DNSキャッシュポイズニング攻撃がさまざまな緩和策を使用しても成功する可能性について理解するために必要な確率の計算を行いました。計算は前回と同じですが、キーサイズは232 / 9600 = 447,392です。

攻撃者が攻撃を成功させるには、150個のトランザクションIDと64個のオープンポートのいずれかに攻撃がヒットしなければなりません。

私はシミュレートされたネットワークで信頼性の高い概念実証(PoC)を作成することができました。このネットワークでは、最悪の場合5分以内に、攻撃が成功した場合は平均10秒以内に社内ネットワーク内からdnsmasqリゾルバをポイズニングさせることができました。

KubernetesとOpenShift

dnsmasqはKubernetesのDNSサービスであるkube-dnsの一部です。kube-dnsサービスは、kube-system名前空間のkube-dnsポッドで実行される3つのコンテナで構成されます。

3つのコンテナは次のとおりです。

  • kube-dns: DNSクエリ解決を実行する、SkyDNSを実行するコンテナです。
  • dnsmasq: SkyDNSからの応答をキャッシュします。
  • sidecar: 指標の報告を処理し、サービスのヘルスチェックに応答するサイドカーコンテナです。

以前は、KubernetesとOpenShiftはDNSサービスにkube-dnsを使用していました。

Kubernetes v1.12の時点では、kube-dnsに置き換わり、CoreDNSが推奨されるDNSサーバーとなっています。ご使用のクラスタが最初にkube-dnsを使用していた場合、CoreDNSではなくkube-dnsをまだ使用している可能性があります。この場合、kube-dnsはdnsmasqを使用しており、この記事で説明しているように、dnsmasqは危険な可能性があります。CoreDNSはdnsmasqを使用しないため、Kubernetesの新しいバージョンは影響を受けません。

アプリケーション

dnsmasqを使用するKubernetesまたはOpenShiftクラスタは、上記の攻撃に対して脆弱になります。クラスタ全体をポイズニングするには、単一の導入環境を侵害するだけで十分です。もう1つの考えられる状況としては、内部ネットワークだけでなく、誤って設定され、インターネットに公開されているdnsmasqマシンがあります。DNSリゾルバがインターネットに公開されていると、ボットがパブリックIPをスキャンして検出しやすくなるため、このシナリオはさらに悪化します。

結論

これらの脆弱性は、長年にわたって追加されてきたあらゆる緩和策があるにもかかわらず、DNSキャッシュポイズニングが、今日の問題に直結している理由を再度示しています。

それでも、最近では、安全なブラウジングと証明書の使用により、攻撃者がドメインのDNSサーバーをポイズニングしたとしても、証明書が一致しないため、被害者の組織のブラウザがページをロードしない可能性が高くなっています。しかし、この技術は、ISPのDNSリゾルバをポイズニングし、存在しないIPアドレスに要求を転送することによる巨大なDoS攻撃にも依然として使用できます。

また、クラウドにおいては、問題ははるかに大きくなります。前述したように、Kuberenetesは、少し前までデフォルトのDNSリゾルバとしてdnsmasqを使用していました。現在でも、ユーザーはCoreDNSの代わりにdnsmasqを使用することを選択できます。このようなシナリオで、攻撃者がクラスタのDNSリゾルバをポイズニングすると、ブラウザとは異なり、クラウドアプリケーションでは通常、証明書の検証が行われないため、莫大な損害が発生する可能性があります。

攻撃者が1つのコンテナに侵入すると、コンテナエスケープの脆弱性がなくても、この攻撃を使用してクラスタ全体に容易に広げていくことができます。

パロアルトネットワークスをご使用のお客様は、さまざまな方法でこのブログで概説した攻撃から保護されています。パロアルトネットワークスの次世代ファイアウォールは、疑わしいDNSクエリや異常なDNS応答を検出することで、DNS攻撃をブロックできます。枯渇または大量のトラフィックに関連する攻撃は、ファイアウォールに組み込まれたDoSまたはゾーン保護プロファイルを使用して処理されます。これらの保護は、DNSセキュリティによるDNSの脅威とインジケータのカバレッジに追加されます。

さらに、Prisma Cloudをご使用のお客様は、脆弱なソフトウェアコンポーネントに関してアラートを発するPrisma Cloudコンピューティングホストとコンテナの脆弱性スキャナを通じて、この脅威から保護されています。このブログで説明する攻撃には、古い脆弱なdnsmasqの導入環境に加えて、次のいずれかが必要です。

  • 悪意のあるパケットを内部からDNSサーバーに送信できるようにする、クラスタの内部ネットワークの侵害。
  • インターネットに公開されている、誤って設定されたDNSリゾルバ。

このようなシナリオは、ほとんどの場合、Prisma Cloud Compute Compliance Protectionによって監視されている、古くて誤って設定されたアプリケーションを攻撃者が悪用することにより発生します。