← すべての記事 IAM

AWS の権限昇格攻撃 3 例: CloudTrail に残る証拠と修正方法

要点

  • AWS における権限昇格攻撃とは、プリンシパルを、保持している権限から一度も付与されていない権限へと移す一連の API 呼び出しです。呼び出し自体はありふれたものなので、見つけにくくなります。
  • 実際のアカウントで繰り返し現れる連鎖は 3 つあります。iam:PassRole と lambda:CreateFunction の組み合わせ、iam:UpdateAssumeRolePolicy に続く sts:AssumeRole、そして別のユーザーに対する iam:CreateAccessKey です。
  • どの連鎖も特定の CloudTrail イベントを残します。検知とは、本来その呼び出しを行うはずのないプリンシパルからのイベントを監視し、リクエストパラメータをシグナルとして扱うことです。
  • どの連鎖にも的を絞った修正があります。iam:PassedToService 条件の追加、権限の削除、または特定のアクションに対する Deny です。ほとんどの場合、ポリシーの変更は 1 つで済みます。
  • 検知と予防はどちらも必要です。CloudTrail は呼び出しの後に教えてくれます。経路を事前に検証すれば、そもそもどのプリンシパルがその呼び出しを行えるのかがわかります。

AWS における権限昇格攻撃とは、プリンシパルを、保持している権限から一度も付与されていない権限へと移す一連の API 呼び出しです。通常の意味でのエクスプロイトはありません。使われる呼び出しは管理者が毎日行っているものと同じで、だからこそ気づきにくく、開いたまま放置されやすいのです。AWS 権限昇格マップ には、このように使われ得るすべての権限が掲載されています。この記事では、最もよく見られる連鎖を 3 つ取り上げ、それぞれについて仕組み、CloudTrail に記録される内容、そして経路を断ち切る変更を示します。

連鎖 1: Lambda にロールを渡す

CreateFunction iam:PassRole runs as role 01 Attacker principal 02 New Lambda 03 Passed role 04 Administrator
連鎖 1。iam:PassRole と lambda:CreateFunction を併せ持つプリンシパルは、関数を作成し、そこに特権ロールを渡し、その関数はそのロールとして実行されます。どちらの権限も、単独では警戒すべきものに見えません。

権限。特権ロールに対する iam:PassRole と、lambda:CreateFunction の組み合わせ。通常は lambda:InvokeFunction も伴いますが、関数はイベントソース経由で起動することもできます。

仕組み。攻撃者は新しい Lambda 関数を作成し、その実行ロールとして特権ロールを渡します。ロールの信頼ポリシーが lambda.amazonaws.com を許可しているため、AWS はこの受け渡しを受け入れます。続いて攻撃者が関数を呼び出すと、自分で書いたコードが特権ロールの権限で実行されます。そのロールが管理者であれば、作成 1 回と呼び出し 1 回でアカウントは攻撃者のものになります。同じパターンは EC2、ECS、Glue、CloudFormation、CodeBuild など、渡されたロールを受け入れるあらゆるサービスで成立します。

CloudTrail に残るもの。lambda.amazonaws.com からの CreateFunction 管理イベントで、その requestParameters.role が特権ロールの ARN になっているもの。iam:PassRole のチェック自体は独立したイベントを生成しません。受け渡しは作成呼び出しのパラメータで確認できます。続く Invoke は Lambda のデータイベントなので、証跡で Lambda データイベントが有効になっている場合にのみ記録されます。これは既定では無効であり、まさにこの理由から有効にしておく価値があります。両方がそろっていれば、シグナルは組み合わせです。これまで関数を作成したことのないプリンシパルが、価値の高いロールを付けた関数を作成し、数分以内にそれを呼び出す、という流れです。データイベントがない場合、シグナルは作成呼び出しそのものと、その後に渡されたロールが行う API アクティビティになります。

修正方法。受け渡しの範囲を絞ります。iam:PassRole の付与に iam:PassedToService 条件を加え、ロールを必要とするサービスにしか渡せないようにし、リソース ARN のワイルドカードを特定のロールに置き換えます。プリンシパルがロールを渡す必要がまったくないなら、権限を削除します。詳しい解説: Lambda にロールを渡す。

