Amazon GuardDuty Malware Protection for Amazon S3でマルウェア検知後にメールで通知してみた
Amazon GuardDuty Malware Protection for Amazon S3でマルウェア検知のテストを行う機会があったのでブログに残します。
やること
以下の構成を作成してS3バケット内にEICAR テストファイルをアップロードした際にAmazon SNS経由でメール通知されることを確認します。
Amazon GuardDuty Malware Protection for Amazon S3って何?という方は以下のブログをご一読ください。
この機能を有効化すると対象のS3バケットにアップロードされたオブジェクトに対してスキャンを行いマルウェアなど悪意のあるファイルを見つけることができる機能です。
リソース作成
リソースの作成は以下のCloudFormationテンプレートで行いました。
AWSTemplateFormatVersion: "2010-09-09"
Description: GuardDuty Stack
Parameters:
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
MailAddress:
Type: String
Resources:
# ------------------------------------------------------------#
# S3
# ------------------------------------------------------------#
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub s3-malware-test-${AWS::AccountId}-${AWS::Region}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
# ------------------------------------------------------------#
# SNS
# ------------------------------------------------------------#
SNSTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: !Ref MailAddress
Protocol: email
TopicName: sns-malware-test
SNSTopicPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Id: __default_policy_ID
Statement:
- Sid: __default_statement_ID
Effect: Allow
Principal:
AWS: '*'
Action:
- 'SNS:GetTopicAttributes'
- 'SNS:SetTopicAttributes'
- 'SNS:AddPermission'
- 'SNS:RemovePermission'
- 'SNS:DeleteTopic'
- 'SNS:Subscribe'
- 'SNS:ListSubscriptionsByTopic'
- 'SNS:Publish'
Resource: !Ref SNSTopic
Condition:
StringEquals:
'AWS:SourceOwner': !Sub ${AWS::AccountId}
- Sid: 'EventBridge Use'
Effect: Allow
Principal:
Service: events.amazonaws.com
Action: 'sns:Publish'
Resource: !Ref SNSTopic
Topics:
- !Ref SNSTopic
# ------------------------------------------------------------#
# IAM
# ------------------------------------------------------------#
GuardDutyRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "role-guardduty-malware-test"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Condition:
StringEquals:
aws:SourceAccount: !Sub ${AWS::AccountId}
Action: "sts:AssumeRole"
Effect: "Allow"
Principal:
Service: "malware-protection-plan.guardduty.amazonaws.com"
GuardDutyPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: policy-guardduty-malware-test
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "events:PutRule"
- "events:DeleteRule"
- "events:PutTargets"
- "events:RemoveTargets"
Resource:
- !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*"
Condition:
StringLike:
events:ManagedBy: "malware-protection-plan.guardduty.amazonaws.com"
- Effect: "Allow"
Action:
- "events:DescribeRule"
- "events:ListTargetsByRule"
Resource:
- !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*"
- Effect: "Allow"
Action:
- "s3:PutObjectTagging"
- "s3:GetObjectTagging"
- "s3:PutObjectVersionTagging"
- "s3:GetObjectVersionTagging"
Resource:
- !Sub "${S3Bucket.Arn}/*"
- Effect: "Allow"
Action:
- "s3:PutBucketNotification"
- "s3:GetBucketNotification"
Resource:
- !GetAtt S3Bucket.Arn
- Effect: "Allow"
Action:
- "s3:PutObject"
Resource:
- !Sub "${S3Bucket.Arn}/malware-protection-resource-validation-object"
- Effect: "Allow"
Action:
- "s3:ListBucket"
Resource:
- !GetAtt S3Bucket.Arn
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:GetObjectVersion"
Resource:
- !Sub "${S3Bucket.Arn}/*"
Roles:
- !Ref GuardDutyRole
# ------------------------------------------------------------#
# GuardDuty
# ------------------------------------------------------------#
GuardDuty:
DependsOn: GuardDutyPolicy
Type: AWS::GuardDuty::MalwareProtectionPlan
Properties:
ProtectedResource:
S3Bucket:
BucketName: !Ref S3Bucket
Role: !GetAtt GuardDutyRole.Arn
# ------------------------------------------------------------#
# EventBridge
# ------------------------------------------------------------#
EventBridgeRule:
Type: AWS::Events::Rule
Properties:
Name: rule-guardduty-malware-protection
EventPattern:
source:
- aws.guardduty
detail-type:
- GuardDuty Malware Protection Object Scan Result
detail:
scanResultDetails:
scanResultStatus:
- THREATS_FOUND
Targets:
- Id: Email
Arn: !Ref SNSTopic
77行目~147行目でGuardDutyが使用するIAMロールとIAMポリシーを作成しています。
こちらのIAMポリシーは以下のドキュメントに記載されているポリシーを参考にしました。
ドキュメントでは「kms:GenerateDataKey」と「kms:Decrypt」を許可するような形となっていますが、今回作成するS3バケットではSSE-S3を使用しているため、IAMポリシーで許可していなくても使用が可能です。
ちなみにIAMロールにS3へのListBucketを許可していないと以下のようなエラーが発生してリソースの作成に失敗します。
The request was rejected because provided IAM role does not have the required permissions to validate S3 bucket ownership.
152行目~159行目でAmazon GuardDuty Malware Protection for Amazon S3を有効化しています。
マルウェア検知時にオブジェクトにタグを付ける設定などもあるのですが、今回は設定せず、シンプルに有効化のみ行っています。
164行目~179行目でEventBridgeルールを作成しています。
マルウェアを検知すると以下のドキュメントに記載されているイベントが発行されます。
{
"version": "0",
"id": "72c7d362-737a-6dce-fc78-9e27a0171419",
"detail-type": "GuardDuty Malware Protection Object Scan Result",
"source": "aws.guardduty",
"account": "111122223333",
"time": "2024-02-28T01:01:01Z",
"region": "us-east-1",
"resources": [arn:aws:guardduty:us-east-1:111122223333:malware-protection-plan/b4c7f464ab3a4EXAMPLE],
"detail": {
"schemaVersion": "1.0",
"scanStatus": "COMPLETED",
"resourceType": "S3_OBJECT",
"s3ObjectDetails": {
"bucketName": "amzn-s3-demo-bucket",
"objectKey": "APKAEIBAERJR2EXAMPLE",
"eTag": "ASIAI44QH8DHBEXAMPLE",
"versionId" : "d41d8cd98f00b204e9800998eEXAMPLE",
"s3Throttled": false
},
"scanResultDetails": {
"scanResultStatus": "THREATS_FOUND",
"threats": [
{
"name": "EICAR-Test-File (not a virus)"
}
]
}
}
}
そのため、EventBridgeルールのイベントパターンでは「scanResultStatus」が「THREATS_FOUND」の時に一致するように以下のようにしています。
{
"detail-type": ["GuardDuty Malware Protection Object Scan Result"],
"source": ["aws.guardduty"],
"detail": {
"scanResultDetails": {
"scanResultStatus": ["THREATS_FOUND"]
}
}
}
デプロイは以下のAWS CLIコマンドを使用します。
aws cloudformation create-stack --stack-name CloudFormationスタック名 --template-body file://CloudFormationテンプレートファイル名 --parameters ParameterKey=MailAddress,ParameterValue=通知先のメールアドレス --capabilities CAPABILITY_NAMED_IAM
動作確認
リソースの作成が完了したらEICAR テストファイルをダウンロードしてS3へアップロードします。
curl https://secure.eicar.org/eicar.com.txt -o eicar.com.txt
aws s3 cp eicar.com.txt s3://s3-malware-test-アカウントID-ap-northeast-1
正常に設定が完了していると以下のメールが届いていることが確認できます。
{
"version": "0",
"id": "11111111-1111-1111-1111-111111111111",
"detail-type": "GuardDuty Malware Protection Object Scan Result",
"source": "aws.guardduty",
"account": "111111111111",
"time": "2024-12-19T07:52:21Z",
"region": "ap-northeast-1",
"resources": [
"arn:aws:guardduty:ap-northeast-1:111111111111:malware-protection-plan/11111111111111111111"
],
"detail": {
"schemaVersion": "1.0",
"scanStatus": "COMPLETED",
"resourceType": "S3_OBJECT",
"s3ObjectDetails": {
"bucketName": "s3-malware-test-111111111111-ap-northeast-1",
"objectKey": "eicar.com.txt",
"eTag": "11111111111111111111",
"versionId": null,
"s3Throttled": false
},
"scanResultDetails": {
"scanResultStatus": "THREATS_FOUND",
"threats": [
{
"name": "EICAR-Test-File (not a virus)"
}
]
}
}
}
「objectKey」も含まれているので対象ファイルも簡単に検索ができます。
さいごに
Amazon GuardDuty Malware Protection for Amazon S3でマルウェア検知時の通知設定を試してみました。
今回は通知のみの設定ですが、Lambdaなどに連携すればファイルの削除や隔離といったことも可能なはずなので、機会があれば試してみたいと思います。