Amazon GuardDuty Malware Protection for AWS Backup でバックアップデータのマルウェアスキャンを試してみた
はじめに
みなさん、バックアップからリストアするときに「このバックアップ、本当に安全なのかな」と気になったことはないでしょうか。
もしバックアップ取得時点で既にマルウェアが潜んでいたら、リストアしたときに感染が広がってしまいます。いわゆる「休眠マルウェア」の問題ですね。
昨年の re:Invent で、この対策として利用できる Amazon GuardDuty Malware Protection for AWS Backup という機能がリリースされています。
実際にバックアップデータに対してマルウェアスキャンを試してみます。
何が嬉しいのか
リストア前にバックアップの安全性を確認できる
バックアップからリストアする前にマルウェアスキャンを実行できます。
これによって、意図せず感染したバックアップをリストアしてしまうリスクを軽減できます。
GuardDuty を有効化していなくても使える
GuardDuty 本体を有効化せずに、この機能だけ単独で利用可能です。基本的には GuardDuty の有効化が推奨です。ただし、EventBridge と CloudWatch での検出結果通知は GuardDuty 無効でも使えます。
増分スキャンで効率的に検査できる
フルスキャンだけでなく、2 つのリソース間の差分のみをスキャンする増分スキャンに対応しています。定期的なスキャンを効率的に実行できます。
Malware Protection for AWS Backup とは
スキャン対象となるリソースは以下のとおりです。
| リソースタイプ | 説明 |
|---|---|
| EBS スナップショット | EC2 インスタンスのブロックストレージスナップショット |
| EC2 AMI | スナップショットを含む EC2 マシンイメージ |
| S3 Recovery Points | AWS Backup で作成された S3 のリカバリポイント |
| ロックされた Vault | イミュータブル(変更不可)なバックアップ Vault |
詳細はドキュメントを参照してください。
増分スキャンの要件
増分スキャンを利用するには、いくつか条件があります。
- ベースリソースが過去 90 日以内にスキャン済み(COMPLETED または COMPLETED_WITH_ISSUES)
- ベースリソースの作成日がターゲットより前
- スナップショットの場合、暗号化タイプが同一
- 同一リネージ(同じボリュームまたはそのコピー)
やってみる
実際にスキャンを実行してみます。今回はお試しなので、テスト用の EC2 へログインし EICAR ファイルをダウンロード、EBS スナップショットを作成してオンデマンドでスキャンという手順で進めます。

IAM ロールの作成
まず GuardDuty がスキャンする際に利用する IAM ロールを用意しておきましょう。
「信頼されたエンティティタイプ」で「カスタム信頼ポリシー」を選択し、以下の JSON を入力します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "malware-protection.guardduty.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