連鎖 2: ロールの信頼ポリシーを書き換えてから引き受ける

権限。特権ロールに対する iam:UpdateAssumeRolePolicy と、sts:AssumeRole。

仕組み。ロールの信頼ポリシーは、誰がそのロールを引き受けられるかを決めます。このドキュメントを書き換えられるプリンシパルは、自分自身を信頼されたプリンシパルとして追加し、sts:AssumeRole を呼び出してそのロールの一時的な認証情報を受け取ります。元の信頼関係は上書きされた時点で意味を失うため、この手口では、プリンシパルが更新呼び出しで到達できるアカウント内のあらゆるロールを乗っ取れます。書き換えられた信頼ポリシーは誰かが気づくまでそのまま残るので、これは権限昇格であると同時に永続化の手段でもあります。

CloudTrail に残るもの。iam.amazonaws.com からの UpdateAssumeRolePolicy イベントで、新しいポリシードキュメントが requestParameters.policyDocument に入っているもの。その後に、追加されたばかりのプリンシパルから、同じロールに対する sts.amazonaws.com の AssumeRole イベントが続きます。健全なアカウントでは信頼ポリシーはめったに変わらないので、デプロイパイプライン以外からの UpdateAssumeRolePolicy イベントはどれも確認する価値があり、アカウント内部のプリンシパルを追加するものは強いシグナルです。

修正方法。IAM 管理の経路ではないすべてのプリンシパルから iam:UpdateAssumeRolePolicy を削除し、アカウント内の特権ロールに対してはこのアクションに明示的な Deny を設定して、デプロイ用ロールだけを例外にします。詳しい解説: ロールの信頼を書き換えてから引き受ける。

連鎖 3: 別のユーザーのアクセスキーを作成する

権限。呼び出し元以外のユーザーに対する iam:CreateAccessKey。

仕組み。攻撃者は別のユーザー名を指定して iam:CreateAccessKey を呼び出し、そのユーザーの新しい長期アクセスキーを受け取ります。ユーザーのパスワードや既存のキーは一切必要ありません。それ以降、攻撃者はそのユーザーとして API を呼び出せ、新しいキーはパスワードのリセットやユーザーの別のキーのローテーション後も有効なままです。1 回の呼び出しで永続的な認証情報が得られ、なりすまされたユーザーには何も見えないため、3 つのうちで最も気づきにくいものです。

CloudTrail に残るもの。iam.amazonaws.com からの CreateAccessKey イベントで、requestParameters.userName が userIdentity の ID と異なるもの。この不一致がシグナルです。ユーザーが自分のキーを作成するのは通常のことです。あるプリンシパルが別のユーザーのキーを作成するのは、オンボーディング用スクリプト以外ではまれで、そのスクリプトのロールは簡単に許可リストに入れられます。その後の悪用は、被害ユーザーによる新しい送信元 IP とユーザーエージェントからの API 呼び出しとして現れます。

修正方法。ID 管理の経路ではないすべてのプリンシパルから iam:CreateAccessKey を削除し、ユーザーが自分のキーを管理する必要がある場合は、付与の範囲を ${aws:username} に絞って、ユーザーが自分自身のキーしか作成できないようにします。詳しい解説: ユーザーのアクセスキーを作成する。

AWS で権限昇格を検知する方法

上の 3 つの連鎖には、一般化できる共通のパターンがあります。権限昇格は、普段その操作をしていないプリンシパルから、通常とは異なるパラメータを持つありふれたイベントを残します。CloudTrail での検知は、次の 4 つに支えられています。

第一に、CloudTrail はすべてのアカウントとすべてのリージョンで有効にし、ワークロードが書き込めない一元管理用アカウントに証跡を配信する必要があります。証跡を無効化または削除できる攻撃者は証拠を消せるので、StopLogging と DeleteTrail は権限昇格のイベントと同じ監視リストに載せるべきです。

