攻撃の初動としても利用される GetCallerIdentity とは何か

記事タイトルとURLをコピーする

セキュリティサービス部 佐竹です。
先日、Amazon GuardDuty から「Critical」の通知を受け取り、フォレンジック調査を行っていました。今回は、その通知の引き金となった sts:GetCallerIdentity について、セキュリティの観点から詳しく解説をしていきます。

はじめに

Amazon GuardDuty から「Critical」の検出アラートが発報されました。従来の GuardDuty の検出結果は「High」「Medium」「Low」が主でしたが、今回は「Critical」です。

これは、2024年 の AWS re:Invent で発表された新機能「GuardDuty Extended Threat Detection」によるものです。この機能は、個別の不審なアクティビティ(シグナル)を関連付け、一連の「攻撃シーケンス」として検出するもので、現状「Critical」は GuardDuty Extended Threat Detection で生成されたもののみとなっています。

関連ブログ

以前、GuardDuty Extended Threat Detection については詳しく解説しておりますので、以下合わせてご覧ください。

blog.serverworks.co.jp

検出された「Initial Access」

実際に検出された GuardDuty のマネジメントコンソールの画面キャプチャがこちらです。

Signals(兆候)として、2つのタイムラインがあるのですが、注目したいのは初回のアクセスです。

IAM access key & secret key pair was identified as potentially compromised by Amazon threat intelligence. として「Initial Access」が記載されています。

その下の MITRE tactics を見ると、こちらでも Initial Access(初期侵入)がハイライトされています。攻撃者が何らかの方法でアクセスキーを入手し、最初のアクションを起こした、と GuardDuty が判断したということになります。

CloudTrail から確認した API Call

「具体的に何が実行されたのか?」を追跡するためには、CloudTrail のログを確認することが重要です。特に S3 のデータイベントは、マネジメントコンソールから閲覧できません。S3 のデータイベントを見たい場合には、Amazon Athena 等を使い、ログファイルを直接閲覧します。

今回は、利用されてしまった IAM User の名前を使って、そのログを us-east-1 で確認します。これは、IAM 関係の API Call が us-east-1 にロギングされるためです。

それに加えてもう1つ、「何故リージョンが重要か」というと、CloudTrail のログはリージョンごとにパーティション化されているためです。つまり、リージョンと年月を絞り込むことで、Athena のスキャン対象を大幅に削減し、コストが最適化できます。例えば以下のようにすると、スキャン範囲が大きく絞り込めます。

LOCATION
's3://central-test-cloudtrail/AWSLogs/012345678901/CloudTrail/us-east-1/2025/10'

その結果が以下です。

GetCallerIdentity

初回のアクセスを見てみると、eventnameGetCallerIdentityeventsourcests.amazonaws.com となっていることがわかります。

これが、GuardDuty が「Initial Access」の兆候として検出した API の呼び出しです。

そうなってくると「GetCallerIdentity」とは一体何なのか?という疑問を覚えることになるでしょう。

GetCallerIdentity とは何か?

GetCallerIdentity は、AWS Security Token Service (STS) が提供する API の一つです。

docs.aws.amazon.com

説明には以下の通りの記載があります。

Returns details about the IAM user or role whose credentials are used to call the operation.

(日本語訳) 操作の呼び出しに使用される認証情報を持つ IAM ユーザーまたはロールの詳細を返却します。

これはつまり、OS でいうところの whoami とか、そういう類のコマンドというわけです*1

実際に AWS CLI で実行してみる (IAM Role の場合)

ではこれを実際に試してみましょう。

AWS CLI では、以下のように実行します。

$ aws sts get-caller-identity

これを実行すると、そのコマンドを実行するために使われたIAMクレデンシャルの詳細が返されます。

get-caller-identity

返ってくる情報は以下の3つです。

  • UserId: IAM User や引き受けた Role の一意な ID
  • Account: そのクレデンシャルが属する AWS アカウント ID
  • Arn: 呼び出し元の IAM プリンシパル(User または Role)の ARN

これにより「ここはどこ? 私はだれ?」が明らかになります。

実際に AWS CLI で実行してみる (IAM Userの場合)

上記の例は IAM Role のため少々現実味がないかもしれません。

よって、IAM User (単独)の場合も以下に記します。

  • 成功時(アクセスキーが有効な場合)
>aws sts get-caller-identity
{
    "UserId": "AIDAJIP54QQQQQQQQQQQQ",
    "Account": "7723999955555",
    "Arn": "arn:aws:iam::7723999955555:user/satake"
}
  • 失敗時(アクセスキーが無効化されている場合)
>aws sts get-caller-identity

An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.

なぜ GetCallerIdentity が攻撃の起点(Initial Access)なのか

whoami コマンド自体に害がないのと同じく、GetCallerIdentity API 自体は単に情報を取得するだけで、リソースを変更したりデータを窃取したりするものではありません。

では、なぜ GuardDuty はこれを「Initial Access(初期侵入)」という攻撃の一部として検出したのでしょうか?

攻撃者にとっての「便利な」現在地確認

