Amazon Web Services (AWS) インシデント調査のメモ。
AWSの構成要素
AWSは以下の要素で構成される。
- AWS Organizational Root
- AWS Organization
- AWS Organizational Unit (OU)
- AWS Account
Organizational Root
Organizationの管理に使用する特別なAccount。Organization内のあらゆるリソースへアクセスできる。
AWSはOrganizational Rootへのログインを検知すると、アラートを発報する。
Organization
組織内の全てのAWS Accountをひとつのツリーへとまとめる。
これにより
- AWS Account間のアクセスを管理する。
- すべてのAWS Accountでシングルサインオンを可能にする。
- ポリシーとコンプライアンスを適用できる。
Organizational Unit (OU)
複数のAWS Accountをグループ化したもの。OUごとに異なるポリシーやコンプライアンスを適用できる。OU間を跨ぐロールも作成できる。
OUで規定されたロールは、OUの配下にあるあらゆるリソースへアクセスできる。異なるOUへはアクセスできない。 (OU間を跨ぐロールは除く)
また上位のOrganizationへもアクセスできない。
Account
AWSにおいてAccountはTenantと言い換えることができる。
- それぞれのAccountには一意の数字が与えられる。
- それぞれのAccountにはrootユーザーが存在する。
- それぞれのAccountは各自のログを所有する。
- それぞれのAccountはIAMユーザーというローカルユーザーを持つことができる。
Accountで規定されたロールは、そのAccount内のリソースのみアクセスできる。異なるAccountや上位のOrganizationやOUへはアクセスできない。
IAM (Identity and Access Management)
Root Account vs IAM Account
Root Account
- 特権ユーザー。
- それぞれのAccountには必ずRootが存在する。無効化することはできず、パーミッションを取り除くこともできない。
- AWSはRootへのログインを検知すると、アラートを発報する。
IAM Account
- 一般のユーザーやサービス用のAccount
- 認証にはパスワード、APIキー、もしくはその両方を用いる。
Policy vs Role
Policy
- IAM Accountに付与する権限の最小単位。
- ユーザーがどのリソースに対して、どのAPIを実行できるかをJSON形式で定義する。
- 例)ユーザーのS3 Storage bucketへの読み取り権を許可する
以下はPolicyの例。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ListRead",
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetAccountPublicAccessBlock",
"s3:ListAccessPoints",
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
}
]
}
AWSのAPIエンドポイントへのリクエストが発生すると、AWSはリクエストの送信者に適用されているポリシーを確認し、リクエストを許可するか否かを決定する。リクエストを明示的に許可するポリシーが無い限り、AWSはリクエストを拒否する(暗黙のDeny)。ただし、ポリシーに関わらずRootはAccount内のすべてのリソースにアクセスできる。
また、同一のリソースに対してAllowポリシーとDenyポリシーが存在する場合、Denyポリシーが優先される。
Role
- Policyの集合体。
- AWSによってあらかじめ定義されたRole (Predefined Roles)が存在する。
- Predefined Rolesに独自のPolicyを加えて、Custom Rolesとすることができる。
IAM Policy Simulator
作成したPolicyが実行可能なAPIやアクセス可能なデータをシミュレートしてくれる。
IAMのインシデント調査の流れ
- 侵害されたクレデンシャル (APIキー、IAM Role、 Account) を特定する 。
- 1. に適用されているPolicyとRoleを確認して、1.がアクセス可能なデータを列挙する。
- Policy Simulatorを利用してアクセスされた可能性のあるデータを洗い出す。
- クレデンシャルの悪用可能な範囲を特定した後、その情報をもとに改めてログを調査する。
AWSへのアクセス方式
Username and Password
- ユーザー名とパスワードを用いる。
- CLI (command line interface)やSDK (software development kits)はユーザー名とパスワードによるアクセスをサポートしない。
API Key
- APIキーを用いる。
- APIキーはユーザー、サービス、ロール、リソースごとに作成可能。
- APIキーそのものにアクセス可能範囲を定義する。
- CLIやSDKで使用可能。
- 簡単に監査でき、自動的に失効するように設定することもできる。
STS (Security Token Service) Token
- トークンを用いる。
- 特定のリソースへのアクセスを一時的に許可したい場合に用いる。
- 一定時間が過ぎたらトークンは自動的に失効する。
IAM Roles Assigned
- リソースに対してIAM Roleを適用することで、そのRoleに定義された挙動のみを許可する。
- よって、リソースへのアクセスの際にクレデンシャルは不要。
IAM Role vs STS Token
IAM Role
IAM Roleはポリシーの集合体で、EC2インスタンスのようなリソースに適用できる。これにより、リソースはAPIキー等を用いることなく、APIを実行できる。同一のIAM Roleを複数のリソースに適用することもできる。
STS Token
STS Tokenはリソースへの一時的なアクセスを許可する一時的なトークンである。
トークンの作成時に以下のことを指定する。
- トークンに付与するロールやポリシー。
- トークンの有効期限。
トークンを使用するユーザーやサービスは、トークンに付与されたロールやポリシーの範囲でのみ、リソースにアクセスできる。有効期限が過ぎるとトークンは失効する。
ARN
Amazon Resource Nameの略。リクエストを送信したリソースを判別するための一意の識別子。
以下はARNの書式。
arn:partition:service:region:account-id:resource-id
arn:partition:service:region:account-id:resource-type:/resource-id
arn:partition:service:region:account-id:resource-type:resource-id
Partition
- aws: AWS Regions
- aws-cn: China Regions
- aws-us-gov: AWS GovCloud (US) Regions
Service
- S3
- STS
- QuickSight
- IAM
Region
- us-east-1
- us-west-1
- eu-west-1
Account ID
- Accountに付与される一意の数字。
- 例:197674874429
Resource Type
- user (IAM)
- assumed-role
- federated-user
Resource ID
- IAMのユーザー名
- Bucket名
- Assumed Role名
IAMユーザーのARNの例
以下はIAMユーザーのARNの例。
arn:aws:iam::197674874429:user/JohnDoe
以下は上記のARNの内訳。
- Partition: aws
- Service: IAM
- Region: IAMはグローバルなため空白
- Account ID: 197674874429
- Resource Type: IAM User
- Resource ID: JohnDoe
Assumed RoleのARNの例
以下はAssumed RoleのARNの例。
arn:aws:sts::197674874429:assumed-role/AWSServiceRoleForAutoScaling/AutoScaling
以下は上記のARNの内訳。
- Partition: aws
- Service: STS
- Region: STSはグローバルなため空白
- Account ID: 197674874429
- Resource Type: Assumed Role
- Resource ID: AutoScaling
CloudTrail
実行されたAPIの情報を記録する。APIのリクエストのみならず、その実行結果も記録される。
例えば、EC2インスタンスの作成と開始といったイベントはCloudTrailに記録される。ただし、EC2のインスタンス内で起きたイベントはCloudTrailに記録されない。
90日までのデータは無料で保管される。90日間以上のデータを保管したい場合は、別途Trailをセットアップする必要がある。(後述)
CloudTrailに記録されるイベントは以下の2種類に分けられる。
Management Event
- リソース (S3 Bucket、IAMユーザー、仮想マシン等)の作成/更新/削除/開始/停止、情報照会のイベント。
- デフォルトで記録される。
Data Event
- S3, Lambda, RDSなどのデータへのアクセスに関するイベント。
- デフォルトでは記録されない。
- 記録するにはTrailを設定して、記録したいデータ元 (S3, Lambda, RDSなど)を指定しなければならない。
Trailのセットアップ
CloudTrailは最大で90日間のログまでしか保管されない。90日間以上のログを保管したい場合はCloudTrailのログの保管先となるS3 Bucketを指定する必要がある。これがTrailのセットアップである。
また、Trailをセットアップすることで先述したData Eventも保管することができる。
注意すべきCloudTrailのフィールド
- eventTime: イベントの発生時刻。UTC表示。
- userIdentity: 誰が(何が)イベントを引き起したかを記録する。(ユーザー名、Role、STS tokenなど)以下はuserIdentityの例。
- Root: 特権ユーザーであるRoot Accountによってイベントが引き起こされたことを示す。
- IAM User: ローカルのIAMユーザーによってイベントが引き起こされたことを示す。
- AssumedRole: Accountやユーザー、サービスに紐づいているIAM Roleによってイベントが引き起こされたことを示す。
- FederatedUser: フェデレーション認証を介して発行された一時トークンによってイベントが引き起こされたことを示す。
- AWSAccount: 外部のAWSのアカウントによってイベントが引き起こされたことを示す。Organizationを跨ぐRoleが使用された場合もAWSAccountとして記録される。
- AWSService: AWSサービスによってイベントが引き起こされたことを示す。
- eventSource: イベントを生成したAWSのサービスを記録する。Microsoft 365のWorkloadのようなもの。
- eventName: 通常、APIの名前が記録される。
- awsRegion: APIを処理したRegionが記録される。
- sourceIPAddress: イベントをリクエストしたIPアドレスが記録される。
- ARN: Amazon Resource Name。 認証に使用されたユーザー名、Role、STS tokenなどのフルネームが記録される。
- userAgent: ユーザーエージェントを記録する。リクエストにAWSコンソールが使われたか、APIが使われたか、あるいはブラウザが使われたかを判断できる。SDKやCLIからリクエストが送られた場合、OSとそのバージョンも併せて記録される。以下はユーザーエージェントの例。
- signin.amazonaws.com: コンソールからのログイン
- console.amazonaws.com: WebコンソールからのAPI要求
- lambda.amazonaws.com: LambdaからのAPI要求
- aws-cli: AWS-CLIを使用
- その他のWebブラウザ: ブラウザから Webコンソールへアクセス
- requestParameters: API要求時に渡されたパラーメータをJSON形式で記録する。
- responseElements: API要求に対する応答内容をJSON形式で記録する。
- eventID: イベントに付与される一意の識別子。
- eventType: イベントの種類を記録する。大抵の場合はAPI。
- resources: APIによってアクセスされた、あるいは影響を受けたリソースをJSON形式で記録する。
- sessionCredentialFromConsole: リクエストがAWSコンソールから送信されたか否かを記録する。
コンソールへのアクセスが発生した際に注視すべきCloudTrailのフィールド
- ARN: どのアカウントがログインしたかを表す。
- eventTime: ログインが発生した日時を表す。
- userAgent: ログインに使用されたブラウザを表す。
- sourceIPAddress: ログインの送信元を表す。
- responseElements: ログインが成功したか否かを表す。
- MFAUsed: ログインの際に多要素認証が使用されたか否かを表す。
CloudTrail Portal
CloudTrailのログを検索するためのWebポータル。
- サービスの作成、削除、更新などのイベントを閲覧できる。
- ログをCSVまたはJSON形式でエクスポートできる。
- S3の同期イベントや先述したData Eventは閲覧できない。
- Trailのセットアップの有無にかかわらず、ポータルからは90日間分のログしか閲覧できない。
API / Access Key
以下はAccessキーの書式の例。
AKIAUOLAJ2BLOJUMYJZM
先頭4文字のAKIAはAccessキーを意味し、続くUOLAJ2BLOJUMYJZMは一意の識別子である。
IAMにてユーザーやグループ、ロール、ポリシー、インスタンスプロファイル、サーバー証明書等が作成されると、それぞれに一意の識別子が与えられる。そのうち、先頭の4文字はリソースの種別を表す。
- ABIA: AWS STS service bearer token
- ACCA: Context-specific credential
- AGPA: User group
- AIDA: IAM User
- AIPA: Amazon EC2 instance profile
- AKIA: Access key
- ANPA: Managed policy
- ANVA: Version in a managed policy
- APKA: Public key
- AROA: Role
- ASCA: Certificate
- ASIA: Temporary (AWS STS) access key IDs
上記のうち、押さえておくべきはAIDA, AKIA, ASIAの3つである。
AIDAはローカルのIAMユーザーがリクエストを行ったことを意味する。そのユーザーのAPIキーが作成され、CLIやSDKで使用されていることを意味するものではない。
AKIAはユーザーまたはロールのAPIキーを使用してCLIやSDKからリクエストを行ったことを意味する。
ASIAはAWS STSの一時トークンを使用してリクエストを行ったことを意味する。
APIキーが生成された際に注視すべきCloudTrailのフィールド
- ARN: キーを生成したアカウントを表す。
- eventTime: キーが生成された日時を表す。
- eventName: キー生成のイベントは
CreateAccessKeyと表される。 - userAgent: キーの生成に使用されたサービス(API, CLI, コンソール)を表す。
- sourceIPAddress: リクエストの送信元を表す。
- responseElements: リクエストの結果 (キーの生成に成功したか否か)を表す。responseElementsにはさらに以下のフィールドが含まれている。
- userName: キーに対応するIAMユーザーを表す。
- accessKeyId: 生成されたキーの名前を表す。
- status: キーの状態を表す。(Active or Disabled)
- createDate: キーが生成された日時を表す。
生成されたキーによって引き起こされたイベントを調べたい場合は、accessKeyIdに記されているキーの名前でフィルターをかける。
応答内容にクレデンシャル情報を含むAPIの一覧
以下のAPIを実行すると応答としてクレデンシャル情報が返ってくる。
chime:CreateApiKey
codepipeline:PollForJobs
cognito-identity:GetOpenIdToken
cognito-identity:GetOpenIdTokenForDeveloperIdentity
cognito-identity:GetCredentialsForIdentity
connect:GetFederationToken
connect:GetFederationTokens
ecr:GetAuthorizationToken
gamelift:RequestUploadCredentials
iam:CreateAccessKey
iam:CreateLoginProfile
iam:CreateServiceSpecificCredential
iam:ResetServiceSpecificCredential
iam:UpdateAccessKey
lightsail:GetInstanceAccessDetails
lightsail:GetRelationalDatabaseMasterUserPassword
rds-db:connect
redshift:GetClusterCredentials
sso:GetRoleCredentials
mediapackage:RotateChannelCredentials
mediapackage:RotateIngestEndpointCredentials
sts:AssumeRole
sts:AssumeRoleWithSaml
sts:AssumeRoleWithWebIdentity
sts:GetFederationToken
sts:GetSessionToken
CloudTrailによる脅威ハンティングの例
Impossible travel
短時間でユーザーの位置情報が大きく変わっていないか?
日本のIPアドレスからアクセスしていたのに、5分後にはナイジェリアのIPアドレスからアクセスしていた等。
不審な送信元IPアドレスからのアクセス
日本にいるユーザーなのに、アメリカのIPアドレスからアクセスしている等。
APIキーやAssumed Roleを使用したコンソールへのアクセス
通常、コンソールへアクセスするのはIAMユーザーやRootユーザーのみであり、APIキーやAssumed Roleを使用したログインは稀。
新規アカウントの作成
規模の大きい組織ではあまり役に立つ指標ではないかもしれない。
短時間で大量の仮想マシンが作成された
特にGPUを内蔵している仮想マシンが大量に作成された場合、マイニング目的の攻撃活動である可能性が高い。
CloudTrail Lake
CloudTrailを始めとしたAWS関連のログやAWS以外の外部サービスのログを保管するデータレイク。
SQL風のクエリを使ってデータを検索できる。
SELECT
eventID, eventName, eventSource, eventTime, userIdentity.arn AS user
FROM
b6e5509-31f5-4e26-afe0-dcb3da691bf9
WHERE
userIdentity.arn LIKE '%john%'
AND eventTime > '2025-05-14 00:00:00' AND eventTime < '2025-05-22 00:00:00'
GuardDuty
- AWSの脅威検知サービス (有料)
- CloudTrailログ、VPC (Virtual Private Cloud)のフローログ、DNSのクエリーログ、EKS (Amazon Elastic Kubernetes Service) の監査ログなど、複数のログを監視・分析する。
- 機械学習、異常検知、脅威インテリジェンス等を駆使して、異常なAPI要求、不正アクセス試行、リソースの侵害などを検知する。
- GuardDutyは有効化された日時から先のログのみ監視・分析する。過去のログを遡って分析することはしない。
EC2 (Elastic Compute Cloud)
Amazonが提供する仮想マシン。初期アカウントの作成とIPアドレスの付与はAWSが行う。(パブリックIPとするかプライベートIPとするかはユーザーが選択)
以下の設定はユーザーが決める。
- EC2インスタンスの実行頻度
- CPU, RAM, ストレージの割り当て
- EC2インスタンスのネットワーク上の配置
EC2の種類
EC2のinstanceTypeの頭文字はインスタンスの種類を表す。
以下はinstanceTypeの例。
t2.micro
汎用インスタンス
- MAC: OS X
- T: Burstable。状況に応じてリソースを拡張できる。
- M: Most Scenarios。最も汎用的な設定のインスタンス。
- A: ARMプロセッサーを搭載しているインスタンス。
コンピューティングに最適化されたインスタンス
- C: メモリよりもCPUを重視( 2GBのRAMにつき1つのCPU)。
メモリに最適化されたインスタンス
- R: RAM。CPUよりもRAMを重視。
- X: Extra-Large Memory。CPUよりもRAMを重視。
- Z: High Frequency。超高速のRAMアクセス。
GPU, FPGA搭載のインスタンス
- P: GPUを搭載。
- G: GPUを搭載。
- F: FPGAを搭載。
マイニング目的で悪用されがち。
ストレージに最適化されたインスタンス
- I: IOを重視。
- D: Dense Storage。大容量のストレージ (HDD)。
- H: Large Local Storage。大容量のストレージ (HDD)。バランスを重視しているため、Dほど大容量ではない。
HPCに最適化されたインスタンス
- HPC: High Performance Computing
Regionに用心
EC2はリージョナルなサービスである。どういう意味かというと、EC2のインスタンスは世界のどこかしらのデータセンター内で稼働しているということである。
EC2インスタンスを調査する際は、どのインスタンスがどのリージョン(地域)で稼働しているかを正しく把握している必要がある (ひとつのリージョンのみに注目していると、ほかのリージョンで発生した侵害を見落とす恐れがある)。
EC2 Global View
各AWSリージョンに存在しているリソースの一覧の確認やリソースの検索ができる。
以下のことが確認できる。
- 各リージョンで稼働中のEC2インスタンスの数。
- 各リージョンに存在するVPC (Virtual Private Cloud)の数。
- 各リージョンに存在するサブネットの数。
- 各リージョンに作成されたsecurity groupの数。
- 各リージョンに存在するEBSボリュームの数。
- 各リージョンで定義されているAuto Scaling groupの数。
EC2 のインスタンスが起動した際に注視すべきCloudTrailのフィールド
- ARN: EC2インスタンスの作成・起動をリクエストしたアカウントを表す。
- accessKeyId: リクエストに使用されたAPIキーを表す。
- eventSource: EC2関連のイベントは常に
ec2.amazonaws.comと記録される。 - eventName: EC2インスタンスの作成は
RunInstancesと記録される。 - awsRegion: インスタンスが稼働しているリージョンを表す。
- sourceIPAddress: リクエストを送ったIPアドレスを表す。
- userAgent: リクエストに使用されたサービス(API, CLI, コンソール)を表す。EC2 web consoleが使用された場合、
console.ec2.amazonaws.comと記録される。 - imageId: インスタンスの識別子 (例:
ami-037ce2fddcbfdbf52)。先頭に必ずAMI(Amazon Machine Image) とつく。AMIとはVMwareのVMXファイルに相当するもので、仮想マシンの起動に必要な設定データが含まれている。 - keyName: SSHの鍵名を表す。
- instanceType: インスタンスの種類を表す。以下は例
t2.micro: T (Burstable) タイプのインスタンス。g4ad.4xlarge: Gタイプ。GPU搭載のインスタンス。
Lightsail
Amazonが提供するVritual Private Server (VPS)。
Lightsail関連のイベントはEC2 Global Viewやフローログに記録されない。故に攻撃者に悪用されがち。
Lightsailのイベントを確認する方法はLightsail consoleにアクセスするか、CloudTrailログにてCreateInstanceイベントの有無を確認するのみである。
EBS (Elastic Block Store)
EC2インスタンスのための仮想ボリューム。EC2インスタンスにはOS用のEBSが最低ひとつは必要だが、各インスタンスが使用できるEBSの数に制限はない。
EBSの種類
EBSには以下の3種類がある。
- 汎用SSD: gp3, gp2。定番かつ最も汎用的なタイプ。
- IOPS特化のディスク (SSD): io2, io1。高速転送、高スループットを保証。
- HDDボリューム:st1, sc1。頻繁にディスクへのアクセスが発生したり、スループットが集中するような用途に向いている。
EBSがEC2インスタンスにアタッチされた際に注視すべきCloudTrailのフィールド
EC2インスタンスにアタッチされたEBSの情報は、instanceTypeフィールド配下のblockDeviceMappingフィールドに記録される。
- deviceName: EBSボリュームへのパスを表す。例:
/dev/xvda - volumeSize: EBSボリュームのサイズを表す。例:
8(GB) - volumeType: EBSボリュームの種類を表す。例:
gp2
スナップショット
スナップショットは、ハイパーバイザーを介して(スナップショット時の)ディスク状態をディスクイメージとして作成する。AWSでスナップショットを作成すると、初回のスナップショットのみ全てのデータを含んでおり、次回以降のスナップショットは前回のスナップショットとの差分データのみを含む。
AWS CLIを用いてのスナップショットの作成
AWS CLIを用いてスナップショットを作成するには以下のようにする。
aws ec2 create-snapshot --volume-id <volumeid> --description "creating first snapshot"
スナップショットが作成されると、スナップショットを識別するためのSnapshotIdが付与される。
スナップショットのダウンロード
スナップショットのダウンロードにはDirectBlockAccess APIが使える。このAPIは各スナップショットの各ブロックからデータをダウンロードする。
また、AWSはcoldsnapというスナップショットのアップロード・ダウンロードを行うツールを提供している。
以下はスナップショットをダウンロードするコマンドの例。
coldsnap --region <region> download <snapshot id> disk.img
スナップショットが作成された際に注視すべきCloudTrailのフィールド
- userIdentity: スナップショットを作成したユーザーを表す。
- eventSource: イベントを生成したAWSのサービスを表す。
- eventName: スナップショットの作成は
CreateSnapshotと記録される。 - awsRegion: スナップショットが保存されるリージョンを表す。
- userAgent: リクエストに使用されたサービス(API, CLI, コンソール)を表す。CLIからリクエストが送られた場合、ユーザーエージェントの末尾にスナップショット作成に使われたコマンドが記録される。例:
aws-cli/2.1.32 Python/3.8.8 Windows/10 exe/AMD64 prompt/off command/ec2.create-snapshot - volumeId: スナップショットされたEBSの識別子。例:
vol-086eb487a26893eff - snapshotId: スナップショットの識別子。スナップショットとやり取りする際にはこのIDが必要。例:
snap-096a35e714244ea98 - encrypted: スナップショットが暗号化されているか否かを表す。復号鍵がAWSのキー管理サービスに保存されており、アカウントが鍵へアクセスできる場合、スナップショットのデータは透過的に復号される。
EFS (Elastic File Store)
AWSが提供するNFS (Network File System)。EBSが専用のブロックストレージを使用していて、一度にアクセスできるインスタンスがひとつなのに対して、EFSは複数のインスタンスが同時アクセスすることができる。
EFSがマウントされた際に注視すべきCloudTrailのフィールド
- type: リクエストを送ったアカウントの種類を表す (
Root,IAMUser,AssumedRole)。 - arn: リクエストに使用されたアカウントを表す。
- invokedBy: リクエストに使用されたAWSサービスを表す。例:
elasticfilesystem.amazonaws.com,AWS Internal - awsRegion: EFSが配置されているリージョンを表す。
- userAgent: リクエストに使用されたサービスを表す。例:
console.amazonaws.com,user_agent,elasticfilesystem.amazonaws.com,elasticfilesystem - eventName: EFSがマウントされると、
CreateNetworkInterfaceイベントが記録される。create EFSのような分かりやすいイベント名ではないので注意。 - vpcId: VPC (Virtual Private Cloud)の識別子。EFSとのネットワーク通信ログを調べたい場合は、このIDが必須 (IDがないと該当のログがどこにあるか探せない)。
- privateIpAddress: EFSに付与されるIPアドレスを表す。
CloudWatch Logs Agent
EC2インスタンスのログをAWSに取り込みたい場合は、CloudWatch Logs Agentを利用する。以下のようなログを取り込める。
- Syslog
- イベントログ
- Apache ログ
- IIS ログ
取り込んだログはCloudWatch Logs上で検索できる。あるいはS3バケットにエクスポートしてAthenaなどで検索することも出来る。
VPC (Virtual Private Cloud)
ネットワーク通信に必要なリソースを提供する。VPCには以下のリソースが含まれる。
- Subnets: AWSのIPアドレス空間内にある個別のネットワークセグメントのこと。オンプレミスネットワークにおけるサブネットと同様の概念。
- EC2 VMs: EC2のネットワークインターフェースは、VPCに割り当てられたサブネットに割り当てる必要がある。同じVPC内にあるEC2インスタンス同士は、デフォルトで通信可能(ルーティングを追加設定する必要なし)。
- Network Security groups: サブネット内外への通信を制御するファイヤーウォールのようなもの。
- Internet gateways: VPCとインターネットとの通信のためのゲートウェイ。このゲートウェイが無い場合、VPCからインターネットへの通信も、インターネットからVPCへの通信も不可能。
- Load balancers: AWSが提供する負荷分散装置。外部ネットワークからの通信を複数のインスタンスに振り分けることで、大量のトラフィックを処理する。
- WAF: Web Application Firewall。Webアプリケーションへの不正な通信を監視してフィルターする。
VPC Subnets
VPCにはプライベートサブネットとパブリックサブネットの2種類がある。
プライベートサブネットはインターネットとの直接通信はできない。パブリックサブネットはインターネットとの通信が可能。
各サブネットは各々のIPアドレス空間を保有しており、個別のセキュリティポリシーを適用できる。
ルーティングを設定することで異なるVPC同士も通信できる。デフォルトでは各VPCは隔離されている。
各VPCは最大で200サブネットまでサポート可能。
Internet Gateways
VPCがインターネットと通信するためにはゲートウェイを設定する必要がある。Internet GatewaysはVPCのパブリックサブネットからインターネットへの通信を可能にする。また、外部向けに公開されているリソースへのインターネット側からのアクセスも可能にする。Internet Gatewaysはデフォルトゲートウェイの役割も果たす。
NATゲートウェイではないので、通信のログにはサブネットと通信を行った実際の外部IPアドレスが記録される。
Internet Gatewaysが設定されていないと、サブネットがインターネットと直接通信を行うことはできない。
もしプライベートサブネットにNATゲートウェイを設定した場合、サブネットからインターネットへの通信はできるが、インターネットからサブネットへアクセスすることはできない。
Network Security Groups
- ステートフル (戻りトラフィックは自動的に許可される)
- EC2インスタンスに適用される。
- 各EC2インスタンスにはSecurity Groupが適用されていなければならない。ユーザーから特に指定が無い場合は、AWSが作成する (その場合、SSH通信はデフォルトで許可される)。
- どのようなサービスの通信 (http, https, ssh, etc)を許可するかを指定する。明示的に許可されていない通信は拒否される。
- サービス (http, https, ssh, etc)が許可されている場合、特定のIPアドレスから、そのサービスへの通信を遮断するような設定はできない。その場合は後述するNetwork ACLsを使う。
- Network Security Groupsへの変更は(インターフェースをリセットしない限り)すでに確立済の通信には適用されない。
- Network Security Groupsが通信を許可したか否かはVPCフローログに記録される。
Network Access Control Lists (ACLs)
- ステートレス
- サブネットに適用される。
- 遮断ルールを適用できる(特定のIPアドレスからの通信を拒否できる)
- 特定のIPアドレスを拒否するルールを適用した場合、確立済の通信であっても直ちに遮断できる。
- Network ACLsが通信を許可したか否かはVPCフローログに記録される。
Load Balancers
AWSが提供するロードバランサーには以下の4種類がある。
Network Load Balancer
(OSI参照モデルの)レイヤー4で稼働する。IPアドレスやポートに基づいて通信のルーティングを行う。複数の VPC 間で負荷を分散する。
Classic Load Balancer
レイヤー4とレイヤー7で稼働する。レガシー・サービス。原則的に1つのVPCのみで稼働する。
Application Load Balancer
レイヤー7で稼働する。HTTP(S)通信を理解し、ホスト名、パス、クエリー文字列、ヘッダー情報に基づいてルーティングを行う。HTTP(S)のほかに以下のアプリケーション通信をサポートする。
- WebSocket
- gRPC
AWSのWAFサービスとも連携可能。
Gateway Load Balancer
レイヤー3で稼働する。サードパーティーの仮想アプライアンスを介してルーティングを行う。
ネットワーク上にロードバランサーが配置されている場合、VPCのフローログにはロードバランサーのIPアドレスが記録される。実際に通信を行った外部のIPアドレスを確認したい場合は、ロードバランサーのログを見なければならない(ロードバランサーのログはデフォルトで有効化されていない)。
フローログに実際の外部IPアドレスを記録したい場合は、以下の手段がある。
- Network Load BalancerにてProxy Protocolを有効化する。
- Application Load BalancerやClassic Load BalancerにてX-Forwarded-For ヘッダーを記録する。
VPC Flow Logs
ネットワーク通信のサマリーを記録する。記録される情報は以下の通り。
- 送信元・宛先IPアドレス
- 送信元・宛先ポート
- 通信サイズ
- 通信の開始および終了時間
フローログは以下の箇所でいつでも有効化できる。
- VPC: VPCで発生した全ての通信のサマリーを取得する。
- サブネット:サブネットで発生した全ての通信のサマリーを取得する。
- ネットワークインターフェース: インスタンス上のネットワークインターフェースで発生した全ての通信のサマリーを取得する。
フローログは1~10分間隔でS3バケットに保存される (このインターバルはユーザーが設定可能)。
また、CloudWatchに転送することもできる。
VPC Flow Logのフィールド
- version: フローログのバージョンを表す。(例:
2) - account-id: ログを生成したAWSのアカウントを表す。(例:
305681518678) - interface-id: アクセスされた仮想ネットワークインターフェースを表す。(例:
eni-06fa0119bda73bdc5) - srcaddr: 送信元IPアドレスを表す。
- dstaddr: 宛先IPアドレスを表す。
- dstport: 宛先ポートを表す。
- srcport: 送信元ポートを表す。
- protocol: プロトコル番号を表す。(例:
6, TCPの場合) - packets: パケット数を表す。
- bytes: バイト数を表す。
- start: 通信の開始時刻をUNIXタイムスタンプ形式で表す。
- end: 通信の終了時刻をUNIXタイムスタンプ形式で表す。
- action: Network Security Groupがどのようなアクションを取ったかを表す。(例:
ACCEPT) - log-status: ログの状態を表す。(例:
OK)
VPC Flow Logのカスタムフィールド
以下はユーザーが追加することのできるカスタムフィールドである。
- Vpc-id: アクセスされたネットワークインターフェースが存在しているVPCを表す。(例:
vpc-09edf30a76f46ad91) - Subnet-id: アクセスされたネットワークインターフェースが存在しているサブネットを表す。(例:
subnet-006107df3ed502ce2) - Instance-id: アクセスされたネットワークインターフェースが存在しているインスタンスを表す。
- Tcp-flags: TCPのフラグを表す。数値の見方についてはこちらを参照。(例:
18, SYN+ACK) - Type: 通信の種類を表す。(例:
IPv4,IPv6,EFA) - Pkt-srcaddr: 通信が NAT化されていた場合、真の送信元IPアドレスを表す。
- Pkt-dstaddr: 通信が NAT化されていた場合、真の宛先IPアドレスを表す。
- Region: アクセスされたネットワークインターフェースが存在しているリージョンを表す。(例:
us-east-1) - Az-id: availability zoneを表す。(例:
use1-az1) - Flow-direction: 通信の方向を表す。(ingress or egress)
- Traffic-path: (egress通信の場合)宛先ネットワークまでのパスの数を表す。
Route 53
AWSが提供するDNSサービスである。インシデント調査においては以下のログが有用。
DNS Zone Query Logging
使用しているAWSドメインへの名前解決要求を記録する。攻撃者が自ドメインに対してどのような名前解決要求を行ったかを確認できる。
Resolver Query Logging
Route 53でリゾルバ機能を有効化した場合、VPCで発生したあらゆる名前解決要求(と応答内容)が記録される。例えば、EC2が侵害された場合、そのインスタンスから送信された名前解決要求を確認することで以下のことが判明するかもしれない。
- C2サーバーのドメイン名
- DNSトンネリングを介したC2通信
- データ漏洩の有無(オンラインストレージなどへの名前解決要求はないか?)
DNSクエリーがキャッシュされた場合、キャッシュの有効期限が切れるまでは、次回以降のクエリーは記録されない。
DNS Zone Query LoggingもResolver Query Loggingもデフォルトでは有効化されていない。
S3 Buckets
Amazon S3とはAmazon Simple Storage Serviceの略で、AWSが提供するストレージサービスである。かつては設定ミス等で意図せずS3バケットにホストしているデータを外部に公開してしまう事例があとを絶たなかった。近年では新規に作成されたバケットはデフォルトでロックダウンされており、アクセスするためには認証をパスしなければならない。バケットを外部に公開するには、複数のセキュリティ設定を変更し、かつカスタムポリシーを適用しなければならない。
S3バケット名は一意でなければならなず、同じ名前のバケットは存在しない。バケットには誰でも任意の名前を付けることができるので、攻撃者がフィッシング目的で実在の企業に見せかけたバケット名を付けることも可能。
S3バケットのアクセス方法
S3バケットには以下の2通りの方法でアクセスできる。
AWS APIsyncやcpなどのAPIを実行してデータを取得できる。APIを介してS3バケットにアクセスした場合は、CloudTrailにログが残る (※TrailをセットアップしてS3のData Eventを記録するように設定していた場合)。
Webインターフェース
ブラウザを始めとしたWebインターフェースでバケットにアクセスした場合、CloudTrailにログは残らない。かわりにS3のサーバーログに記録が残る。ただし、サーバーログはデフォルトで有効化されていない。
S3バケットのアクセスレベル
S3バケットには以下のアクセスレベルを設定できる。
Public
誰でも認証無しでバケットにアクセスできる。
AWS User
AWSのユーザーなら誰でも(組織外のAWSユーザーでも)バケットにアクセスできる。
Org User
Organizationにサインインしているユーザーなら誰でもバケットにアクセスできる。
IAM Roles
特定のIAM Roleを有していれば、バケットにアクセスできる。IAM Roleによるアクセス制限を適用するには事前に以下の設定をする必要がある。
- IAM ロールポリシーにてS3バケットへのアクセスを許可する。
- S3バケットポリシーにてIAMロールへのアクセスを許可する。
Token
STSトークンが埋め込まれたURLを利用してバケットにアクセスする。トークンの有効期限が切れるとアクセスは無効になる。
S3バケットへのアクセスが発生した際に注視すべきCloudTrailのフィールド
先述したようにAWSのAPI・CLIを介してS3バケットにアクセスした場合、CloudTrailにログが残る。(※TrailをセットアップしてS3のData Eventを記録するように設定していた場合)
- userIdentity: リクエストを送ったユーザー情報を表す。
- eventName: S3のオペレーションを表す。(例:
GetObject) - sourceIpaddress: リクエストの送信元IPアドレスを表す。
- userAgent: リクエストに使用されたツールやOSを表す。
- requestParameters: アクセスされたバケット名やリソースへのフルパスを表す。
S3バケットへのアクセスが発生した際に注視すべきサーバーログのフィールド
先述したようにブラウザを始めとしたWebインターフェースでバケットにアクセスした場合、サーバーログに記録が残る。(※サーバーログはデフォルトで有効化されていない)
- Bucket Owner: アクセスされたバケットを所有しているユーザーIDを表す。
- Bucket: アクセスされたバケット名を表す。
- Time: リクエストが処理された日時を表す。
- Remote IP: リクエストを送ったIPアドレスを表す。
- Requester: リクエストが認証されていた場合、アクセスに使用されたAWSアカウント、APIキー、ロール等を表す。
- Request Id: リクエストを識別するための識別子を表す。
- Operation: S3のオペレーションを表す。(例:
REST.GET.OBJECT) - Key: アクセスされたリソース名を表す。
- Request-URI: リクエストされたURIを表す。(例:
GET /file.doc HTTP/1.1) - HTTP Status: HTTPの応答コードを表す。
- Error Code: (エラーが発生した場合) エラーコードを表す。
- Bytes Sent: リクエストへの応答として送信されたバイト数を表す。
- Object Size: リクエストされたリソースの合計サイズを表す。
- Total Time: サーバーがリクエストを完了するまでに要した時間を表す。
- Turnaround Time: AWSがリクエストを処理するまでに要した時間を表す。
- Referrer: リクエストされたバケットのリンク元を表す。
- User-Agent: ユーザーエージェントを表す。
- Authentication Type: リクエストが認証されていた場合、認証の種類を表す。
- Host Header: バケットをホストしているホスト名を表す。(例:
<hostname>.s3.amazonaws.com)
AWS Glue
GlueはCloudTrailのログが保存されているS3バケットを巡回して、収集したログを仮想テーブルに変換する。この仮想テーブルはAthena (後述)の検索に使用される。
AWS Athena
AthenaはS3バケットに保存されているデータを検索するサービスである。
先述したGlueによって作成された仮想テーブルに対してSQL風のクエリーを送ることでデータを検索する。
Amazon Detective
Amazonが提供する脅威ハンティングサービス。以下のログをもとにデータの統計を取り、異常なユーザーアクティビティや不審な通信を洗い出す。
- GuardDutyのアラート
- VPCのフローログ
- CloudTrailのログ
Amazon Detectiveは有効化された日時から先のログのみ監視・分析する。過去のログを遡って分析することはしない。
AWS Systems Manager (SSM)
AWS Systems Manager (SSM)を利用するとAWS内のシステムに対して、任意のコマンドやスクリプトを管理者権限で実行できる。
注意すべきAWS SSMのコマンド
- Describe-instance-information: SSMによって管理されているシステムの一覧を表示する。この一覧に載っているシステムに対しては後述する
Send-command等で任意のコマンドが実行できる。 - Send-command: 対象のシステムに対して任意のコマンドを管理者権限で実行する (システムにインストールされているSSMのエージェントは管理者権限で実行されているため)。
- Start-session: 対象のシステムとの対話シェルを管理者権限で開始する。
- Resume-session: 既存の対話シェルを再開する。
- Start-automation-execution: 定義済のrunbookを実行する。
AWS SSMのログの保存場所
セキュリティ上の理由から、CloudTrailにはSSMによって実行されたコマンドの詳細は記録されない。
実行されたコマンドの詳細を知りたい場合は、コマンドの実行先のシステムのSSMエージェントのログを調べる。
Windowsシステムのログの保存場所は以下の通り。
%PROGRAMDATA%\Amazon\SSM\Logs\amazon-ssm-agent.log%PROGRAMDATA%\Amazon\SSM\Logs\errors.log
Linuxシステムのログの保存場所は以下の通り。
/var/log/amazon/ssm/amazon-ssm-agent.log/var/log/amazon/ssm/errors.log