第二に、イベント名だけでなくパラメータを監視します。CreateFunction 単体は日常的な操作ですが、パラメータに管理者ロールが含まれる CreateFunction はアラートに値します。対象ユーザーが呼び出し元と異なる CreateAccessKey も同様です。

第三に、プリンシパルごとにベースラインを取ります。毎時関数を作成する CI ロールと、1 年間一度も IAM を呼び出していない開発者は性質の異なる発生源であり、同じイベントでもそれぞれ意味が違います。

第四に、イベントを組み合わせます。権限昇格は一連の流れです。作成してから呼び出す、信頼を書き換えてから引き受ける、キーを作成してから新しい場所で使う。最初のイベントと 2 番目のイベントを短い時間枠で結び付けるルールは、どちらかのイベント単体よりも誤検知がはるかに少なくなります。Lambda、S3、DynamoDB のアクティビティはデータイベントなので、組み合わせる前に証跡で有効にしておく必要があります。

検知は第二の防衛線

CloudTrail が教えてくれるのは呼び出しが行われた後です。第一の防衛線は、どの呼び出しよりも前に、どのプリンシパルがそれを行えるのかを知ることです。つまり、マップ上のすべての連鎖を取り上げ、アカウント内の実際の認可、すなわち ID ポリシー、境界、SCP、信頼ポリシー、条件と照らし合わせて解決することです。あるプリンシパルについて許可と解決された連鎖は実証済みの経路であり、修正は上で示した変更を、誰かが試す前に適用することです。Pathbreak はこの解決をすべてのアカウントにわたって読み取り専用で行い、実証済みの経路を到達先に応じて順位付けし、各修正が適用された後にそれを確認します。無料の pathbreak-audit ツールは、出発点として、単一アカウント内のどのプリンシパルがこれらの権限を保持しているかを一覧にします。

よくある質問

AWS における権限昇格攻撃とは何ですか。

AWS における権限昇格攻撃とは、プリンシパルが付与されていない権限を得るための一連の API 呼び出しです。たとえば、作成できるサービスに特権ロールを渡す、ロールの信頼ポリシーを書き換えて引き受ける、より強い権限を持つユーザーのアクセスキーを作成する、といったものです。 Pathbreak は、AWS アカウント内のどのプリンシパルがこれらの呼び出しを行えるかを検証します。

CloudTrail で権限昇格を検知するにはどうすればよいですか。

各連鎖が生成する特定のイベントを監視します。たとえば、パラメータに特権ロールを含む CreateFunction、AssumeRole が続く UpdateAssumeRolePolicy、対象ユーザーが呼び出し元と異なる CreateAccessKey です。プリンシパルごとにベースラインを取り、最初のイベントと 2 番目のイベントを組み合わせ、証跡はワークロードが変更できないアカウントに置きます。 Pathbreak は、呼び出しが行われる前に、どのプリンシパルがそれを行えるかを示すことで、CloudTrail による検出を補完します。

iam:PassRole は単独でも危険ですか。

単独では危険ではありません。lambda:CreateFunction や ec2:RunInstances のように、ロールを受け入れるコンピューティングリソースを作成または更新する権限と組み合わさり、かつ対象ロールがそのサービスを信頼している場合に、権限昇格の経路になります。iam:PassedToService と特定のロール ARN で受け渡しの範囲を絞れば、この経路はなくなります。 Pathbreak は経路を検証する際、各ロールの受け渡しについて信頼ポリシーと条件を確認します。

最も多くの権限昇格経路を取り除く修正はどれですか。

ほとんどのアカウントでは、特権ロールに対する iam:PassRole の範囲を絞るか削除するのが最も効果的です。何十ものサービスが渡されたロールを受け入れるためです。Pathbreak のラボアカウントでは、1 つのロールに対する 1 つの Deny で、4,087 本の経路のうち 3,893 本がなくなりました。最初に行うべき変更は、実証済みの経路がどのプリンシパルを通っているかによって決まります。

関連記事

CloudTrail に知らされる前に、今日あなたのアカウントでどのプリンシパルがこれらの呼び出しを行えるのかを確認してください。

デモを申し込む デモを見る