EC2 に IAM アクセスキー を保存して S3 の API をコールしたとき CloudTrail のイベントログの記録内容を調べてみた

2022.06.28

IAM アクセスキーが保存された EC2 を捜索する方法を考えていました。

手始めに CloudTrail のイベントログにどのようなイベントが記録されるか把握しておきたいと思い、今回の検証では IAM アクセスキーを作成し EC2 に保存し、IAM アクセスキーの認証情報を使って S3 の API をコールしたとき、CloudTrail のイベントログにはどのように記録されるのかを確認することを目的とします。CloudTrail のログの内容の記録を残すついでに検証内容を紹介します。

確認結果

EC2 から S3 の API(ListBuckets)をコールしたときの CloudTrail のイベントログより

  • IAM ロールでの API コールは EC2 のインスタンス ID が記録され特定が容易
  • IAM アクセスキーからの API コールは EC2 の Public IP か Private IP から EC2 を特定できる
  • ただし、IAM アクセスキー + NAT Gateway 経由は NAT Gateway の EIP がソースとして記録される
    • NAT Gateway 配下に複数台 EC2 がある場合は1つのイベントログから EC2 の特定は困難
Credential サブネット VPC Endpoint Gateway Type ユーザー名の表示 ソース IP の表示
IAM ロール Public なし EC2 の インスタンスID EC2 の Public IP
IAM ロール Private なし EC2 の インスタンスID NAT Gateway の EIP
IAM アクセスキー Public なし IAM ユーザー名 EC2 の Public IP
IAM アクセスキー Private なし IAM ユーザー名 NAT Gateway の EIP
IAM アクセスキー Public あり IAM ユーザー名 EC2 の Private IP
IAM アクセスキー Private あり IAM ユーザー名 EC2 の Private IP

IAM ロール編

IAM アクセスキーを保存した EC2 と比較するために IAM ロールの場合のイベントログの記録内容を確認します。

AmazonS3ReadOnlyAccess ポリシーをアタッチした IAM ロールを作成し EC2 に設定しました。

パブリックサブネットの EC2 の場合

パブリックサブネットで起動した EC2 から Internet Gateway を経由して S3 バケットへアクセスします。VPC エンドポイントは設定していません。

[ec2-user@ip-10-0-1-232 .aws]$ aws s3 ls | grep abashiri
2022-04-08 10:37:53 abashiri-image
2022-04-08 10:37:52 abashiri-image-log

CloudTrail から ListBuckets イベントを確認します。ユーザー名から EC2 インスタンスの ID を確認できます。

個人的な見どころ

  • アクセス元の EC2 のインスタンス ID (i-0f48040475b4f3464)を確認できる
  • IAM ロール名(s3readonly)を確認できる
  • アクセス元のソースIP(52.197.156.173)は EC2 のパブリック IP であった
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROAQ4BT4DHFO2FNYZAOZ:i-0f48040475b4f3464",
        "arn": "arn:aws:sts::123456789012:assumed-role/s3readonly/i-0f48040475b4f3464",
        "accountId": "123456789012",
        "accessKeyId": "ASIAQ123456789012345",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROAQ4BT4DHFO2FNYZAOZ",
                "arn": "arn:aws:iam::123456789012:role/s3readonly",
                "accountId": "123456789012",
                "userName": "s3readonly"
            },
            "webIdFederationData": {},
            "attributes": {
                "creationDate": "2022-06-28T00:11:43Z",
                "mfaAuthenticated": "false"
            },
            "ec2RoleDelivery": "2.0"
        }
    },
    "eventTime": "2022-06-28T00:20:59Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "ListBuckets",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "52.197.156.173",
    "userAgent": "[aws-cli/1.18.147 Python/2.7.18 Linux/5.10.118-111.515.amzn2.aarch64 botocore/1.18.6]",
    "requestParameters": {
        "Host": "s3.ap-northeast-1.amazonaws.com"
    },
    "responseElements": null,
    "additionalEventData": {
        "SignatureVersion": "SigV4",
        "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "bytesTransferredIn": 0,
        "AuthenticationMethod": "AuthHeader",
        "x-amz-id-2": "kEvE5BsV+VcwE9WiDT1LJpJNXqAfzDMPGV8WkbM3dutCE5XfIbXGvM9E6gIeGYjyf6e+RvGkswg=",
        "bytesTransferredOut": 5391
    },
    "requestID": "9JWF4V4M8CPX3PXE",
    "eventID": "40279e48-60fc-4a2a-9742-3d23cff08dac",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "s3.ap-northeast-1.amazonaws.com"
    }
}

