ポリシーリスクを可視化。自然な言葉でポリシーに関する疑問を解決します。 デモを申し込む →
Published:
AWSで攻撃者のキルチェーンを断ち切る: IAMロール
by FireMon
この1年間、クラウドネイティブな手法でクラウド内のセキュリティインシデントに対処するための具体的な助言を求める声が急増しています。組織が本番ワークロードをクラウドへ移行すると、セキュリティ担当者は基本原則が概念的には似ていても実務上はかなり異なることにすぐ気づきます。その中核概念の一つがキルチェーンです。これは攻撃者のプロセスを表すためにLockheed Martinが最初に用いた用語です。いずれかの環を断ち切れば攻撃は成立しなくなるため、多層防御とインシデントレスポンスの能動的な要素を組み合わせる考え方によく合致します。
クラウド環境における攻撃は大きく4つに分類でき、それぞれ異なるキルチェーンを持ちます。
- クラウドプラットフォーム自体への攻撃。 クラウドプロバイダー自体の根本的な侵害(クラウド利用者の手の及ばない領域)を除けば、この種の攻撃は通常クラウドサービスの設定ミスに起因します。S3バケットを公開したままにする、API Gatewayにオーソライザーを設定しない、あるいはAWSの認証情報をGitHub上に露出させる、といったものがこのカテゴリーに該当します。
- クラウド上に顧客が展開したリソースおよびアプリケーションへの攻撃。 これらの従来型の攻撃は、データセンターに対して実行されるものと変わりません。代表的な例としては、Webアプリケーションに対するSQLインジェクションや、誤ったポートをインターネットに開放した脆弱なサーバーが挙げられます。アカウント/サブスクリプション/プロジェクトとVPCまたは仮想ネットワークを用いて影響範囲を限定していれば、データセンターの場合よりも影響はやや限定的になる傾向があります。
- クラウド管理者および開発者への攻撃。 次回ペネトレーションテストを実施する際は、開発者や管理者へのフィッシングを試行させてください。攻撃者にとって、クラウドアプリケーション自体を破るよりも開発者のシステムへアクセスする方がはるかに容易な場合が多いため、これはクラウドへ侵入する最も有効な経路の一つです。この点は今後取り上げますが、まずは「MFAは味方である」という点から始めましょう。
- 複合型攻撃。 本日取り上げるのはこのカテゴリーです。この種の攻撃では、脅威アクターがクラウド上に展開された何らかの対象に侵入し、それを足がかりにクラウド管理プレーンへと横展開します。(開発者への攻撃も複合型と見なす向きもありますが、ここでは別に分類しています。)
経験則として、あらゆる階層における攻撃の成功は権限昇格や横展開によって複合型攻撃に発展しうる、と常に想定しています。そうなった時点で、管理プレーンのセキュリティとインシデントレスポンスが最善の防御となります。
本日は最も一般的な複合型攻撃のプロセスの一つに焦点を当て、キルチェーンを断ち切るための検知的統制と予防的統制の組み合わせを概説します。詳細に入る前に申し上げますが、本稿を複雑な問題の単純化と受け取らないでください。これから述べる内容を大規模環境で管理することは、熟知していても極めて困難です。
今後数週間のうちに、これらの課題に特化した最初のOpsを早期アクセスのお客様へ提供開始し、その後比較的早い段階で本番環境に投入する予定です。
AWSにおける複合型攻撃:IAMロール認証情報の窃取
複合型攻撃では、脅威アクターがより従来型の対象に侵入し、それを足がかりにクラウド管理プレーンへ横展開します。これが起こる主な経路は3つあります。いずれの場合も、攻撃者は静的に保存された認証情報か、一時的なIAMロール認証情報のいずれかを窃取します。これらについては後ほど説明します。
- インスタンスまたはコンテナの直接的な侵害。例えば、ポート22を開放したままにし、攻撃者が侵入するか、その他の方法でシェルアクセスを取得する場合です。
- サーバーサイドリクエストフォージェリ(SSRF)。攻撃者は(多くの場合)Webサーバー/サービスの脆弱性を悪用し、シェルアクセスを取得せずにコマンドを実行します。
- Lambda関数の侵害。Lambdaではシェルを取得できませんが、コード実行の脆弱性の影響は受け、アプリケーションに欠陥があれば任意コード実行に至ることもあります。その具体的な影響はSSRFに類似します。
いずれの場合も、攻撃者の目的はAWS管理プレーンへの認証情報を取得し、既存の権限を利用するか権限を昇格させることです。権限昇格については今後の記事で取り上げることとし、ここではその認証情報が何であり、その悪用をどう防ぐかに焦点を当てます。
静的な認証情報については多くの方が理解しているでしょう。AWSではアクセスキーとシークレットキーがこれに当たります。ユーザー名とパスワードのようなものですが、AWSのAPI呼び出しに使用されます。現行バージョンでは、これらのAPI呼び出し時のHTTPリクエスト署名にSignature 4と呼ばれる暗号処理が用いられます。これらはユーザー名とパスワードとまったく同様に扱うべきであり、インスタンスやLambdaなどのクラウドリソース内に保存してはなりません。
IAMロールはAWSを使い始めた当初は扱いが難しく、優れていると同時に恐ろしくもあります。AWSにおけるIAMロールは、実質的にセッションで使用する権限のコンテナです。IAMロールが優れているのは、それ自体は認証情報ではないという点です。ロールを引き受けると、AWSが時間制限付きセッション用の認証情報一式を提供します。ロールは「AWS内部限定」の仕組みです。AWS内のリソース(インスタンスやLambda関数など)に割り当てることができ、そのリソースは静的に保存された認証情報なしでAPI呼び出しを行えるようになります。 ロールはフェデレーテッドアイデンティティ接続、インスタンス、Lambda関数、およびAWS内のその他すべてのサービスで使用します。アクセスキーが必要になるのは実質的にAWSアカウント内にユーザーを作成する場合のみで、それ以外はすべてロールを使用します。
ロールには4種類の権限が関連付けられます。
- そのロールがAWS内で何を実行できるか。これはロールにアタッチするアクセス許可ポリシーそのものです。
- 誰が、または何がそのロールを使用できるか(信頼ポリシー)。ロールを作成しただけでは誰でも使えるわけではなく、このポリシーによって、例えばAWSインスタンスや特定のLambda関数へとアクセスが制限されます。
- ロールの適用範囲を制限するアクセス許可境界。これはやや複雑で本日の議論には関係しないため、後日取り上げます。
- セッションのためにロールを引き受ける際、そのセッションで使用する既存権限のサブセットを指定することもできます。これは最小権限の観点で優れた機能ですが、本日の議論には直接関係しません。
仕組みは、実際の流れを追って説明する方が分かりやすいでしょう。S3バケットまたはDynamoデータベースへのアクセスを必要とするアプリケーションがあるとします。インスタンス用のIAMロールを作成し、EC2サービスがそのロールを使用できるよう信頼ポリシーを設定します。次にインスタンスを起動し、ロールを割り当てます。AWSはインスタンスを実行し、そのインスタンスにロールを引き受けさせます。ロールを引き受けるとセッションが開始され、アクセスキー、シークレットキー、セッショントークンが割り当てられます。AWSはその後1〜6時間ごとにこれらの認証情報をローテーションし、インスタンスはアクセス許可ポリシーで認可されたAPI呼び出しを実行できるようになります。
認証情報はインスタンス内に保存されていませんが、インスタンスからは依然としてアクセス可能です。内部で動作するコードは、S3やDynamoへアクセスする実際のAPI呼び出しを行うために認証情報を知る必要があるため、メタデータサービスと呼ばれる仕組みが要求に応じてそれらを提供します。メタデータサービスはAWSにおけるインスタンスやコンテナ向けの特別な仕組みで、その構成に関するあらゆる情報を保持しています。例えばサーバーが自身のIPアドレスを取得できることは非常に重要です。
ここに攻撃の余地が生じます。
メタデータサービスは、アクセスすれば要求した情報を返す単なるURLです。curl 169.254.169.254/latest/meta-data/ で基本情報がすべて取得でき、パス curl 169.254.169.254/latest/meta-data/iam-security-credentials/ を使えばアクセスキー、シークレットキー、トークンが取得できます。(Lambdaを起点とする攻撃の場合、見た目はまったく異なり、curlではなくSDKのコードを使用しますが、原理は同じです。)
攻撃者はこれらの認証情報をコピーし、侵害したサーバー上にコードを読み込んで実行する必要なく、別の場所でツールに埋め込んで使用できます。さらにURLベースであるため、完全な任意コード実行を必要とせず、より広範なSSRF攻撃の対象となります。認証情報はいずれ失効しますが、攻撃の内容によっては、現在の認証情報が機能しなくなったことを確認した時点で再度アクセスし、新しい認証情報を取得することもあります。
Amazonは既知のアドレス範囲外で窃取・使用された認証情報を検知する仕組みを備えているため、近年の巧妙な攻撃者は自身が管理するAWSアカウント内でその認証情報を使用します。
IAMロール窃取のキルチェーンを断ち切る
キルチェーンを整理してみましょう。攻撃者は次のことを行う必要があります。
- ロールの認証情報にアクセスできるインスタンス、コンテナ、またはLambdaの脆弱性を発見し、悪用する。これはほぼ常に顧客側のミスに起因します。パッチ適用の漏れ、不要なポートの開放、脆弱なコードのデプロイなどです。
- 現在のロールの認証情報を抽出する。
- 自身の管理下にある環境で、許可されたAPI呼び出しを成功させる。
- 許可されたIAMロールの権限ポリシーの範囲内で、何らかの悪事を働く。もっとも「おそらく悪事」であって、攻撃者が代わりにコードにパッチを当ててくれるわけではありません。
以下の手法は、このチェーンのさまざまな環を断ち切るもので、検知的コントロールと予防的コントロールが混在しています。圧倒されるように見えても気に病む必要はありません。私が関わってきた組織のうち、これらを包括的に、とりわけ大規模に実装できているところはごく、ごくわずかです。
攻撃チェーンのさまざまな環を断ち切るための6つの手法
- 脆弱性管理
- リソース制限を伴う最小権限のIAM権限ポリシー
- 権限ポリシーでIP、VPC、その他のリクエスト送信元による条件制限を使用する
- ポリシー付きのサービスエンドポイントとリソースポリシーを併用する
- HTTPユーザーエージェントフィルタを備えたメタデータプロキシを追加する(メタデータサービス保護)
- ロールの重複使用に対する保護
脆弱性管理
- 複雑さ: 中
- 有効性: 低
- 拡張性: 困難
- 種別: 検知的および予防的
当然ながら、まず取り組むべきは、攻撃者が侵入経路を広げて認証情報を奪うために利用しうる初期の脆弱性や設定ミスをすべて排除することです。これにはクラウド固有の新しい要素は何もないため、複雑さは「中」と評価しました。一方で、包括的な脆弱性管理が過去数十年にわたる数多の侵害を防げてきたわけではないので、有効性は「低」としています。概念は単純ですが、大規模になると途方もなく複雑です。
リソース制限を伴う最小権限のIAM権限ポリシー
- 複雑さ: 中
- 有効性: 高
- 拡張性: 中~困難
- 種別: 予防的
AWSのIAMポリシーはデフォルト拒否であり、明示的な許可ステートメントと拒否ステートメントを含みます。たとえば、S3バケットの読み取りだけを許可するポリシーを記述できます。また、リソース制限も含まれるため、許可ステートメントがロールに読み取りAPIの呼び出しを認可する一方で、リソース制限によってロールが読み取れるバケットやオブジェクトを特定のものに限定できます。防御は常に、必ずここから始めてください。アセスメントを実施すると、ほぼすべてのプロジェクトで、権限(API呼び出し)を与えすぎ、リソース制限が不足しているIAMポリシーが見つかります。そのサービスにDynamoデータベースへのアクセスが必要なのは確かでしょうが、すべてのテーブルへのアクセスまで必要でしょうか。このコントロールは小規模であれば実装はさほど難しくありませんが、規模が大きくなり、こうしたポリシー判断に関わる人間が増えるほど、大規模での一貫性維持は難しくなります。また、誰かが新しい権限を含むポリシーをロールに追加した場合に備えて、明示的な拒否ステートメントを加えることも重要です。権限は累積されますが、拒否ステートメントは許可ステートメントを常に上書きします。
権限ポリシーでIP、VPC、その他のリクエスト送信元による条件制限を使用する
- 複雑さ: 高
- 有効性: 中~高
- 拡張性: 困難
- 種別: 予防的
IAMポリシーは条件ステートメントをサポートしており、IPアドレスや送信元VPCなどさまざまな選択肢を利用できます。特定のロールがアプリケーションスタック内の特定リソースからしかAPI呼び出しを行わないと分かっているなら、認可をそのIPアドレスやサブネットに限定できます。攻撃者が認証情報を盗み、別の場所で使おうとしてもAPI呼び出しは失敗します。これは精密誘導型の大ハンマーのようなもので、概念は容易でも実行は困難です。適切な実装を妨げる別の複雑さに直面することがあるからです。たとえば、AWSサービスへのAPI呼び出しは、インターネットに直接出るか、NATゲートウェイを経由するか、サービスエンドポイント(これについては後ほど説明します)で内部的にルーティングされます。検出されるIPアドレスは、API呼び出しがインターネットに至る経路によって変わります。いずれも管理・検出(そして自動化)は可能ですが、まずは各パターンを理解できるよう事前に読み込んでおくとよいでしょう。
具体例については、Netflixによるこの投稿の前半をご覧ください。
Lambda関数をVPC上で実行していない限り、侵害された関数を保護する手段としてこれは選択肢になりません。
ポリシー付きのサービスエンドポイントとリソースポリシーを併用する
- 複雑さ: 中
- 有効性: 中~高
- 拡張性: 中
- 種別: 予防的
AWSにおけるサービスエンドポイントは、通常はインターネット経由でAWSサービスへ向かうトラフィックを内部へ再ルーティングする、ネットワーク上のタップのようなものです。もともとは、インターネットへ到達する手段を持たない完全にプライベートなサブネットからでも特定のAWSサービスにアクセスできるようにするために作られました。エンドポイントはポリシーをサポートしており、IAMポリシーとよく似た方法でアクセスやアクションを制限できます。この場合、エンドポイントポリシーに制限を追加し、そのエンドポイントの先にある特定のリソースへののみアクセスを許可します(S3が最も一般的な例です)。許可するバケットを指定すれば、そのサブネット内の他のリソースはそのサービスにアクセスできません。これはIAMポリシーに対する最後の砦と考えてください。制限的なポリシーを適用したサービスエンドポイントがあれば、誰かが誤って(あるいは意図的に)ロールに本来より広いアクセス権を与えてしまっても、サービスエンドポイントポリシーで許可されていないものにはアクセスできません。つまり、リソースへのアクセスを許可する必要があるポリシーの層が3つあるということです。
- ロールにそのリソースへのアクセスを許可するIAM権限ポリシー。
- 使用されるロールの権限にかかわらず、エンドポイント経由のリクエストに対してリソースへのアクセスを許可するサービスエンドポイントポリシー。
- 承認されたIPアドレスからのみアクセスを許可できる、バケットポリシーまたはリソースポリシー(リソースの種類によって異なります)。
Lambda関数をVPC上で実行していない限り、この手法もまた、侵害された関数を保護する選択肢にはなりません。
HTTPユーザーエージェントフィルタを備えたメタデータプロキシを追加する(メタデータサービス保護)
- 複雑さ: 高
- 有効性: 中
- 拡張性: 困難
- 種別: 予防的
ここまでのコントロールはいずれも、攻撃者がロールの認証情報を盗み得ることを前提としています。しかし、承認済みのインスタンスやコンテナが侵害されたとしても、認証情報を入手しにくくする方法があるとしたらどうでしょうか(この手法はLambda関数には使えません)。新たな選択肢として、そもそもメタデータサービスへのアクセスを制限する方法があります。IPTablesでこれを試みた例もありますが、インスタンス上で稼働しているコードに必要な機能まで壊してしまう恐れがあります。2018年11月、AWSとNetflixは協力し、AWS SDKから行われるAPI呼び出しのHTTPヘッダーにユーザーデータを追加し始めました。これはSSRFに対する防御になります。ほとんどのSSRF攻撃は、アプリケーションを騙して攻撃者の代わりにHTTPリクエストを行わせるものですが、そうしたリクエストは通常curlのようなコマンドラインツールや別のプロセスから発せられ、AWS SDK由来のユーザーデータヘッダーを欠いているからです。これを機能させるには、そうしたリクエスト向けにプロキシを挿入する必要があります。インスタンスやコンテナ向けにはオープンソースの選択肢がいくつかあり、仮想アプライアンスやsquidプロキシにトラフィックをルーティングする代わりに、インスタンス上で動作するプロキシもあります。
攻撃者がホストインスタンスを侵害してシェルを実行した場合、Roxyを無効化したり承認済みプロセスを乗っ取ったりできるため、この手法は機能しません。
詳細については、こちらのNetflixの投稿をご覧ください。
ロールの重複使用に対する保護
- 複雑さ: 高
- 有効性: 高
- 拡張性: 高
- 種別: 検知的
これもNetflixのチームによるものです。同チームは、AWS内であっても、IAMロールが許可されていない場所で使用されていることを検知する優れた手法の手順を公開しました。リンク先の投稿を読むことを強くお勧めしますが、要点は、CloudTrailログと他のツールを組み合わせて、どのインスタンスがどのIPアドレスからどのロールを使用しているかの表を維持するというものです。そのうえで他のAPI呼び出しを監視し、承認済みの場所で使用されているのと同時に、あるロールが新しいIPアドレスから再利用されている状況を見つけます。この方法なら、組織全体で使用中のIPアドレスをすべて把握しておく必要はなく、使用状況の表を動的に構築し、そのロールが同時に別の場所で使われていることを検知できます。CloudTrailを集約していればロジックを中央で実行できるため、この手法は極めてスケーラブルです。CloudTrailの集約はいずれにせよ一般的なベストプラクティスです。
まとめ
これもまた長大な投稿になりました。すべてのデプロイでこれらの選択肢をすべて実装できるとは考えていません。整理のために、IAMロール悪用のキルチェーンを順に見ていきましょう。
- ロールの認証情報にアクセスできるインスタンス、コンテナ、またはLambdaの脆弱性を発見し、悪用する。これはほぼ常に顧客側のミスに起因します。パッチ適用の漏れ、不要なポートの開放、脆弱なコードのデプロイなどです。
- 脆弱性管理(アプリケーション向けのSASSTやDASTなどのツールを含む)と、クラウド設定のアセスメント(DisruptOpsや、ProwlerやCloudMapperといったオープンソースツールの利用)が第一の防御線です。
- 現在のロールの認証情報を抽出する。
- メタデータサービス保護と脆弱性管理
- 自身の管理下にある環境で、許可されたAPI呼び出しを成功させる。
- ロールの重複使用の検知、権限ポリシーでのIP、VPC、その他のリクエスト送信元による条件制限の使用、ポリシー付きサービスエンドポイントとリソースポリシーの併用
- 許可されたIAMロールの権限ポリシーの範囲内で、何らかの悪事を働く。もっとも「おそらく悪事」であって、攻撃者が代わりにコードにパッチを当ててくれるわけではありません。
- リソース制限を伴う最小権限のIAM権限ポリシー
この記事が、こうした攻撃の成功率を下げる方法を把握する一助となれば幸いです。