ポリシーリスクを可視化。自然な言葉でポリシーに関する疑問を解決します。 デモを申し込む →

Published:

AWS ExternalID とクロスアカウント AssumeRole アクセスを保護する高度な手法

by FireMon

先月、Praetorian Security の Kesten Broughton 氏が、Amazon が推奨するクロスアカウント接続手法を利用するサードパーティ製クラウドセキュリティ製品に関する優れた調査を公開しました。多数の主要ベンダーで発見された AWS IAM Assume Role の脆弱性です。冒頭の段落が、この調査の内容を的確に要約しています。

クロスアカウント信頼に関する本シリーズの第1回となるこのブログでは、90 社のベンダーを対象とした調査結果を示します。そのうち 37% は、混乱した代理人攻撃から保護するための ExternalId を正しく実装していませんでした。さらに 15% のベンダーは、UI 上では AWS アカウント統合を正しく実装していたものの、バックエンドで ExternalId パラメータが適切に検証されておらず、これらのサイトも脆弱な状態でした。最後に、AWS のクロスアカウント assume role 信頼によって新たに生じる攻撃対象領域について論じます。結論として、ベンダーおよび顧客は、ロール信頼がマルチテナント型 SaaS ソリューションにとって最適な信頼メカニズムであるかどうかを批判的に検討すべきです。

この調査を読んだときの私の第一の反応は「なぜこれほど不適切な判断をするのか」というものでした。しかし実際のところ、「クラウドセキュリティの専門家」という概念自体が比較的新しく、AWS は混乱した代理人問題についてある程度きちんと説明しているものの、製品が顧客に接するまで実際には意識しないような実装上の課題までは網羅していません。AssumeRole を用いたクロスアカウント接続には明快なエンジニアリング上の解決策がありますが、適切な脅威モデリングを行わなければ、Kesten 氏の調査に記録されているような誤りを犯すことは極めて容易です。

当社 DisruptOps では、初期段階の脅威モデリングに基づいていくつかの賢明な判断を下しており、そのおかげで安全な状態を維持できています。とはいえ、この調査から得られた知見もあり、さらなる強化を進めています。加えて、この問題の大部分を解消しつつ、顧客環境への直接の書き込みアクセスを必要とせずに大規模な自動化を実現するスカンクワークスプロジェクトも進行中です。

ただし、この投稿には一点だけ大きく意見を異にする部分があります。静的な認証情報とボールティングを使用するという推奨よりも、私は自動ローテーションされる認証情報を常に選びます。他のクラウドプロバイダーでは依然として静的な認証情報を使わざるを得ませんが、当社は自社環境の「どこにも」静的な認証情報を置かない方法を常に模索しています。

問題点

今日、さまざまな種類のアプリケーションがクラウド API に直接接続する必要があります。それは S3 バケットへのアクセスのような単純なものから、完全に自動化されたクラウド検知・対応プラットフォーム(あくまで一例としてですが)のような複雑なものまで多岐にわたります。これらのリクエストには何らかの認証情報が必要であり、それは静的なもの(ユーザー名とパスワード、あるいは IAM アクセスキーとシークレットキーなど)か、動的なもののいずれかです。動的な認証情報には、トークンなど時間制限のある一時的な属性が含まれます。

クラウド管理プレーンへの直接アクセスを許す静的なアプリケーション認証情報は……好ましくありません。ユーザーについては MFA で解決できますが、それでは先ほどの(決して仮想ではない)クラウド検知・対応プラットフォームのような自動化アプリケーションには対応できません。少し前に Amazon Web Services は、IAM ロールという概念でこの問題に取り組みました。AWS におけるロールとは、本質的には権限のコンテナであり、2 つのポリシーを持ちます。すなわち、そのコンテナが何をできるかと、誰(または何)がそのロールを引き受けられるかです。ロールはセッションベースであるため、認可されたエンティティがロールを引き受けると、セッションの有効期間(1 時間から 24 時間)にわたって使用できる一組の認証情報(アクセスキー、シークレットキー、セッショントークン)が得られます。

AWS のロールは、外部 SAML 接続(ユーザー向け)、内部の「信頼された」接続(他の AWS アカウントから)、または AWS サービス(EC2 インスタンスや Lambda 関数など)を通じて引き受けることができます。これにより、インスタンス上でコードを実行しつつ、そのインスタンスには静的な認証情報を一切保存しない、といった優れた構成が可能になります。これは多くの手間を実際に取り除いてくれます。

自社が管理していないアカウントからの接続を許可する場合は事情が少し異なります。特にそのアカウントが複数の顧客にサービスを提供するプラットフォームである場合はなおさらです。そうしたプラットフォーム(そう、当社のような)は、数百から数千に及ぶ他の AWS アカウントへのアクセスを必要とします。攻撃者がプラットフォームを騙して誤ったアカウントで何らかの操作を行わせる、たとえば現在のユーザーが所有していないアカウントに対して構成評価を実行させることができたらどうなるか想像してみてください。これは混乱した代理人問題の簡略版です。代理人は複数のアカウントから信頼されており、ユーザーはその代理人を騙して、本来決して触れるべきではないアカウントへのアクセスを得るのです。

これに対する最も現実的な悪用手法は、プラットフォームがユーザーに、自分が管理していないアカウントの ID を入力してプロファイルに追加させ、プラットフォームに与えられた信頼を悪用できてしまう場合です。

AWS には、これを防ぐための仕組みとして AWS ExternalIDがあります。これは、プラットフォーム提供者と顧客が帯域外でやり取りする任意の共有シークレットです。この ID は、顧客アカウントのロールを引き受けるリクエストの際に渡される属性であり、当該アカウントのロール信頼ポリシーには、その共有シークレットが正しいかどうかを検証する条件が設定されます。適切に実装されていれば、攻撃者は顧客アカウントの共有シークレットを設定することも知ることもできないため、自分が管理していないアカウントを代理人に追加することはできません。

