Nozomi Networks 人気のC標準ライブラリにパッチ未適用のDNSバグが発見されるIoT が危険にさらされる

Nozomi Networks 人気のC標準ライブラリにパッチ未適用のDNSバグが発見されるIoT が危険にさらされる

この記事は2022年6月6日に更新され、2022年5月20日付でuClibC-ngバージョン1.0.41が修正されたことに留意されたい。修正されたライブラリは こちらから.

Nozomi Networks 研究所は、IoT 製品で人気のある C 標準ライブラリであるuClibcおよびuClibc-ng の全バージョンのドメインネームシステム(DNS)実装に影響する脆弱性(CVE-2022-30295、ICS-VU-638779、VU#473698 で追跡)を発見した。この欠陥は、ライブラリが生成する DNS リクエストに含まれるトランザクション ID の予測可能性に起因しており、攻撃者はターゲットデバイスに対して DNS ポイズニング攻撃を実行できる可能性があります。

それぞれの公式ウェブサイトによると、uClibcは、Linksys、Netgear、Axis(2010年まで、新しいAxis製品には他のライブラリが含まれている)などの主要ベンダーや、Embedded GentooなどのLinuxディストリビューションで使用されていることが知られている

ライブラリのメンテナが修正プログラムを開発できなかったため、この脆弱性にはパッチが適用されていません。このため、本脆弱性を再現できたデバイスの詳細については開示していない。

このブログでは、IoT デバイスで使用されている C 標準ライブラリの背景から始まり、問題の技術的分析とその悪用可能性の詳細、そして情報公開プロセスの包括的なタイムラインを紹介する。

背景C標準ライブラリとuClibc

コンピューティングにおいて、ライブラリとは、ソフトウェア間で共有されるリソース(関数、設定データ、仕様など)のコレクションである。ライブラリの目的は、ソフトウェアが一般的な操作(ディスク上のファイルへのアクセスやネットワーク操作など)を実行するために使用できる標準的なプリミティブを提供することであり、それらを常に再実装する必要はない。

A C standard library is no exception, in the sense that it is a library for the C programming language itself. A real-world example can be found in the well-known C “Hello, World!” program. When we type the pre-processor command “#include <stdio.h>” and invoke an output function (for instance, “printf”) to print “Hello, World!”, we are actually executing the code of the chosen output function provided by the selected C standard library for the implementation of the header file “stdio.h”.

特筆すべきは、uClibcは利用可能なC標準ライブラリの1つであり、特に組み込みシステムに特化していることだ。他の有名なC標準ライブラリには、glibc(GNU Cライブラリ)、musl libc、Microsoft Cランタイムライブラリ(CRT)がある。

Cの標準ライブラリに影響を及ぼす脆弱性は、少々複雑なものになる可能性があることに注意することが重要だ。一つのプログラムの複数の箇所で脆弱性のある関数が何百、何千と呼び出されるだけでなく、その脆弱性は、そのライブラリを使うように設定された複数のベンダーの不特定多数の他のプログラムに影響を与えるだろう。

ドメインネームシステム(DNS)

ご存知のように、現代のコンピュータネットワークにおいてDNSは、ドメイン名を関連するIPアドレスに変換することを主な、そして重要な目的として機能する階層型データベースであり、ユーザーは複雑な数字の羅列ではなく、人間に親しみやすい名前を記憶することで、より簡単にリソースにアクセスすることができる。

Under the hood, DNS requests are mostly transmitted through UDP, which is a connectionless protocol. Thus, in order to distinguish the responses of different DNS requests, besides the usual 5-tuple {source IP, source port, destination IP, destination port, protocol} and of course the query, each DNS request includes a parameter called “transaction ID”. This is a unique number per request that is generated by the client, added in each request sent, and that must be included in a DNS response to be accepted by the client as the valid one for a corresponding request. If this condition is false, the response is discarded; if true (and other checks are satisfied as well), the response is accepted and the program that asked for a translation of a certain domain name can initiate the connection to the IP address provided.

DNSエクエストの例
図1.DNSリクエストの例。5タプル、txID、およびクエリは赤でハイライトされている。

他のC標準ライブラリと同様に、uClibcは、プログラムがルックアップや他のDNS関連要求を容易に実行できるようにする、広範なDNSクライアントインターフェースを提供する。

DNSへのポイズニング攻撃

その関連性から、DNSは攻撃者にとって貴重な標的となり得る。DNSポイズニング攻撃では、攻撃者はDNSクライアントを欺き、偽造された応答を受け入れるように仕向けることができるため、特定のプログラムが正当なエンドポイントではなく、任意に定義されたエンドポイントとネットワーク通信を実行するように誘導することができる。DNSポイズニング攻撃は、攻撃者がDNSレコードをポイズニングすることで、ネットワーク通信を自分のコントロール下にあるサーバーに迂回させることができるため、その後の中間者攻撃を可能にする。攻撃者はその後、ユーザーから送信された情報を盗んだり、操作したりすることができ、それらのデバイスに対して他の攻撃を行い、完全に侵害することができる。ここでの主な問題は、DNSポイズニング攻撃がどのように認証応答を強制できるかということである。

あるDNSリクエストに対してDNS応答を受け付けるには、前述の5タプルとクエリ、およ びトランザクションIDが正しく設定されていなければならない。1.プロトコルはDNS、2.宛先ポートは53/udp、3.クエリは攻撃者が侵害したいターゲット、4.送信元IPアドレスはターゲッ トマシン、5.宛先IPアドレスは公開情報(あるネットワークで使用されているDNSサーバーのIPアドレス)であるとすると、未知なのは送信元ポートとトランザクションIDだけである。この2つのパラメータが可能な限り予測不可能であることが極めて重要である。

脆弱性の詳細

ラボでテスト中のIoT デバイスが実行した DNS リクエストのトレースを確認していたとき、Wireshark の出力から実行された DNS リクエストのパターンに気づきました。以下のスクリーンショット(図2)を見ると、トランザクションIDが最初にインクリメントされ、次に値0x2にリセットされた後、再びインクリメントされていることがわかる。

DNSリクエストのトレース
図2. IoT 、テスト対象のデバイスが実行したDNSリクエストのトレース。

関連する実行ファイルをデバッグし、根本的な原因を理解しようとしているうちに、DNSリクエストを実行するコードが実行ファイル自体の命令の一部ではなく、使用されているC標準ライブラリ、すなわちuClibc 0.9.33.2(「libuClibc-0.9.33.2.so」)の一部であることに気づいた。

ソースコードレビューの結果、uClibcライブラリは、ソースファイル「/libc/inet/resolv.c」にある内部の「__dns_lookup」関数を呼び出すことでDNSリクエストを実装していることが判明した。

DNSルックアップ機能
図3.uClibcのDNSルックアップ機能。
行#1240を参照すると、この関数は静的変数「last_id」を宣言しているこの変数には、最後のDNSリクエストで使用されたトランザクションIDの値が格納され、"__dns_lookup "の最初の呼び出し時に値1で初期化される
行#1240を参照すると、この関数は静的変数「last_id」を宣言している。この変数には、最後のDNSリクエストで使用されたトランザクションIDの値が格納され、"__dns_lookup "の最初の呼び出し時に値1で初期化される

さらに、行#1260で、この関数は変数「local_id」を宣言している。この変数には、次のDNSリクエストで使用されるトランザクションIDの値が格納される。

その後、以下のコードが実行される。

uClibcのDNSルックアップ機能
図4.uClibc (2)のDNSルックアップ機能。

行#1309を参照すると、最初のDNSリクエストで、変数 "local_id "は最後のDNSリクエストのトランザクションID("last_id")の値で初期化される。行#1320が脆弱性の実際の核心である:「local_id "は、古い値を1インクリメントすることで更新される。最初の起動時に値が1に初期化されることを考えると、これが、前のWiresharkのスクリーンショット(図2)でトランザクションIDが0x2にリセットされた理由である。

1321行目でビットごとのANDを行った後、この値は1323行目で「last_id」変数に格納される。最後に、#1335行目で "local_id "の値がstruct resolv_header "h "変数内にコピーされる。このコードの同様の修正は、uClibcとuClibc-ngのすべてのバージョンで見つかった。

脆弱性 Exploitability

トランザクションIDが予測可能になったことを考えると、この脆弱性を悪用するためには、攻撃者は正しいソース・ポートを含むDNSレスポンスを作成し、DNSサーバーから送られてくる正当なDNSレスポンスとの競争に勝つ必要がある。この問題の悪用可能性は、まさにこれらの要因に依存する。この関数は明示的なソース・ポートのランダム化を適用していないため、オペレーティングシステムが固定または予測可能なソース・ポートを使用するように設定されている場合、この問題は信頼できる方法で容易に悪用される可能性が高い。

オペレーティングシステムがソース・ポートのランダム化を適用している場合(現 在ではすべてのOSで行われている-例えば、最新のLinuxカーネルは32768~60999の 範囲を使用している)、悪用可能性は、攻撃者が複数のDNS応答を送信して16ビットのソース・ ポート値をブルートフォースし、同時に正当なDNS応答との競争に勝てるかどうかに依存する。この状況では、攻撃可能性は、攻撃者が自由に使用できる帯域幅やDNSクエリの 応答時間などの要因に依存する。さらに、散発的なクエリを実行するターゲットと比較して、ターゲットデバイ スが一定時間内に多数の同一のクエリを実行する場合、攻撃者がDNSポイズニング攻撃 を少なくとも1回は成功させる可能性が高くなる。

緩和策

注:このブログの最後にある更新情報をご覧ください。

この脆弱性にはまだパッチが適用されていませんが、私たちは解決策を見つけるために、ライブラリのメンテナやより広範なコミュニティと協力しています。

この脆弱性にはまだパッチが適用されていないため、コミュニティの安全のため、私たちはテス トを行った特定のデバイスを公表することはできない。しかし、私たちは、それらが、すべての重要なインフラに配備されている可能性の高い、最新 のファームウェア・バージョンを実行している、様々なよく知られたIoT デバイスであったことを明 らかにすることができる。

IT環境とOT 環境の両方において、ネットワークの可視性とセキュリティを高めることをお勧めする。

情報開示のプロセスとスケジュール

事件の時系列は以下の通りである:

  • 2021/09/13:ICS-CERTへの開示
  • 2021/10/05:ICS-CERTからのアップデートを求める
  • 2021/10/05: チケット番号ICS-VU-638779、VU#473698の予約について
  • 2021/10/26:ICS-CERTからのアップデートを求める
  • 2021/11/19:ICS-CERTにアップデートを求める2度目の試み
  • 2021/11/29: CERT/CC VINCEケースへの招待を受ける
  • 2021/12/08:CERT/CCから、最新の1.0.39バージョンで脆弱性を検証し、開示状況に関する洞察を提供するよう要請があった。
  • 2021/12/09:CERT/CCに回答、脆弱性は1.0.39で確認、現時点ではICS-CERTのみに開示が提出されたとCERT/CCに通知
  • 2021/12/09 (およびそれ以降):CERT/CCによるVINCEケースへのuClibc-ngメンテナ招待の試み
  • 2022/01/24: CERT/CCがVINCEのケースに複数のベンダーを招待、脆弱性が公開される
  • 2022/02/24: CERT/CCの更新を要請
  • 2022/03/11:uClibc-ng メンテナに連絡を試みる
  • 2022/03/14:メンテナは、CERT/CCから連絡を受けたことを確認し、自分では脆弱性を修正できないと説明し、コミュニティからの助けを期待して公開するよう明確に要請した。
  • 2022/03/15-16:次のステップについて CERT/CC と協議。メンテナに再確認を依頼し、30日以内にベンダーへの開示通知に進む予定。
  • 2022/03/18: メンテナに再確認を依頼
  • 2022/03/21: CERT/CC はベンダーに VINCE 事件の状況報告を行った。
  • 2022/03/21-22:次のステップについてCERT/CCと協議
  • 2022/03/23: メンテナへのメール再送
  • 2022/03/29: CERT/CCに、メンテナからの回答(または反対注文)がないことを考慮し、ベンダへの30日通 知を進めることを提案。
  • 2022/04/01: CERT/CCが情報開示スケジュール案を承認
  • 2022/04/01: VINCEの件でベンダーに状況報告を行い、5月2日に脆弱性が公表されることを伝えた。
  • 2022/05/02:情報公開
  • 2022/05/20: メインテナがこの脆弱性の修正をリリース
  • 2022/06/03:Nozomi Networks 、CERT/CCとベンダーに修正を通知した。
  • 未定:ベンダーが修正を実施

軽減措置の最新情報

UPDATE:2022年5月20日現在、uClibC-ngバージョン1.0.41が修正されています。修正されたライブラリはこちらからダウンロードできます。ライブラリのメンテナはこの修正をリリースしましたが、アセット所有者は、ベンダーがファームウェアにパッチを当てるのを待つ必要があります。以下は、DNSセキュリティに関するその他の推奨事項です:

  • 信頼されたローカルネットワークに、DNSプロキシとして機能する別のデバイスを配置する。脆弱なデバイスがDNSクエリをDNSプロキシに送信するように設定し、DNSプロキシがDNSクエリを外部ネットワーク(資産所有者が管理していないネットワーク)にのみ送信できるようにする。
  • デバイスでドメインネームシステムセキュリティ拡張(DNSSEC)を有効にする
  • エンドツーエンドの暗号化通信(DNS over TLS、DNS over HTTPS、VPNなどを使用)で、信頼できるDNSサーバーにDNSクエリーを送信するようにデバイスを設定する。