Bitbucket に開いた穴: CI / CD パイプラインからシークレットが漏れる理由
Mandiant
Written by: Mark Swindle
※この投稿は米国時間 2024 年 5 月 22 日に、Google Cloud blog に投稿されたものの抄訳です。
最近の Amazon Web Services(AWS)シークレットの漏洩について調査していたところ、Mandiant は Atlassian のコード リポジトリ ツールである Bitbucket からクライアント固有のシークレットが漏洩し、脅威アクターが AWS への不正アクセスに利用しているシナリオを特定しました。このブログ投稿では、Bitbucket の保護された変数がどのようにパイプラインで漏洩し、ユーザーをセキュリティ侵害にさらす可能性があるかについてご説明します。
背景
Bitbucket は、Atlassian が提供するコード ホスティング プラットフォームで、Bitbucket Pipelines と呼ばれる継続的インテグレーションと継続的デリバリー / デプロイ(CI / CD)サービスが組み込まれています。Bitbucket Pipelines は、AWS でリソースをデプロイおよび保守するなど、CI / CD のユースケースを実行するために使用されます。Bitbucket には「保護された変数」と呼ばれる管理機能があり、管理者は AWS キーなどの CI / CD シークレットを Bitbucket に直接保存し、コード ライブラリから簡単に参照できるようになっています。
CI / CD シークレット: CI / CD シークレットは、CI / CD パイプライン内で認証と認可のバックボーンとして機能します。CI / CD シークレットは、パイプラインが AWS などのプラットフォームとやり取りするために必要な認証情報を提供し、パイプラインがそのタスクに対して適切な権限を持っていることを保証します。シークレットはたいてい非常に強力であり、環境への直接のアクセスが維持されるため、攻撃者の格好のターゲットとなっています。デベロッパーにとっての使いやすさとのバランスを取りながらシークレットの機密性を保持することは、CI / CD パイプラインの保護における終わりのない闘いと言えます。
Bitbucket の保護された変数: Bitbucket は、デベロッパーがコードを書く際にすぐに参照できるよう、変数を保存する手段を提供しています。さらに、機密性の高いデータのために、変数を「保護された変数」として宣言するオプションを用意しています。保護された変数は、管理者が値を設定すると、平文として読めなくなるように設計されています。この構造により、デベロッパーは Bitbucket のどこにも値を漏洩させることなく、シークレット変数を素早く呼び出すことができます。ただし…
Bitbucket からシークレットを平文としてエクスポートする
CI / CD パイプラインは、家の配管と同じように設計されています。安心して使える水道水を提供するために、パイプ、バルブ、調整弁が一体となって動作します。CI / CD パイプラインは、特定のタスクの達成を目的とする、イベントの複雑なオーケストレーションです。これを実現するため、こうしたパイプラインは大量のデータを完全に自律的にパッケージ化してデプロイすることに優れています。これは、デベロッパーにとっては作業を自動化する無限の可能性となりますが、セキュリティ専門家にとっては不安や悩みの種の原因となります。シークレットがハードコードされた 1 行のコードが本番環境に忍び込むかもしれませんし、デベロッパーが誤って自分のマシンにシークレットをローカル保存してしまうかもしれません。あるいは、最近の調査で見られたように、AWS 環境のシークレットが含まれた Bitbucket のアーティファクト オブジェクトが、S3 バケットや会社のウェブサイトなど、一般利用できる場所に公開される可能性もあります。
Bitbucket の保護された変数は、デベロッパーがすぐに参照できるよう、シークレットを Bitbucket 内にローカルに保存する便利な手段です。ただし、これらの変数には、アーティファクト オブジェクトを通じて平文で漏洩してしまう可能性があるという、厄介な特性があります。保護されているかどうかを問わず、artifacts: コマンドを使って Bitbucket の変数をアーティファクト オブジェクトにコピーすると、その変数の値を平文で表示した .txt ファイルが生成されます。
Mandiant が確認した事例では、開発チームがトラブルシューティングのためにウェブ アプリケーションのソースコードで Bitbucket のアーティファクトを使用していたところ、知らないうちにそれらのアーティファクトにシークレット鍵の平文値が含まれていました。その結果、シークレット鍵が、置かれていた公共のインターネット上に漏洩し、攻撃者の不正アクセスに利用されました。
AWS キーのような保護された変数が平文で .txt ファイルにコピーされると、シークレットが漏洩します。シークレットがどこに流出し、攻撃者がいつ見つけるかはパイプライン次第です。
シークレットの漏洩を再現する
Bitbucket 環境でシークレットの漏洩を再現する手順は、以下のとおりです。重要な注意点があります。このガイドで詳しく説明しているコマンドは可能性の一つにすぎません。Bitbucket のアーティファクトに保護された変数をエクスポートする方法は他にもいくつかあります。管理者とデベロッパーは、bitbucket-pipelines.yml ファイルやリポジトリ内の他のファイルにあるアーティファクト オブジェクトへの参照をよく確認する必要があります。
Bitbucket で保護された変数を設定する
「保護された変数」に設定されていれば、リポジトリ レベルで行ってもワークスペース レベルで行ってもかまいません。


bitbucket-pipelines.yml ファイルを更新して環境アーティファクトを作成する
以下のコード行は、コマンド printenv を実行して、すべての環境変数を Bitbucket から environment_variables.txt という .txt ファイルにコピーします。デベロッパーは正当な開発目的のためにさまざまな変数を確認する必要があるため、この操作は開発でトラブルシューティングを行う際によく行われます。.txt ファイルが作成されると、コードはそれを Bitbucket のアーティファクト オブジェクトに渡し、必要に応じてパイプラインの将来のステージで使用できるようにします。


パイプラインの実行履歴に移動してアーティファクトをダウンロードする


アーティファクトを開いて保護された変数を探す
.txt ファイルをエクスポートすると、Bitbucket 環境のすべての変数の中からシークレットを平文で読み取ることができます。この手順には注意点があります。ここで追加の手順として、.tar ファイルのコンポーネントの抽出が必要となる場合があります。この場合、お好きなデータ抽出ツールを使って .tar ファイルを抽出してください。


パイプラインに沿ってシークレットが流出する
シークレットが environment_variables.txt ファイルに出力されると、パイプラインを通じて Bitbucket から流出し、漏洩した状態になります。開発中のミス、悪意、偶発的な開示のいずれかが重なると、シークレットの漏洩と脅威アクターによる不正使用につながる可能性があります。
推奨事項
Bitbucket Pipelines は、コードの保存、共同編集、デプロイを行うための優れたプラットフォームです。ただし、Bitbucket は専用のシークレット マネージャーではないため、Bitbucket に直接シークレットを保存すると、シークレットが漏洩する可能性があります。Bitbucket Pipelines を使用する際は、以下のようにしてシークレットを安全に保護してください。
-
専用のシークレット マネージャーにシークレットを保存し、Bitbucket リポジトリに保存したコードでその変数を参照する
-
Bitbucket のアーティファクト オブジェクトを精査し、シークレットが平文ファイルとして漏洩していないことを確認する
-
パイプラインのライフサイクル全体にコードスキャンを導入し、本番環境にデプロイする前に、コードに保存されたシークレットを検出する
まとめ
この投稿は、Bitbucket を非難するものではありません。何も問題なさそうに見える行為が、いかに深刻な問題に発展しうるかを示したケーススタディです。私たちが「漏洩」という言葉を使うのには、明確な理由があります。たったひとつのキー操作、コード、構成ミスで、パイプラインから世界へと、一見追跡できそうにないシークレットの水滴がゆっくりと漏れ出していくのです。
-Mandiant、執筆者: Mark Swindle