HN 日本語サマリー

← 一覧へ戻る
セキュリティ

BasetenのプロダクションGitHubへの管理権限を25分で取得

We got admin access to Baseten's production GitHub in 25 minutes (strix.ai)

306 pointsby bearsyankees173 コメント

要約

セキュリティ企業Strixは、自身が利用を検討していたAIプラットフォームBasetenのセキュリティ評価を実施したところ、25分で同社のプロダクションGitHubリポジトリに対する管理権限を持つトークンを発見しました。このトークンは、公開されたDockerイメージのビルド履歴に含まれており、主要なソースコードリポジトリやインフラストラクチャを管理するリポジトリへの管理者権限を有していました。Baseten側は迅速に対応し、問題は修正されました。

全文翻訳

Basetenのインファレンスを使おうとしたら、BasetenのGitHubへの管理者アクセス権を取得してしまった

私たちは、自社および顧客のデータをBasetenに委ねようとしていました。安全を期すため、Strixを使ってまず彼らが安全であることを確認しました。約25分後、Basetenの内部リポジトリに対するリポジトリレベルの管理者権限を持つ、稼働中のGitHubトークンを入手しました。

私たちはStrixという自律型ハッキングエージェントを開発しています。もちろん、そのためには(安価で高速な)インファレンスが必要です。私たちは選択肢を検討しており、Basetenはその有力な候補の一つでした。素晴らしい製品であり、彼らは130億ドルの評価を受け、多くの大手企業が彼らに依存しています。

しかし…私たちはセキュリティ企業です。第三者にデータ、モデル、コードを提供する前に、私たちはそれをスキャンします。そのサービスに依存し始める前に問題を発見し、修正を支援できる方がはるかに良いと考えています(私たちはほとんどすべてのベンダーに対してこれを行っており、深刻な問題を発見する割合は高いです)。

そこで…私たちはStrixを*.baseten.coに向け、認証情報やソースコードなしで実行させました。

結果として、basetenbot用の有効なGitHub個人アクセストークンが見つかりました。そのトークンは、Basetenのメイン製品リポジトリ、クラスターを駆動するGitOpsリポジトリ、およびHomebrew tapに対して管理者およびプッシュアクセスを持ち、さらに顧客ごとの特定のリポジトリを含む他のプライベートリポジトリに対しても読み取り/書き込みアクセス権を持っていました。

検出されたイメージのビルドは2023年3月の日付でしたが、2026年7月に発見したとき、トークンはまだ有効でした。

しかし、詳細に入る前に、Basetenのセキュリティチームに称賛を送りたいと思います。彼らはこの問題をクリティカルと確認し、レジストリプロジェクトをロックダウンし、翌日の午後にはトークンをローテーションしました。彼らはプロフェッショナルで、この状況(多くの場合そうではない)に非常に迅速に対応しました。

Strixはどのようにしてそれを見つけたのか

Strixは、優れたペネトレーションテストと同様に、偵察から始まります。多くの場合、インフラストラクチャ上の最も深刻な脆弱性は、忘れていたサブドメイン上のサービスにある可能性があります(だからこそ、コードアクセスを伴うテストと並行してブラックボックステストを常に推奨しています!)。そのため、Strixはホストを列挙し、証明書ログを調べ、完全なサーフェスをマッピングしました。最終的に、gcp-us-east4-zlw.registry.baseten.coにあるHarborレジストリを発見しました。

Harborはコンテナイメージを格納し、リポジトリをプロジェクトにグループ化します。これらのプロジェクトのうちの1つは公開されていました。トークンや認証なしで、Strixはリポジトリをリストし、匿名プルトークンを取得し、実際のイメージマニフェストとブロブをダウンロードできました。これにはbaseten/baseten-appという名前のイメージも含まれていました。

この時点で、公開されたレジストリを報告して次に進むのは簡単です。しかし、企業は意図的にイメージを公開することがあり、Strixは偽陽性を報告したくありません。重要なのは、公開されたイメージがどのような影響を与えるかということです。

Strixはイメージをプルして、中身を確認することにしました。以下は、Strixでのその部分の実行ログです(はい、エージェント自身の記述はAIのように聞こえます。当然の理由です):

Harbor Exposure Impact Review

Thinking

