クラウド環境
Traefik Proxyすり抜けのリスク:cAdvisorが公開するラベル情報の不正利用
本稿では、著名なクラウドネイティブのプロキシ・アプリケーション「Traefik Proxy」を絡めた分析に基づき、コンテナラベルをcAdvisorメトリクスとして公開するリスクについて解説します。
コンテナ監視ツール「cAdvisor(Container Advisorの略記)」に関する前回の調査では、設定不備のために機密情報がPrometheusメトリクスとして流出するリスクを分析しました。流出対象の情報として、環境変数内の認証情報やトークンなどを挙げました。一方、今回の調査では、環境変数だけでなく、稼働しているコンテナの「ラベル」もPrometheusメトリクスに取り込まれ、デフォルトで公開されることが判明しました。一般的にコンテナラベルはシークレットに相当しないものと見なされがちですが、実際のところはどうでしょうか。本稿では、著名なクラウドネイティブのプロキシ・アプリケーション「Traefik Proxy」を絡めた分析に基づき、コンテナラベルをcAdvisorメトリクスとして公開するリスクについて解説します。
はじめに
cAdvisorのメトリクス用エンドポイント「/metrics」が公開する情報を調べたところ、その中から、稼働している全コンテナに紐づくラベルが発見されました。コンテナラベルは「キーと値」のペア文字列として表現され、さまざまなメタデータの格納先として利用されます。対象のメタデータとして、稼働中のコンテナやイメージ、ボリューム、デーモン、ネットワークのライセンス情報や管理情報、バージョン情報などが挙げられます。例として、図1のDockerfileによってコンテナイメージをビルドすると、「LABEL」で指定したコンテナラベル(キー:「com.example.vendor」、値:「ACME Inc.」)が自動で登録されます。
コンテナラベルを利用する際のベストプラクティスとして、Open Container Initiative(OCI)のガイドラインがGitHub上に公開されています。
ここで、コンテナラベルが機密情報(シークレット)に相当するかについて、考えます。一般に、最終工程で使用されるコンテナラベルは、オブジェクトのメタデータに過ぎないものと「想定」されています。例えば、コンテナイメージをプル可能な形で公開する場合、そのコンテナラベル(図1のLABELで指定した箇所)にシークレットは含まれないものと想定されます。この点について試しにChatGPTに問いかけたところ、同様の「見解」が示されました(図2)。
回答はこちら
図2の日本語訳:
質問:シークレットや認証情報をコンテナラベルに格納することはありえるでしょうか。推奨事項や対策の提示は不要です。
回答:シークレットや認証情報をコンテナラベルに格納することは、推奨されません。コンテナラベルは通常、バージョニングや環境情報、デプロイ設定などのメタデータとして使用されるものであり、機密情報を扱う想定で設計されていません。また、機密情報の保護に必要な機能も十分には備わっていません。コンテナラベルは、標準的なコンテナ管理コマンドを使うだけでも簡単にアクセス可能です。従って、こうした方式でシークレットを格納すると、それが意図せず公開されたり、未承認ユーザに不正利用される可能性があります。
エンドポイント「/metrics」からメトリクスを取得
前回の記事では、稼働しているコンテナの環境変数がエンドポイント「/metrics(図3)」を介して公開される仕組みを解説しました。ここで公開されるデータは、オープンソース・ツール「prom2json(Prometheusの開発陣による呼称)」により、さらに読みやすい形式に変換できます。本ツールは、Prometheusメトリクスのスクレイピング(抽出、加工)や、JSONファイルへの変換機能を提供します。図4に、エンドポイント「/metrics」からコンテナラベルを取得するコマンドの例を示します。
図4のコマンドを用いることで、公開状態にあるcAdvisorのエンドポイント「/metrics」からコンテナラベルを取得できることが分かりました。次の注目は、こうしたコンテナラベルにどのような情報が格納されているか、という点です。今回の調査で特に目を引いた点として、「container_label_traefik_」から始まる名前のコンテナラベルから、ユーザ名やパスワードのハッシュ値にあたるデータが発見されました。
Traefik Proxyの概要
先述の「container_label_traefik_」から始まるコンテナラベルは、クラウドネイティブのプロキシ・アプリケーション「Traefik Proxy」によって使用されるものです。Traefik Proxyの主な機能として、流入データの制御、リバースプロキシ、Webアプリケーション用ファイアウォール、ロードバランサなどが挙げられます。公式ドキュメントに記載の通り、本ツールは「サービス探索」の仕組みにより、通信データのルーティング(本稿では「配送」と表現)設定を動的に構成します。通信プロトコルとして、HTTP/2やHTTP/3、TCP、UDP、WebSocket、gRPCなどの主要なものを一通りサポートしています。また、ロードバランサやレート調整、Circuit Breaker、ミラーリング、認証などの機能をミドルウェアによって実現します。さらに、SSLターミネーションや、オープン認証局「Let's Encrypt」による証明書の自動作成にも対応しています。
Traefik Proxyがネイティブ・サポートするプラットフォームやサービスは多岐に及び、KubernetesやDocker Swarm、etcd、Azure Service Fabric、Amazon Elastic Container Service(ECS)、Azure Kubernetes Service(AKS)、Elastic Kubernetes Service(EKS)、Google Kubernetes Engine(GKE)、OpenShiftなどが含まれます。こうした長所も相まって、Traefik Proxyは幅広いユーザ層からの支持を受け、GitHub上では48,000件以上のスターを獲得しています。その広範かつ高度な機能は、多種多様に及ぶアプリケーションの包括的なゲートウェイと見なせるでしょう。
Traefik Proxyのコンポーネント
Traefik Proxyが使用する基本コンポーネントとその役割を、下記に示します。
- プロバイダ:通信リクエストの配送設定をAPI経由でTraefik Proxy側に伝え、動的な更新をサポートする(例:Docker、ECS)
- エントリポイント:ネットワークの入口に相当する構成要素であり、ポート番号や通信プロトコルによって定義される
- ルータ:「2.エントリポイント」で受信したリクエストを分析し、必要に応じて「4.ミドルウェア」を呼び出した上で、適切な「5.サービス」に引き渡す
- ミドルウェア:リクエストやレスポンスを「3.ルータ」から「5.サービス」に引き渡す前に、各種処理を実行する(例:基本認証、URL加工)
- サービス:リクエストやレスポンスを最終的なハンドラに渡す方式を指定する(例:ロードバランサ)
上記のうちプロバイダとエントリポイントは、Traefik Proxyの起動時に指定したものがそのまま利用され続け、後から変更されることのない「静的」なコンポーネントに相当します。一方、ルータ、ミドルウェア、サービスは、Traefik Proxyの起動後にもその内容が変化する「動的」なコンポーネントであり、これによって、通信リクエストの動的な配送を実現します。
(出典:Traefik)
図5においてTraefik Proxyは、受信したリクエストを確認し、そのURL(/path1、/path2、/path3)に対応するバックエンド・サービスに配送します。配送先に関する設定情報は、コンポーネントの項で挙げた「プロバイダ」から動的に取得します。このプロバイダとしては、Dockerのようなコンテナ・エンジンやオーケストレータ、クラウドプロバイダ、キー・値によるデータストアなどを利用可能です。プロバイダが提供する配送先情報に変更や追加があった場合、Traefik Proxy側で、その内容を動的に取り込むことが可能です。
エントリポイントで受信したリクエストについては、そのヘッダーやURL、ホスト情報に応じて、受け入れ先のルータ(先述したコンポーネントの1つ)を決定します。個々のルータには、ヘッダーやURLの照合パターン(図6)を組み合わせた設定事項「ルール」が存在し、これにより、受信リクエストの受け入れ判定を行います。受け入れ先となったルータは、コンポーネントの項で挙げた「ミドルウェア」を呼び出し、リクエストに対する各種処理を実行します。最後に、もう1つのコンポーネントである「サービス」にリクエストを引き渡します。
(出典:Traefik)
プロバイダとしてDockerやSwarm、Amazon ECSを使用している場合、Traefik Proxyはコンテナラベルやファイルを参照する形で、配送先設定を動的に生成します。今回は特に、公式ドキュメントに記載のあるDockerコンテナを用いた方式(図7)に着目しました。本方式では、「Docker Compose」のYAML設定ファイル中、services配下のlabels要素(図8参照)にコンテナラベルを記載します。また、Traefik Proxy側で当該のコンテナラベルをDockerエンジンから動的に取得できるように、Dockerソケットへのアクセスを追加します(図8のvolumes)。
(出典:Traefik)
図8の構成例では、Dockerをプロバイダとして指定し(--providers.docker)、ポート番号80宛てのリクエストを待ち受けるエントリポイントを「web」の名前で作成(--entrypoints.web)します。本構成に基づくTraefik Proxyの動作概要を、下記に示します。
- Traefik Proxyが各サービスの配送先情報をプロバイダ「Docker」から取得する。
- エントリポイント「web」により、ポート番号80宛てのリクエストを待ち受ける。
- Webサーバ「nginx」のコンテナラベル(labelsの部分)により、Traefik Proxyのルータが自動設定される。labelsの1行目は、エントリポイント「web(ポート番号80)」に届くリクエストがnginxへの配送対象であることを示す。
- labelsの2行目は、先述の「ルール」であり、リクエストヘッダー「Host」が「nswashere.local」であるかをチェックする。結果、宛先ポートが80で、かつヘッダー「Host」の値が「nswashere.local」となるリクエストは、Webサーバ「nginx」に配送されるようになる。
図8の構成は、リバースプロキシ(Traefik Proxy)のポート80を介してWebサーバ(nginx)にアクセスすることを想定しています。なお、nginx自体のポートは一切露出していません。この状態でリバースプロキシにアクセスしたところ、ヘッダー「host」が未指定の場合は、「404 page not found(ページが見つかりません)」のエラーが返されました(図9の2行目)。一方、ヘッダー「host」として「nswashere.local」を指定した場合は、期待通り、nginxのウェルカムページが返されました(図9の4行目以降)。
図8では、nginxに対応するルータの設定を、コンテナラベルとして記載しました。そのため、図10のようにDocker CLIを用いてコンテナラベルの一覧を取得すると、当該の設定内容が表出します。
認証機能を追加
ミドルウェアを用いることで、リクエストをサービス側に送信する前に、内容の調整やURLのプレフィクス加工、認証関連の処理を実行できます。HTTPプロトコルで利用可能なミドルウェアの一覧は、こちらから確認できます。今回は、基本認証(BasicAuth:RFC 2617)に相当するミドルウェアを分析しました。
ミドルウェア「BasicAuth」を用いることで、未承認ユーザではサービスにアクセスできないように、制御することが可能です。本機能を使用するにあたり、プロバイダがDockerの場合は、承認済みユーザの名前とパスワードを指定する必要があります。パスワードについては、平文ではなく、そのMD5、SHA1、またはBCryptのハッシュ値で指定します。本情報の具体的な設定法を、下記に示します。
図11に、ミドルウェア「BasicAuth」を組み込んだ場合の構成例を示します。
図12の通り、ヘッダー「host」の値が「nswashere.local」で、かつ認証情報「test:test」を指定した場合のみ、nginxのウェルカムページが表示されます。先と同様にDocker CLIを用いてコンテナラベルの一覧を取得すると、図13の通り、nginxのアクセスに必要なユーザ名とパスワードのハッシュ値が表出します。Traefik Proxy側では、当該情報をnginxサービスから動的に取得し、認証の手続きを実行します。
以上の通り、今回はDockerをプロバイダとするTraefik Proxyを構成し、その設定情報をコンテナラベル内に記載しました。Traefik Proxyは、コンテナラベルを通して環境内のサービスを動的に検知します。また、当該ラベルの内容に基づいてヘッダー「host」の照合処理やミドルウェア「BasicAuth」による認証処理を行い、通信リクエストを動的に配送します。こうしたコンテナラベルの一覧を取得する方法として、コマンド「docker inspect」が存在します。実際に対象サービスのコンテナラベルを取得したところ、その中には、Traefik Proxyのルール設定や認証情報が確かに含まれていました(図13)。これは動作仕様として当然の結果ではありますが、その意味するところに注意する必要があります。
cAdvisorの検討
cAdvisorをデフォルト設定で起動すると、コンテナラベルがPrometheusメトリクスとして公開されます。さらに重要なこととして、cAdvisor自体には、メトリクス用エンドポイントの保護機能が備わっていません。そこで今回は、cAdvisorのメトリクス用エンドポイントを公開し、かつ、Traefik Proxyを並行稼動している状況について、調査しました。例として、図14に示すDocker ComposeのYAMLファイルには、脆弱な設定が含まれています。
上図の構成例は、図11に対してcAdvisorのサービスを新たに追加したものです。cAdvisorは、リバースプロキシ(Traefik Proxy)とWebサーバ(nginx)の両コンテナを監視すると同時に、ポート番号8080にダッシュボードを公開します。実際に本構成によってcAdvisorを起動し、メトリクス用エンドポイントにアクセスすると、Traefik Proxyのコンテナラベルを確かに取得できることが分かりました(図15)。
- BasicAuth(基本認証):ユーザ名とパスワードのハッシュ値(BCryptまたはMD5)
- Headers(ヘッダー):コンテンツ・セキュリティ・ポリシーの値
- IPWhiteList(IPホワイトリスト):sourceRangeの値(許可対象のIPアドレスを指定)
- RedirectRegex(リダイレクト用正規表現):URL照合用の正規表現
2. ルータのルール設定に用いられる照合パターン(図6に対応)
以上の情報が未承認ユーザに不正利用された場合、Traefik Proxyの保護下にあるエンドポイントに侵入される可能性があります。ミドルウェア「BasicAuth」の設定情報からは117個の一意なパスワード・ハッシュ値が確認され、そのうちの25個は、一般公開されている単語リストでクラック可能なものでした。こうした暴かれやすいパスワードが実際に使用されていることについて、十分に注意を払う必要があります。一方、ルータのルール設定が知られた場合、有効と見なされるリクエストヘッダー「Host」の値や正規表現、リクエストの最終的な配送先となるバックエンド・サービスを特定される可能性があります。
不正利用のシナリオ
先述のようにcAdvisorは、Traefik Proxyの設定情報を含むコンテナラベルをメトリクスとして取り込み、外部に公開します。こうした情報が攻撃者の手に渡ると、Traefik Proxyをすり抜けられ、その先にあるサービスに不正アクセスされる恐れがあります。本攻撃シナリオの流れを、下記に示します。
- 攻撃者が公開状態のcAdvisorエンドポイント「/metrics」にアクセスし、起動中の全コンテナに対応するコンテナラベルを入手する。本エンドポイントはデフォルトで有効化されるため、cAdvisorのネイティブ機能だけでは、こうした状況を抑止できない。
- 攻撃者は、特定のコンテナラベルを調べることで、Traefik Proxyの保護下にあるサービスや、そのアクセス法を特定できる。当該ラベルの例として、リクエストヘッダー「Host」の照合パターンや、ミドルウェア「BasicAuth」のユーザ名やパスワード・ハッシュ値が挙げられる。ハッシュ値については、オフライン作業でクラックされる可能性がある。
- 攻撃者は、クラック済みの認証情報やリバースプロキシの構成情報を用いることで、Traefik Proxyの壁をすり抜け、その先にあるサービスに侵入する可能性がある。
今回の調査では、Traefik Proxyだけでなく、Amazon ECSのメタデータを含むコンテナラベルも別途発見され、そこからECSコンテナやECSクラスタ、ECS Task ARNの名前を特定できることが判明しました。こうした情報を起点として、さらにAWSアカウントIDなどの環境情報を暴かれる可能性もあります。公式ドキュメントの記載上、AWSアカウントIDはシークレットと見なされていません。しかし、標的環境の偵察活動に利用される可能性を踏まえ、シークレットと見なすべきであるという意見が、リサーチコミュニティ内で活発に交わされています。
防御策
これまでに挙げた例では、Traefik Proxyの設定をコンテナラベルに記載する方式を用いました。しかし、コンテナラベルよりも、さらに安全な方式が存在します。図18の構成例では、コンテナラベルの代わりに、外部ファイルに設定情報を書き込みます。
上図では、Traefik Proxy側で静的設定ファイル「./traefik.yml」と動的設定ファイル「./dynamic.yml」を使用できるように、両者をマウントしています。Traefik Proxyの静的設定ファイルはフラグ「--configFile」によって指定できますが、デフォルトでも下記ディレクトリ内のtraefik.ymlが順に参照されます。
- /etc/traefik/
- $XDG_CONFIG_HOME/
- $HOME/.config/
- .(現在の作業ディレクトリ)
静的設定ファイルについては、図19の通り、エントリポイントに続き、ファイル・プロバイダ(動的設定ファイルのパス)を指定します。
動的設定ファイルについては図20の通り、ルータやミドルウェア、サービスの定義を記載します。
上図に示す動的設定の内容は、先の図14でコンテナラベルによって指定したものと同一です。しかし、改めてcAdvisorのエンドポイント「/metrics」からコンテナラベルを取得すると、そこにはTraefik Proxyの設定情報が含まれていないことが分かります。
先のような形で設定情報が意図せず公開される事態を防ぐためには、下記の対策が有効です。
- メトリクス用エンドポイントを外部公開する必要がないのであれば、外部アクセスを拒否するための措置をとる。
- 使用しているエッジルータの機能やリスクを入念にチェックし、その脅威モデルを作成する。例えば、cAdvisorによってコンテナラベルが公開されている場合、ミドルウェア「BasicAuth」のオプション「users」の代わりに「usersFile(認証情報を外部ファイルで設定)」を使用する。これにより、認証情報のハッシュ値が流出するリスクを軽減できる。攻撃者にとって、単純にメトリクスを参照するよりも、外部ファイルにアクセスする方が、敷居は高いと考えられる。
- 誤って情報を流出させないように、システム上で外部に露出している箇所を継続的に監視する。
- コードベース(Docker ComposeやKubernetesのYAML)を自発的にスキャンし、Traefik Proxy がDockerやSwarm、Amazon ECSのコンテナラベルに依存して動作していないか、検査する。特に、認証情報や機密情報の管理には、コンテナラベルではなくファイル・プロバイダを用いることが望ましい。
- cAdvisorの安全性を高めるため、通信プロトコル「TLS」やミドルウェア「BasicAuth」を利用し、匿名ユーザによる外部アクセスを阻止する。
- cAdvisorによって全コンテナラベルが公開されないように、オプション「--store_container_labels」を用いてコンテナラベルをメトリクスから除外するか、またはオプション「--whitelisted_container_labels」を用いて許可対象のコンテナラベルを限定する。
- cAdvisorのダッシュボードを外部公開しない。前回の調査では、公開状態のcAdvisorから情報が流出するリスクについて、解説した。
まとめ
Traefik Proxyは、単独であれば、すぐに安全に利用できるように見受けられます。しかし、cAdvisorのようなコンポーネントが同時起動する環境下では、その安全性もやや不明瞭なものとなります。原因として、DockerやECS、Swarmをプロバイダとした際のコンテナラベルの利用法や、その設計方針が挙げられます。Traefikは今回の件について、大変有意義で洞察に富んだ見解やセキュリティ・ガイドラインを提示しました。その内容は、本稿にも反映されています。レビューを通してTraefikは、Dockerラベルが認証情報などの機密情報を格納する手段として安全ではないことに同意しました。これは、本稿で挙げたセキュリティ上の懸念点を裏付けるものです。ラベルが配送ルールの設定に役立つことは、確かにあるでしょう。しかし、機密情報に対してはファイルやシークレットなどの安全な方式を用いるべきであり、Traefikも、そのように推奨しています。
本稿に挙げた懸念の根本は、特定機能の利用に関する「想定」と「実態」が乖離、または互いに依存していることにあります。こうした目に見えにくい歪みは、やがて攻撃者に利用され、防御者に痛手を与えることになります。また、サービス単体では安全でも、他サービスと同時稼動した時に初めて危険性が表出することがあります。コンテナラベルをオブジェクト・メタデータの格納先に利用すること自体は、理にかなっています。しかし、コンテナラベルを機能上の一端に組み込むと、そこに目が届きにくくなる点に注意する必要があります。コンテナラベルは、手動で意図的にチェックしない限り、ユーザの目に映らないためです。アプリケーションを保護するためには、関連するさまざまなコンポーネントやサービスに目を向け、その複雑な繋がりを理解する必要があります。本稿の例で言えば、cAdvisorによって公開される情報の内容や、当該ツールを他サービスと併用した際に生じるリスクについて、注意することが重要です。
参考記事:
Leaky Labels: Bypassing Traefik Proxy Leveraging cAdvisor Metrics
By: Nitesh Surana
翻訳:清水 浩平(Core Technology Marketing, Trend Micro™ Research)