EC2 のパブリック IP アドレス

プライベートサブネットの EC2 の場合

プライベートサブネットで起動した EC2 から NAT Gateway を経由して S3 バケットへアクセスします。VPC エンドポイントは設定していません。

IAM ロールに付与された権限で S3 バケットの一覧を取得(ListBuckets)することができました。

[ec2-user@ip-10-0-17-225 .aws]$ aws s3 ls | grep abashiri
2022-04-08 10:37:53 abashiri-image
2022-04-08 10:37:52 abashiri-image-log

CloudTrail から ListBuckets イベントを確認します。ユーザー名から EC2 インスタンスの ID を確認できます。

個人的な見どころ

  • アクセス元の EC2 のインスタンス ID (i-0989653702d4b4d51)を確認できる
  • IAM ロール名(s3readonly)を確認できる
  • アクセス元のソースIP(54.150.188.89)は NAT Gateway の EIP であった
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROAQ4BT4DHFO2FNYZAOZ:i-0989653702d4b4d51",
        "arn": "arn:aws:sts::123456789012:assumed-role/s3readonly/i-0989653702d4b4d51",
        "accountId": "123456789012",
        "accessKeyId": "ASIAQ123456789012345",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROAQ4BT4DHFO2FNYZAOZ",
                "arn": "arn:aws:iam::123456789012:role/s3readonly",
                "accountId": "123456789012",
                "userName": "s3readonly"
            },
            "webIdFederationData": {},
            "attributes": {
                "creationDate": "2022-06-27T09:38:14Z",
                "mfaAuthenticated": "false"
            },
            "ec2RoleDelivery": "2.0"
        }
    },
    "eventTime": "2022-06-27T09:42:21Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "ListBuckets",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "54.150.188.89",
    "userAgent": "[aws-cli/1.18.147 Python/2.7.18 Linux/5.10.118-111.515.amzn2.aarch64 botocore/1.18.6]",
    "requestParameters": {
        "Host": "s3.ap-northeast-1.amazonaws.com"
    },
    "responseElements": null,
    "additionalEventData": {
        "SignatureVersion": "SigV4",
        "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "bytesTransferredIn": 0,
        "AuthenticationMethod": "AuthHeader",
        "x-amz-id-2": "pDzNkahMJYN5k0pSHFUyAsMCPq8chu1it5UWuqT7S//x1s72py7h0oDh2eY0lqbejET56k8ighU=",
        "bytesTransferredOut": 5391
    },
    "requestID": "6P0XPKQ7PA6T1A1K",
    "eventID": "e939f3aa-a258-4227-888e-ba418a0d7efb",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "s3.ap-northeast-1.amazonaws.com"
    }
}

NAT Gateway の EIP

IAM アクセスキー編

AmazonS3ReadOnlyAccessポリシーをアタッチした IAMユーザーを作成し、IAM アクセスキーを発行しました。EC2 は IAM ロールを設定せず、ここで発行した IAM アクセスキーを利用する構成を取ります。

パブリックサブネットの EC2 の場合

認証情報を EC2 に書き込み、IAM アクセスキーが EC2 上に保存しました。S3 バケットへのアクセス経路は Internet Gateway です。Internet Gateway へのルートを設定したサブネット上で EC2 には パブリックIP を付与しています。

[ec2-user@ip-10-0-1-232 ~]$ aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: ap-northeast-1
Default output format [None]: json

IAM アクセスキーに付与された権限で S3 バケットの一覧を取得(ListBuckets)することができました。

[ec2-user@ip-10-0-1-232 ~]$ aws s3 ls | grep abashiri
2022-04-08 10:37:53 abashiri-image
2022-04-08 10:37:52 abashiri-image-log

CloudTrail から ListBuckets イベントを確認します。ユーザー名から IAMアクセスキーの元のユーザー名を確認することができます。IAM ロールのときとは異なり、EC2 インスタンス ID は確認できませんでした。