ここで、この鍵を拾った攻撃者の視点で考えてみましょう。

もしあなたが、GitHub リポジトリのコードにハードコードされていたり、フィッシングで入手したりしたアクセスキーを手に入れたとします。

そのキーが本物か、まだ有効か、そしてどの AWS アカウントのものか、全く分からない状況だとします。

そこで、まず実行するのが aws sts get-caller-identity となるわけです。

  • シナリオ1:エラー(InvalidClientTokenIdなど)
    • → 「このキーは無効だ(失効済み、または偽物)となる」
  • シナリオ2:成功(JSONが返ってくる)
    • → 「このキーは有効だ(生きている)となる」
    • → 「自分は今、アカウントID 123456789012 の、MyUser という IAM User として振る舞えるぞ」

このように、GetCallerIdentity は、攻撃者が入手したクレデンシャルの「有効性確認」「現在地(アカウント ID や権限)の特定」を行うための、最も手軽で確実な手段となります。

これが、whoami と同じく、攻撃者が「侵入(Initial Access)」に成功した直後に実行する典型的な「偵察(Discovery)」行動なのです。

この後何が起きるか?

IAM アクセスキーが「生きている」と判断されると、すぐさま攻撃に移られることがあります。

そして、その後何が起きるかは「その鍵がどこまでの権限を持っているのか」によりますし、攻撃者が実行したいと考えている Script にもよります。

これは一例ですが、盗まれた IAM User が IAMFullAccess のような強権限を持っていた場合には、新たに AdministratorAccess を保持する IAM User を作成され、そこから巨大なインスタンスを構築されたような事故も過去ありました。

GetCallerIdentity は制限ができない

ここで一つの疑問が浮かびます。「IAM ポリシーで禁止すればよいのでは?」と。

実は、sts:GetCallerIdentity は非常に特殊な API です。

この API は、IAMポリシーで明示的に Allow(許可)されていなくても、有効なクレデンシャルであれば誰でも実行できます

例えば、以下のポリシーだけを持っているとします。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name"
      ]
    }
  ]
}

この状態でも GetCallerIdentity は呼び出せてしまいます。

さらに、ドキュメントには以下の記載があります。

No permissions are required to perform this operation. If an administrator attaches a policy to your identity that explicitly denies access to the sts:GetCallerIdentity action, you can still perform this operation. Permissions are not required because the same information is returned when access is denied.

(日本語訳)

この操作を実行するのに必要な権限はありません。管理者が sts:GetCallerIdentity アクションへのアクセスを明示的に拒否するポリシーをIDに適用している場合でも、この操作は実行できます。アクセスが拒否された場合にも同じ情報が返されるため、権限は必要ありません。

先程の通り「暗黙的な Deny」が有効ではないように、「明示的な Deny」も有効ではありません。つまり、この API を Deny 等で制限することはできません。

よって攻撃者は「GetCallerIdentity」により確実にその鍵の有効性と、有効な場合には「対象の AWS アカウント等の情報」を得ることが可能になります。

小話:AWS Chatbot と Critical 通知

余談ですが、この「Critical」通知は Amazon Q Developer in chat applications(旧称 AWS Chatbot)による Slack 連携でも受け取りました。

何故か High にされる Extended Threat Detection

実のところ以前は、AWS Chatbot は Critical の Severity に対応しておらず、Critical の通知がなぜか High として Slack に表示されるという問題がありました。

しかし、この問題も(私の環境では)2024年10月頃には修正されたようでした*2。現在は GuardDuty が発行した通り「Critical」として正しく Slack に通知されるようになっています。

まとめ

本ブログでは GuardDuty Extended Threat Detection で検出されたインシデントを元に sts:GetCallerIdentity についてセキュリティの観点から解説を行いました。

aws sts get-caller-identity は、AWS 環境における所謂 whoami であり、管理者にとっても攻撃者にとっても「自分が誰か」を知るための基本的なコマンドです。

この API Call 自体は無害ですが、それによって返却される値は攻撃者にとって非常に重要な意味を持ちます。

GuardDuty Extended Threat Detection が、漏洩した可能性のあるキーによる GetCallerIdentity の実行を「Initial Access」の兆候として検出するのは、まさにこの攻撃者の行動パターンを捉えたものです。

ということで、以上が「何故 GuardDuty Extended Threat Detection が GetCallerIdentity の実行を Initial Access として検出したのか」の解説でした。

では、またお会いしましょう。

*1:whoami コマンドは、現在コンピュータにログインしているユーザー名(アカウント名)を表示するためのコマンドです

*2:AWS サポートに改善依頼を出した甲斐がありました

佐竹 陽一 (Yoichi Satake) エンジニアブログの記事一覧はコチラ

セキュリティサービス部所属。AWS資格全冠。2010年1月からAWSを業務利用してきています。主な表彰歴 2021-2022 AWS Ambassadors/2020-2025 Japan AWS Top Engineers/2020-2025 All Certifications Engineers。AWSのコスト削減やマルチアカウント管理と運用を得意としています。