コンプライアンス
Azure DevOps Server 2020におけるデフォルト設定時(HTTP)のサプライチェーン攻撃
本ブログ記事では、構成が不適切なAzure DevOps Server 2020に対するサプライチェーン攻撃について解説します。特に、継続的インテグレーション/継続的デリバリ(CI/CD)パイプラインエージェントがTLSを使用せず通信する場合の技術的な詳細を説明します。
送信データに対する暗号化の必要性から、法人組織はTLSを頼りにするようになっています。これはインターネットを介してデータを送信する場合だけでなく、信頼された企業環境の中でも言えることです。TLSやSSLを使用しない場合、送信されたデータの真正性とエンドポイントのアイデンティティを検証することはできません。
本ブログ記事では、構成が不適切なAzure DevOps Server 2020に対するサプライチェーン攻撃について解説します。特に、継続的インテグレーション/継続的デリバリ(CI/CD)パイプラインエージェントがTLSを使用せず通信する場合の技術的な詳細を説明します。本ブログの公開に先立ち、トレンドマイクロはMicrosoft社に連絡を取っており、サプライチェーン攻撃のリスクを軽減するために同社が推奨するベストプラクティスについてもご紹介します。
■ Azure DevOps Server 2020の概要
Azure DevOps Serverは、以前はVisual Studio Team Foundation Serverと呼ばれていたオンプレミスソフトウェアです。レポート作成、要求管理、プロジェクト開発、自動ビルド、プロジェクト管理、CI/CDなどに使用されます。
![](/content/dam/trendmicro/global/ja/research/22/b/supply-chain-attack-on-azure-devops-server-2020/image01.jpg)
図1:サプライチェーンの工程
この記事では、サプライチェーンの工程におけるCI/CDパイプラインのステップに焦点を当てます。通常、CI/CDパイプラインでは分散型アーキテクチャを採用し、コンテナやマシンなどの複数の環境でビルドエージェントを実行してビルドタスクを遂行します。Azure DevOps Serverも例外ではなく、複数のプラットフォームで利用できる独自のパイプラインエージェントを提供しています。これにより、プライマリマシン上、または各種の構成やシークレットを格納したメインサーバ上での望ましくないコード実行を防止するだけでなく、さまざまなプラットフォーム向けにコードをビルドし、より多くのビルドを同時に実行できます。
![](/content/dam/trendmicro/global/ja/research/22/b/supply-chain-attack-on-azure-devops-server-2020/image02a.jpg)
図2:複数プラットフォーム向けに提供されるAzure DevOps Serverのビルドエージェント
ビルドタスクの実行時には、ソースコードを構成してコンパイルするためのプロセスの生成が必要となります。これはビルドエージェント上でのリモートコード実行(RCE)と見なせますが、プロセスが不正なものでない限り、または意図どおりにタスクを実行できている限りは、これは正常な工程であることに注意してください。また、この工程の間はビルドエージェントがコードの機密性を保持する必要があることも重要です。そのため、一連の工程を安全に実施するためには、保護された通信チャネルの確立が不可欠です。
では、ビルドエージェントとAzure DevOpsサーバの間で使用される通信チャネルを見てみましょう。Azure DevOpsサーバはIIS(Internet Information Software)Webサーバ上のWebサービスとして実行されます。新しいエージェントを登録するには、ユーザが「ビルド環境」オプション内でエージェントをインストールし、構成スクリプトを実行します。その後、このスクリプトがサーバに接続してエージェントの登録を試み、処理を続けるために認証を求められます。ここまでは特に問題なさそうに見えます。しかし、何事も細部に落とし穴があるものです。Azure DevOpsサーバはデフォルト設定ではHTTP(Hypertext Transfer Protocol)を使用しており、HTTPS(Hypertext Transfer Protocol Secure)を使用するには設定を変更する必要があります。
![](/content/dam/trendmicro/global/ja/research/22/b/supply-chain-attack-on-azure-devops-server-2020/image02b.jpg)
■ HTTPを使用するAzure DevOps Serverに対する攻撃シナリオ
このセクションでは、HTTPSを使用するよう構成されておらず通信チャネルがHTTPのままになっている場合に、不正な実行者が行う可能性のある攻撃シナリオについて説明します。なお、この攻撃を成功させるためには攻撃者がすでにネットワーク内にいる必要があり、それ自体がリスクであることに注意してください。また、この攻撃シナリオには、サーバとエージェントの間のルータなど、管理が及ばない場所にある感染済みデバイスも含まれます。
まず、エージェントの登録について説明します。エージェント上で構成スクリプトが実行されると(これは1回だけ行われます)、スクリプトがサーバへの接続を開始します。続いて、サーバがMicrosoft NTLM(New Technology LAN Manager)プロトコルを使用して認証を要求します。
![](/content/dam/trendmicro/global/en/research/21/d/https-over-http-a-supply-chain-attack-on-azure-devops-server-2020-/Figure%203_A%20Supply%20Chain%20Attack%20on%20Azure%20DevOps%20Server%202020.png)
図3:Azureパイプラインエージェントの初期構成画面
エージェントはRSA公開鍵と秘密鍵のペアを新たに生成し、公開鍵をエージェントのほかのメタデータとあわせてサーバに送信します。サーバはそれを受信した後、データベースに格納します。このように、安全でないチャネルを使用している場合でもセキュリティ確保の試みがなされていることがわかります。しかしサーバは、エージェントがサーバからの応答を検証できるようにするための鍵ペアを生成していません。これが後々重要な意味を持つことになります。
![](/content/dam/trendmicro/global/en/research/21/d/https-over-http-a-supply-chain-attack-on-azure-devops-server-2020-/Figure%204_A%20Supply%20Chain%20Attack%20on%20Azure%20DevOps%20Server%202020.png)
図4:エージェントの構成時に送信された公開鍵
エージェントのサービスはこの後も引き続き実行する必要があり、これはあらかじめ提供されている実行スクリプトによって行われます。エージェントは構成済みの設定を使用して、アクティブに保たれた一連のHTTP接続を介してサーバに接続し、サーバからのジョブ定義の応答を待ちます。
エージェントがサーバに接続するとセッションが確立され、その際にサーバがAES鍵を生成しますが、この鍵はデフォルトではエージェントの公開鍵で暗号化されます。つまり、暗号化されたメッセージの内容はエージェントだけが復号できます。このメッセージにはビルド定義が含まれています。一見これは防御の堅いセキュリティのように見えるかもしれませんが、セッション開始応答に含まれている「encrypted」プロパティの存在を注目しておかなければなりません。
![](/content/dam/trendmicro/global/en/research/21/d/https-over-http-a-supply-chain-attack-on-azure-devops-server-2020-/Figure%205_A%20Supply%20Chain%20Attack%20on%20Azure%20DevOps%20Server%202020.png)
図5:セッション開始応答に含まれている「encrypted」プロパティ
このプロパティはサーバが生成したAES鍵に関連しています。また、エージェントのバイナリを詳細に解析したところ、暗号化されていないAES鍵をエージェントに送信できることがわかりました。
![](/content/dam/trendmicro/global/en/research/21/d/https-over-http-a-supply-chain-attack-on-azure-devops-server-2020-/Figure%206_A%20Supply%20Chain%20Attack%20on%20Azure%20DevOps%20Server%202020.png)
図6:暗号化されていない鍵の使用を許可している復号ルーチン
このAES鍵はその後、RCEコマンドを含むジョブ仕様の暗号化に使用されます。
■ サプライチェーン攻撃
上述の解析結果を受けて、攻撃者が同じネットワークセグメントにいる場合、またはサーバとエージェントをつなぐ経路上のネットワークデバイスにアクセスできる場合に、エージェントに対してRCE攻撃を行うことが可能かどうかを検証しました。
その結果、サプライチェーン攻撃のシナリオとして以下の手順が成り立ち得ることがわかりました。
- ARP(Address Resolution Protocol)スプーフィングの実施。これは、不正な実行者がローカルエリアネットワーク上で偽装したARPメッセージを送信する攻撃の一種であり、不正な実行者のMACアドレスとサーバのIPアドレスを関連付ける目的で行われます。これにより、不正な実行者が通信を傍受して正規のサーバになりすませるようになります。
- エージェントの要求に対するサーバ応答の模倣。これにより、エージェントに任意のコマンドを実行させます。
上記の手順を実行したところ、Azure DevOps Serverのエージェントに対する攻撃が成功し、リバースシェルを生成することができました。
![](/content/dam/trendmicro/global/en/research/21/d/https-over-http-a-supply-chain-attack-on-azure-devops-server-2020-/Figure%207_A%20Supply%20Chain%20Attack%20on%20Azure%20DevOps%20Server%202020.png)
図7:Azure DevOps Serverのエージェントに対する攻撃の成功例
■ 何が攻撃を可能にしているのか
以下のプラットフォーム設計上の特徴により、システムに対してサプライチェーン攻撃が行われる余地が生まれています。
- エージェントは、受信した応答が正規のサーバからのものかどうかを検証しません。
- ジョブ仕様の暗号化に使用するAES鍵は、「encrypted」プロパティを「false」にすることでカスタマイズしたAES鍵に置き換え可能です。これにより、暗号化されていないカスタムバージョンのAES鍵をエージェントに使用させることができます。なお、このような機能がなかったとしても、攻撃者はエージェントの構成時に送信される公開鍵を盗聴し、その鍵を使用して攻撃者自身のAES鍵を暗号化できます。
- TLSはデフォルトでは構成されません。ユーザが手動で構成する必要があります。
■ サプライチェーン攻撃が成功した場合の影響と対策
通常、ビルドエージェントはソフトウェアのソースコードを実行ファイル形式に変換するために使用されます。そのため、構成が不適切なAzure DevOps Serverに対する攻撃が成功した場合の影響は、SolarWinds社のサプライチェーンへの侵害事例と同様であると考えるべきです。つまり、不正な実行者に対して、標的となった組織のネットワークへの自由なアクセスを与えてしまうということです。
また、攻撃者はSolarWinds社への攻撃でSunburstバックドアを利用していたように、ビルド環境にバックドアを埋め込む可能性があります。これにより、攻撃者がビルド工程そのものに介入できるようになります。さらに、攻撃が成功した場合、攻撃者はビルドの成果物にもアクセスできる可能性があります。通常、この成果物にはソースコードや実行ファイルが含まれています。
このような攻撃シナリオを軽減するためには、ユーザはデフォルト設定に頼らずにTLSを使用することを肝に銘じておく必要があります。
この推奨事項は、今回の攻撃シナリオをMicrosoft社に報告した際に同社から寄せられた以下の助言にも表れています。
「テストと再現の結果から、この問題はHTTPSではなくHTTPで通信を行うことに依拠していると思われます。HTTPは選択肢の1つですが、既知の脆弱性が内在しているため、ネットワーク抽象化レイヤやその他の予防的/制限的セキュリティ対策で保護されたビルド環境での使用が意図されています。ほとんどのお客さまのユースケースにおいては、こちらの指針に沿ってビルドエージェントや環境をデプロイするといったベストプラクティスの実践をお勧めしています」
参考記事:
- 「HTTPS over HTTP: A Supply Chain Attack on Azure DevOps Server 202」
by Trend Micro