個人的な見どころ

  • IAM ユーザー名(aeecess-key-on-ec2)を確認できる
  • アクセス元のソースIP(52.197.156.173)は EC2 のパブリック IP であった
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "AIDAQ4BT4DHFPP4W7TSKU",
        "arn": "arn:aws:iam::123456789012:user/access-key-on-ec2",
        "accountId": "123456789012",
        "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "userName": "access-key-on-ec2"
    },
    "eventTime": "2022-06-27T06:55:24Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "ListBuckets",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "52.197.156.173",
    "userAgent": "[aws-cli/1.18.147 Python/2.7.18 Linux/5.10.118-111.515.amzn2.aarch64 botocore/1.18.6]",
    "requestParameters": {
        "Host": "s3.ap-northeast-1.amazonaws.com"
    },
    "responseElements": null,
    "additionalEventData": {
        "SignatureVersion": "SigV4",
        "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "bytesTransferredIn": 0,
        "AuthenticationMethod": "AuthHeader",
        "x-amz-id-2": "5OleDo0vLGBwP4/ly62pWv1kLmBCOw3k9L9dPjHE6keZuRJaD1zia8hcm3DuhjuQaUP446jAJUg=",
        "bytesTransferredOut": 5391
    },
    "requestID": "YJK57XN5ZFW2B0PH",
    "eventID": "46651a03-4bed-4b03-b4c0-cbfb905b4a4d",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "s3.ap-northeast-1.amazonaws.com"
    }
}

EC2 のパブリック IP アドレス

念のため、EC2 からグローバル IP を確認しました。間違いなく S3 バケットにアクセスした元の IP がソース IP と記録される様です。

[ec2-user@ip-10-0-1-232 ~]$ curl https://ifconfig.me
52.197.156.173

わかったこと

EC2 のパブリック IP がsourceIPAddress表示されるため、EC2 インスタンスの特定はできないまでも EIP から辿ればアクセス元の EC2 インスタンスを特定することは可能。

プライベートサブネットの EC2 の場合

同様に認証情報を EC2 に書き込み、IAM アクセスキーが EC2 上に保存しました。S3 バケットへのアクセス経路は NAT Gateway を経由してアクセスします。NAT Gateway へのルートを設定したサブネット上で起動している EC2 です。

パブリックサブネットで検証した EC2 を踏み台に利用してアクセスしました。同様に IAM アクセスキーに付与された権限で S3 バケットの一覧を取得(ListBuckets)することができました。

[ec2-user@ip-10-0-17-225 ~]$ aws s3 ls | grep abashiri
2022-04-08 10:37:53 abashiri-image
2022-04-08 10:37:52 abashiri-image-log

個人的な見どころ

  • IAM ユーザー名(aeecess-key-on-ec2)を確認できる
  • アクセス元のソースIP(54.150.188.89)は NAT Gateway の EIP であった
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "AIDAQ4BT4DHFPP4W7TSKU",
        "arn": "arn:aws:iam::123456789012:user/access-key-on-ec2",
        "accountId": "123456789012",
        "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "userName": "access-key-on-ec2"
    },
    "eventTime": "2022-06-27T07:06:53Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "ListBuckets",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "54.150.188.89",
    "userAgent": "[aws-cli/1.18.147 Python/2.7.18 Linux/5.10.118-111.515.amzn2.aarch64 botocore/1.18.6]",
    "requestParameters": {
        "Host": "s3.ap-northeast-1.amazonaws.com"
    },
    "responseElements": null,
    "additionalEventData": {
        "SignatureVersion": "SigV4",
        "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "bytesTransferredIn": 0,
        "AuthenticationMethod": "AuthHeader",
        "x-amz-id-2": "22aQ5pD3JaEQNdwI6ziYBW1gNVlRvKSax9JBZgKYw+g1DWWkNZ5hbeyEz3AqZGhijmDUmSYc4+c=",
        "bytesTransferredOut": 5391
    },
    "requestID": "NK5TSRSJNE1KJZGE",
    "eventID": "9911af24-f5fb-4d27-b828-4d6d78c2733d",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "s3.ap-northeast-1.amazonaws.com"
    }
}

NAT Gateway の EIP

念のため、EC2 からグローバル IP を確認しました。同様に S3 バケットにアクセスした元の IP がソース IP と記録される様です。

[ec2-user@ip-10-0-17-225 ~]$ curl https://ifconfig.me
54.150.188.89

わかったこと

アクセス元の IP(sourceIPAddress)に NAT Gateway の EIP が表示されるため、同 NAT Gateway を経由する EC2 インスタンス が複数台ある場合は、CloudTrail のひとつのイベントログから EC2 インスタンスを特定することはできない。

VPC エンドポイント Gateway 型の場合

Gateway 型の VPC エンドポイントはよく利用されていると思います。VPC エンドポイントを設定し同様の手順を実施しイベントログを確認します。

個人的な見どころ

  • IAM ユーザー名(aeecess-key-on-ec2)を確認できる
  • sourceIPAddressには EC2 のプライベート IP が表示される
  • vpcEndpointId で経由してきた VPC エンドポイントを確認できる