もしこれらのHarborプロジェクトが公開されることを意図していないのであれば、これはメタデータのノイズではなく、実際の露出です。重要なのは連鎖です:公開プロジェクトの列挙、アーティファクトメタデータの読み取り、repository:baseten/baseten-app:pullにスコープされた匿名service/tokenの発行、マニフェストのプル、そして署名付きストレージリダイレクトを介したブロブの取得。これは、実際の匿名プルアクセスを証明します。トリアージ担当者に真剣に受け取ってもらう方法は、プルされたイメージから1つのこと、つまり専有コード、内部バイナリ、ハードコードされた認証情報、または内部ホスト名を証明することです。

最初に見つかった有望なものは、baseten/baseten-app内のAWSキーのペアでした。Strixは読み取り専用のsts:GetCallerIdentity呼び出しを試みましたが、これは認証情報がどのアカウントに属するかを教えてくれます。応答はInvalidClientTokenIdでした。

そのキーは無効だったので、Strixは探し続けました。

そして、実際に機能するトークン

レイヤーをプルし、TruffleHog(オープンソースセキュリティの友人たちに感謝!)を実行し、イメージ設定を直接検査しました。そして、そこにありました:古典的なGitHub個人アクセストークンが、history[].created_by内にありました。

私はDockerランタイムの専門家ではありませんが、幸いStrixは(ほぼすべての人間の知識を利用できるため)専門家です。そのため、そのフィールドがビルドステップがどのように作成されたかを記録することを知っていました。この場合、それはGITHUB_TOKENの値が直接展開されたRUNコマンドを含んでいました。

StrixはGitHubに対して読み取り専用のGET /userリクエストにそのトークンを使用しました… そして、うまくいきました。200応答で、アカウント名はbasetenbotでした。

[画像: Dockerビルド履歴内のトークン、続いてGitHubがそれをbasetenbotとして識別。認証情報は編集済み。]

Dockerビルド履歴内のトークン、続いてGitHubがそれをbasetenbotとして識別。認証情報は編集済み。フルサイズで画像を開く。

トークンが見つかった場所をよく見てください。私が学んだように、Dockerイメージにはファイルシステムレイヤーがありますが、イメージとそのビルド履歴に関する情報を含む設定も含まれています。その設定は、イメージと一緒にダウンロード可能です。ビルド履歴にトークンの別のコピーが残っている場合、認証情報ファイルをクリーンアップしても意味がありません。

そして、このトークンは3年以上経ってもまだ有効でした。

さて、basetenbotは何ができるのか?