許可ポリシーの画面では「許可なしでロールを作成」を選択して一旦スキップし、「次へ」をクリックします。ロール名に GuardDutyMalwareProtectionRole と入力して「ロールを作成」をクリックします。
アクセス許可ポリシーの追加
ドキュメントを参考にポリシーを追加します。
作成したロールを開き、「許可を追加」→「インラインポリシーを作成」をクリックします。JSON タブを選択し、以下のポリシーを入力します。
GuardDutyMalwareProtectionPolicy(クリックで展開)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ebs:ListSnapshotBlocks",
"ebs:ListChangedBlocks",
"ebs:GetSnapshotBlock"
],
"Resource": "arn:aws:ec2:*::snapshot/*"
},
{
"Sid": "CreateGrantPermissions",
"Effect": "Allow",
"Action": "kms:CreateGrant",
"Resource": "arn:aws:kms:*:*:key/*",
"Condition": {
"ForAnyValue:StringLike": {
"kms:EncryptionContext:aws:guardduty:id": "snap-*",
"kms:ViaService": [
"guardduty.*.amazonaws.com",
"backup.*.amazonaws.com"
]
},
"ForAllValues:StringEquals": {
"kms:GrantOperations": [
"Decrypt",
"CreateGrant",
"GenerateDataKeyWithoutPlaintext",
"ReEncryptFrom",
"ReEncryptTo",
"RetireGrant",
"DescribeKey"
]
},
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
},
{
"Sid": "CreateGrantPermissionsForReEncryptAndDirectAPIs",
"Effect": "Allow",
"Action": "kms:CreateGrant",
"Resource": "arn:aws:kms:*:*:key/*",
"Condition": {
"ForAnyValue:StringLike": {
"kms:EncryptionContext:aws:ebs:id": "snap-*",
"kms:ViaService": [
"guardduty.*.amazonaws.com",
"backup.*.amazonaws.com"
]
},
"ForAllValues:StringEquals": {
"kms:GrantOperations": [
"Decrypt",
"ReEncryptTo",
"ReEncryptFrom",
"RetireGrant",
"DescribeKey"
]
},
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeImages",
"ec2:DescribeSnapshots"
],
"Resource": "*"
},
{
"Sid": "ShareSnapshotPermission",
"Effect": "Allow",
"Action": "ec2:ModifySnapshotAttribute",
"Resource": "arn:aws:ec2:*:*:snapshot/*"
},
{
"Sid": "ShareSnapshotKMSPermission",
"Effect": "Allow",
"Action": [
"kms:ReEncryptTo",
"kms:ReEncryptFrom"
],
"Resource": "arn:aws:kms:*:*:key/*",
"Condition": {
"StringLike": {
"kms:ViaService": "ec2.*.amazonaws.com"
}
}
},
{
"Sid": "DescribeKeyPermission",
"Effect": "Allow",
"Action": "kms:DescribeKey",
"Resource": "arn:aws:kms:*:*:key/*"
},
{
"Sid": "DescribeRecoveryPointPermission",
"Effect": "Allow",
"Action": "backup:DescribeRecoveryPoint",
"Resource": "*"
},
{
"Sid": "CreateBackupAccessPointPermissions",
"Effect": "Allow",
"Action": "backup:CreateBackupAccessPoint",
"Resource": "arn:aws:backup:*:*:recovery-point:*"
},
{
"Sid": "ReadAndDeleteBackupAccessPointPermissions",
"Effect": "Allow",
"Action": [
"backup:DescribeBackupAccessPoint",
"backup:DeleteBackupAccessPoint"
],
"Resource": "*"
},
{
"Sid": "KMSKeyPermissionsForInstantAccess",
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:*:*:key/*",
"Condition": {
"StringLike": {
"kms:ViaService": "backup.*.amazonaws.com"
}
}
}
]
}
ポリシー名に GuardDutyMalwareProtectionPolicy と入力して「ポリシーの作成」をクリックします。
EICAR テストファイルの配置
EC2 インスタンスに接続して、EICAR テストファイルをダウンロードします。
EICAR テストファイルは、マルウェア検出ソフトウェアのテスト用に設計された無害なファイルです。実際のマルウェアではありませんが、スキャナーによって検出されるように作られています。
テスト用に作成した EC2 へログインし、ターミナルで以下のコマンドを実行して EICAR ファイルをダウンロードします。
curl https://secure.eicar.org/eicar.com.txt -o ./eicar.com.txt
ダウンロードを確認したら接続を終了しましょう。
スナップショットの作成
EICAR ファイルを含む EBS ボリュームのスナップショットを作成します。
EC2 コンソールの左メニューから「ボリューム」を選択します。テスト用インスタンスにアタッチされているボリュームを選択し、「アクション」→「スナップショットを作成」をクリックします。

説明に「Malware scan test snapshot」と入力し、「スナップショットを作成」をクリックします。スナップショットが完了するまで待ちましょう。
スキャンの実行
スナップショットが作成できたら、GuardDuty コンソールからスキャンを実行します。
GuardDuty コンソールを開き、左メニューから「Malware Protection」を選択して「AWS Backup」を開きます。

「Start on-demand scan」をクリックします。

以下の設定でスキャンを開始します。

| 項目 | 設定値 |
|---|---|
| Scan scope | Scan backup of an AWS resource |
| Scan mode | Full scan |
| Target resource ARN | スナップショットの ARN |
| Service access | GuardDutyMalwareProtectionRole |
スナップショットの ARN は以下の形式で入力します。
arn:aws:ec2:ap-northeast-1:123456789012:snapshot/snap-xxxxxxxxxxxxxxxxx
スナップショット ID は EC2 コンソールの「スナップショット」画面で確認できます。
「Start scan」をクリックするとスキャンが開始されます。スキャン状況は左メニューの「Malware scans」画面で確認できます。
しばらく待つと無事 EICAR ファイルが検出されました。

スキャン結果に EICAR-Test-File (not a virus) として表示されていますね。
検出結果の確認
マルウェアが検出された場合、以下のような Findings が生成されます。
| Finding タイプ | 対象リソース |
|---|---|
Execution:EC2/MaliciousFile!Snapshot |
EBS スナップショット |
Execution:EC2/MaliciousFile!AMI |
EC2 AMI |
Execution:EC2/MaliciousFile!RecoveryPoint |
EC2 Recovery Point |
Execution:S3/MaliciousFile!RecoveryPoint |
S3 Recovery Point |
GuardDuty を有効にしている場合は上記 Findings をコンソールからも確認できます。
View malware findingsから GuardDuty の検出結果を見てみると、Execution:EC2/MaliciousFile!Snapshotとして検知されていました。

これでリストアする際も安心ですね。
注意点
クォータ(制限事項)
スキャン対象にはいくつか制限があります。
| 項目 | 制限値 |
|---|---|
| スナップショット最大サイズ | 2 TB |
| S3 オブジェクト最大サイズ | 100 GB |
| AMI 内スナップショット数 | 40(フルスキャン時) |
| アーカイブ展開最大サイズ | 100 GB |
| アーカイブ内ファイル数 | 10,000 |
| ネスト深度 | 5 レベル |
2 TB を超えるスナップショットや、100 GB を超える S3 オブジェクトはスキャンできないので注意が必要です。
料金
スキャン量に基づく従量課金となっています。詳細は公式の料金ページを確認してください。
まとめ
Malware Protection for AWS Backup により、バックアップデータのマルウェアスキャンが可能になりました。リストア前にバックアップの安全性を確認できるので、休眠マルウェアによる感染拡大リスクを軽減できます。
バックアップ運用に組み込んで、定期的なスキャンを実施してみてはいかがでしょうか。