ただし……

話の行き着く先はお察しのとおりです。Praetorian は、デフォルトの AWS ExternalId を使用している、あるいはアカウント全体で一意でない ExternalId 値を顧客に設定させているプロバイダーが多数存在することを特定しました。また、顧客がロール信頼ポリシーで External ID を実際に強制しているかを検証していない製品も見つかりました。Praetorian は、クロスアカウントロールのセキュリティが不十分なために混乱した代理人攻撃が可能となる、実際に悪用可能なプラットフォームを発見したのです。

クロスアカウント接続の堅牢化

これらはすべて DisruptOps における脅威モデリングの一環として検討済みであり、当社は良好な状態にあります。とはいえ、改善につながるアイデアをいくつか新たに得ることもできました。ここでは、Praetorian が特定した各課題を順に見ていき、セキュリティ強化のための最善の選択肢を検討します。

  • AWS ExternalID がデフォルト設定のまま: 当社ではランダムな ExternalID を使用しています。
  • AWS ExternalID が複数の顧客アカウントで共有されている:当社では、顧客単位ではなくアカウント単位でランダムな ExternalID を使用しています。
  • AWS ExternalID が列挙可能または推測可能: 当社は完全にランダムで長い AWS ExternalID を使用しています。API のレート制限があるため、PRNG の選択については懸念していません(暗号技術に詳しい方向けの補足です)。
  • 顧客が自身で ExternalID を設定でき、重複したり脆弱な ExternalID が使われる可能性がある: 当社は顧客自身による ExternalID の設定をサポートしていません。ただし、この要望を受けたことは確かにあります。他のプロバイダーが問題に陥ったのは、まさにこの点だと考えています。顧客は製品のプロビジョニングを自ら自動化できるようにこの機能を求めますが、これを安全に行うには、ExternalID が長さとランダム性の要件を満たしているかを検証する必要があります。適切な検証を行えば、おそらく安全に実現できるでしょう。
  • 同一の AWS アカウントを複数回プロビジョニングできてしまう: 当社ではこれを許可していません。
  • IAM ロールがプロバイダーアカウント内の単一のエンティティに限定されておらず、アカウント内の任意のロールに許可されている: 本稿では触れていませんが、顧客アカウント内の「ワーカー」ロールへのアクセスを、アカウント内の任意のロールに許可することも、単一のリソースまたはロールに限定して許可することもできます。当社は、クロスアカウントアクセスに使用する特定のロールにアクセスを限定しています。
  • IAM ロール名がすべての顧客アカウントで固定されている: ここでのリスクは、本質的にはユーザー名(ロール名)が推測可能であるという点です。他に非常に根本的な不備がない限り、これはリスクとは考えていません。一例として、攻撃者がロール名を知っていて顧客アカウントへのアクセスを得た場合、自身をロール信頼ポリシーに追加し、その権限を利用できる可能性があります(私はインシデント対応のトレーニングクラスでこれに類する内容を教えています)。これは潜在的なリスクではありますが、当社の評価ではかなり低いものです。攻撃者がそのレベルのアクセスを持っているなら、アカウント内のどのロールでも乗っ取れる可能性が高いからです。
  • プロバイダーが、ExternalID がアクセス条件として設定されていることを検証していない: 当社は、これが適切に設定されることを保証する CloudFormation テンプレートを顧客に提供しています。今後は、それが維持されていることを検証する機能も追加していきます。特に、顧客要件に応えるために CloudFormation 以外のプロビジョニング手段を追加していくにあたって重要となります。

Kesten 氏は、接続の保護にあたって静的な認証情報モデルと、プロバイダー側での適切なボールティングの利用を好んでいるようです。個人的にはこれに同意せず、基本的な予防策を講じるのであれば、AWS のモデルの方が当初からより安全だと考えています。

当社は現在、Praetorian の推奨事項に加えて、次の 2 つの予防策を講じています。

  • CloudFormation で ExternalID をマスクする: 当社は CloudFormation テンプレート内で ExternalID をパラメータとして設定し、NoEcho オプションを有効にしています。これにより、コンソール、コマンドラインツール、API 上で値がマスクされます。IAM の権限は持たないものの CloudFormation を実行する権限を持つ人物への露出リスクを低減できます。
  • CloudFormation テンプレートへのアクセスを対象アカウントのみに制限する: これにより、プロビジョニングの過程で第三者が ExternalID を奪取するリスクを低減できます。

仮に ExternalID が露出したとしても、問題にはならないはずです。プラットフォーム側で、対象アカウントが一度しか登録されないこと、かつランダムな ExternalID でのみ登録されることを保証すべきだからです。攻撃者がロール名と ExternalID を知っていたとしても、その情報を入力できる箇所がプラットフォーム上に存在せず、また AWS 自体がクロスアカウント接続は信頼されたアカウントから発信されることを強制するため、何もできません。これはスプーフィングできるものではありません。

当社の対応方法をご覧いただくことで、ご自身のツール構築にあたっての示唆が得られれば幸いです。アカウント登録とランダムな ExternalID の要件は、AWS Organizations を使用している場合でも推奨します。自組織からのアクセスのみに制限する条件を追加しても、セキュリティレベルの低いアカウントから高いアカウントへの攻撃の余地が残る可能性があるためです。

そして、先ほどの新しいスカンクワークスプロジェクトにもご期待ください。数か月後にはお話しできる見込みで、この種の問題に対する真のゲームチェンジャーとなるものです。

AWS ExternalID を保護する高度な手法 | FireMon