[[画像: Job's not finished.]]

稼働中のトークンは興味深いですが、もちろん権限が重要です。このトークンは権限がゼロで、したがって影響もゼロである可能性があります。そのため、Strixはアカウントとその組織メンバーシップを確認しました。GitHubはX-OAuth-Scopes: repoを返し、アカウントはbasetenlabsに属していました。

[画像: GitHubはbasetenbotに対してrepoスコープを返し、basetenlabsをその組織としてリストしました。]

GitHubはbasetenbotに対してrepoスコープを返し、basetenlabsをその組織としてリストしました。フルサイズで画像を開く。

次に、個々のリポジトリの権限を確認しました。これも読み取り専用リクエストを使用しました:

リポジトリアクセス
basetenlabs/b***admin: true, push: true
basetenlabs/f***admin: true, push: true
basetenlabs/h***admin: true, push: true
basetenlabs/r***プライベート、読み取り/書き込み
basetenlabs/b***プライベート、読み取り/書き込み
basetenlabs/t***プライベート、読み取り/書き込み
basetenlabs/b***プライベート、読み取り/書き込み

これは、公開ダウンロード可能なイメージに残しておくには、信じられないほどの量のアクセス権です。

その時点で、報告するのに十分な情報があり、これが偽陽性ではないと確信できました。顧客リポジトリをクローンしたり、何かをプッシュしたり、設定を変更したりしませんでした。そこで作業を停止し、すぐに開示メールを作成しました。

トークンはどのようにしてそこにあったのか?

ビルド履歴にはタイムスタンプが付いていました。トークンを含むステップは2023年3月3日に実行されました。これは古いビルド認証情報であり、2026年7月にテストしたとき、まだそのすべてのアクセス権を持っていました。

根本的な間違いは非常に一般的です。ビルドがGitHubからプライベート依存関係を取得する必要があったため、誰かがビルド引数としてトークンを渡しました。関連するパターンは次のようでした:

1ARG GITHUB_TOKEN
2RUN GITHUB_TOKEN=${GITHUB_TOKEN} bash -c '\
3if [ [ "${GITHUB_TOKEN}" != "" ] ]; then \
4git config --global --add \
5url."https://${GITHUB_TOKEN}@github.com/".insteadOf "git@github.com:"; \
6fi'

誰かがこれを書くことになる経緯は理解できます。プライベート依存関係が必要で、トークンを渡し、Gitが認証し、ビルドが機能します。しかし、Dockerはそのビルド引数をイメージのメタデータと履歴に記録できます。この場合、実際のトークン値が記録されました。Dockerはこれについて明示的に警告しています。

このパターンには第二の問題もあります:git config --globalは認証済みURLをGitの設定ファイルに書き込みます。トークンがビルドにどのように渡されるかを変えても、それをイメージに保存しないようにする必要があります。

修正策は、BuildKitのシークレットマウントと、認証情報を永続化しない一時的な認証を使用することです。そして、イメージのレイヤーとその履歴の両方を検査します。そして、古いトークンを失効させてください!Dockerfileを変更しても、既にダウンロードされたイメージには影響しません。

Strixが自律的に行ったこと

Basetenは応答性の高いセキュリティチームを持っており、既にAIセキュリティツールを使用しています。それでも、2023年のビルドからのこのトークンは、私たちが発見したとき、彼らの製品およびデプロイメントリポジトリに対する管理者アクセス権を持っていました。

アプリケーションとソースリポジトリに焦点を当て、古いコンテナイメージを忘れてしまうのは簡単です。イメージのファイルをスキャンしても、ビルド履歴を確認する必要があります。

このスキャンで気に入っているのは、Strixが見つけた発見を追跡し続けたことです。レジストリを見つけ、実際にイメージをプルできるか確認し、認証情報をテストして無効であることを発見し、ビルド履歴で別の認証情報を見つけ、それが何にアクセスできるかを確認しました。

Harborを探すように指示したり、トークンについての手がかりを与えたりしていませんでした。すべてを約25分で自律的に実行しました。

これが私たちがStrixを構築している理由です。AIによる攻撃はここ数週間で非常に恐ろしいものになっており、自分自身を守る唯一の方法は、悪者たちが見つける前に、これらの問題(問題は常に存在するでしょう)を常に見つけ出すために自分自身をハッキングし続けることだと信じています。

開示

Basetenはこの件にうまく対応しました。タイムラインは以下の通りです:

  • 7月13日 23:10: 稼働中のbasetenbotトークン、公開されているHarborプロジェクト、およびリポジトリの権限について報告しました。
  • 7月14日 午前: BasetenはHarborプロジェクトをプライベートにしました。トークン自体がまだ有効であることを指摘しました。
  • 7月14日 16:34: BasetenセキュリティのAnton氏が、問題をクリティカルと確認し、Harborプロジェクトをプライベートにし、トークンをローテーションしたと述べました。また、プルしたイメージを安全に削除するように求めました。
  • 7月14日 17:05: 削除を確認し、同じスキャンからの2つの低リスクの発見事項を送信しました。
  • 7月17日: Basetenは残りの発見事項をクローズしました。
  • 9月: Basetenに、この発見事項を公に開示する計画があることを伝え、この投稿の下書きを送りました。

彼らはまた、このクリティカルなバグを見つけてくれたことへの感謝として、Tシャツとスウェットシャツを送ってくれました。

古いイメージを確認してください

コンテナを実行していてGitHubを使用している場合、自身のインフラストラクチャでこれをチェックする価値があります:

  1. ログインなしで何がプルできるかを確認してください。古いタグや、しばらく考えていなかったプロジェクトも含まれます。
  2. docker history --no-truncでビルド履歴を読むか、設定ブロブのhistory[].created_byフィールドを検査してください。レイヤーも確認してください。
  3. ビルド引数からシークレットを抽出します。シークレットマウントを使用し、それらのシークレットを使用するコマンドがイメージに書き戻さないようにしてください。
  4. ビルドトークンが実際に何ができるかを確認してください。依存関係を取得するには、その依存関係への読み取りアクセスが必要です。そのトークンに製品およびデプロイメントリポジトリの管理者権限を与えることは、漏洩をさらに悪化させます。権限を制限し、有効期限を設定してください。

そして、Strixのようなものを自身のシステムに対して実行してください。このスキャン全体は、インファレンスプロバイダーを使用したいと思ったことから始まりました。ドメインを提供したところ、Basetenが翌朝対応できるクリティカルな脆弱性が返ってきました。

AI攻撃者はこれらの同じパスをたどることができます。エージェントが25分で古いイメージから稼働中の管理者トークンを見つけられるなら、あなたのエージェントにそれを見つけさせたいはずです。