パブリックサブネット の EC2 からアクセスしたログ

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "AIDAQ4BT4DHFPP4W7TSKU",
        "arn": "arn:aws:iam::123456789012:user/access-key-on-ec2",
        "accountId": "123456789012",
        "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "userName": "access-key-on-ec2"
    },
    "eventTime": "2022-06-27T11:43:10Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "ListBuckets",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "10.0.1.232",
    "userAgent": "[aws-cli/1.18.147 Python/2.7.18 Linux/5.10.118-111.515.amzn2.aarch64 botocore/1.18.6]",
    "requestParameters": {
        "Host": "s3.ap-northeast-1.amazonaws.com"
    },
    "responseElements": null,
    "additionalEventData": {
        "SignatureVersion": "SigV4",
        "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "bytesTransferredIn": 0,
        "AuthenticationMethod": "AuthHeader",
        "x-amz-id-2": "V5mPuZ9gO9chY7ij2N4YDiFCmIP3crAE23hdsjJIjnTo9IM17K7S3+3jlTyQ5Jlc0MyNCdS1BO4=",
        "bytesTransferredOut": 5391
    },
    "requestID": "ZZG0ZHDYDQKB2VKE",
    "eventID": "78a65258-0d6d-4147-bb50-e1ab845b9566",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "vpcEndpointId": "vpce-04c1f50dba315db84",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "s3.ap-northeast-1.amazonaws.com"
    }
}

プライベートサブネット の EC2 からアクセスしたログ

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "AIDAQ4BT4DHFPP4W7TSKU",
        "arn": "arn:aws:iam::123456789012:user/access-key-on-ec2",
        "accountId": "123456789012",
        "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "userName": "access-key-on-ec2"
    },
    "eventTime": "2022-06-27T11:43:48Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "ListBuckets",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "10.0.17.225",
    "userAgent": "[aws-cli/1.18.147 Python/2.7.18 Linux/5.10.118-111.515.amzn2.aarch64 botocore/1.18.6]",
    "requestParameters": {
        "Host": "s3.ap-northeast-1.amazonaws.com"
    },
    "responseElements": null,
    "additionalEventData": {
        "SignatureVersion": "SigV4",
        "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "bytesTransferredIn": 0,
        "AuthenticationMethod": "AuthHeader",
        "x-amz-id-2": "j10MVy30v+tXJhVJC3m9AZDX4pA4P67QGnOkbQ+daCjx7VGGbvHnXd4BwcaMSO+xeQqow1HQaro=",
        "bytesTransferredOut": 5391
    },
    "requestID": "JTPF3BX69A6HYWE3",
    "eventID": "e68aa472-3862-46b9-b6c1-74abd9ac7e36",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "vpcEndpointId": "vpce-04c1f50dba315db84",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "s3.ap-northeast-1.amazonaws.com"
    }
}

VPC エンドポイント ID

わかったこと

アクセス元の IP(sourceIPAddress)に EC2 のプライベート IP が表示されるため EC2 の特定が可能になる。

想定と異なった点

Gateway エンドポイントを経由して S3 バケットへのアクセスはパブリック IP が使用され、CloudTrail のソース IP は EC2 の EIP か、NAT Gateway の EIP になると想定していました。実際の結果は CloudTrail のアクセス元の IP は EC2 のプライベート IP アドレスでした。

AWS PrivateLink for Amazon S3 - Amazon Simple Storage Service

まとめ

S3 の API(ListBuckets)をコールしたときのイベントログからでは、IAM アクセスキーかつ、NAT Gateway 経由のイベントログからのソース表示だけは EC2 を特定することができない。他の IAM アクセスキーのケースでも EC2 のインスタンス ID が直接わかるわけではなく、IP アドレスから追いかけて確認する必要がある。

Credential サブネット VPC Endpoint Gateway Type ユーザー名の表示 ソース IP の表示
IAM ロール Public なし EC2 の インスタンスID EC2 の Public IP
IAM ロール Private なし EC2 の インスタンスID NAT Gateway の EIP
IAM アクセスキー Public なし IAM ユーザー名 EC2 の Public IP
IAM アクセスキー Private なし IAM ユーザー名 NAT Gateway の EIP
IAM アクセスキー Public あり IAM ユーザー名 EC2 の Private IP
IAM アクセスキー Private あり IAM ユーザー名 EC2 の Private IP

おわりに

収穫は IAMアクセスキーを使った EC2 では インスタンス ID が表示されないことと、VPC エンドポイントの Gateway 型を経由すると アクセス元がプライベート IP になるということでした。それと、IAM アクセスキーが埋め込まれている EC2 をこの方法で見つけるには非効率ということがわかりました。

非常に地味な検証で時間もかかるので同じことしようと思った方の参考になれば幸いです。

参考