話題の記事

[神アップデート]GuardDutyがEC2やECSのマルウェア検知時のスキャンに対応したので実際にスキャンさせてみた #reinforce

神機能が提供されました。EC2やコンテナでマルウェア感染の挙動を検知したら、GuardDutyがマルウェアスキャンを実施できるようになりました。ユーザーが頑張ることが1つ減りました。控えめに言って最高ですね。
2022.07.27

こんにちは、臼田です。

みなさん、AWSで脅威検知してますか?(挨拶

神機能がリリースされました!現在開催されているAWSのセキュリティカンファレンスre:InforceにてEC2やECS/EKSなどのコンテナワークロード上でマルウェアを検知した際にスキャンする機能が発表されました!

New for Amazon GuardDuty – Malware Detection for Amazon EBS Volumes | AWS News Blog

この機能を実際に試してみます。

かんたんまとめ(長くなった)

  • 機能概要
    • AWS上の脅威検知サービスであるGuardDutyがマルウェアスキャンに対応
    • 機能名はMalware Protection
    • Protectionは防御の意味でも使われるけど、機能の動作としては検知
    • マルウェアの動きを直接止めない
  • 有効化
    • GuardDutyの追加機能で、有効無効の設定がある
    • 新規GuardDuty利用時はデフォルト有効化
    • 既存GuardDutyでは無効、明示的に有効化できる
  • 料金
    • 有効化後30日間の無料枠あり
    • スキャンしたEBSボリューム1GBあたりの料金
      • バージニアなどでは0.03ドル/GB
      • 東京リージョンなどでは0.05ドル/GB
  • 対応リージョン
    • だいたい全部
  •  機能動作
    • マルウェアをスキャンするためには、別のGuardDutyの検知をトリガーとしたマルウェアスキャンの開始が必要
      • Backdoor:EC2/C&CActivity.BやCryptoCurrency:EC2/BitcoinTool.B!DNSなどマルウェアの動作が疑われるFindingsが対象
      • 対象Finding Typesの検知があると自動でトリガーされる
      • スキャンは新しく作成されるスキャン用IAM Roleから実施する
    • 対象のEBSを特定し、スナップショットを取得する
      • スナップショットに対してスキャンするため、既存リソースへの影響はない
      • スナップショットに対してスキャンするため、既存でEC2などにエージェントを入れる必要はない
    • トロイの木馬、ワーム、クリプトマイナー、ルートキット、ボットなどの脅威を検知する
    • 一度スキャンされたEC2などは24時間は再スキャンされない
    • タグにより任意でスキャン対象をInclude/Excludeできる
    • KMSによるEBSの暗号化に対しても適切に動作する
    • スナップショットはスキャン完了後デフォルトではすぐ削除される
      • オプションでスナップショットを保持できる
    • スキャンの結果マルウェアが検知されたらFindingsが生成される
      • マルウェアが検知されなければFindingsは生成されない
      • スキャン自体は履歴に残る
      • CloudWatch Logsにスキャンのログが出力される
  • 未確認の内容
    • ECSやEKSも検知対象となっているが、EBSに対するスキャンが実態の機能なため、Fargate利用時などで検知できるか要確認

2022/10/15追記 現状ではFargateに対応していないとユーザーガイドに明記されました。

アップデートの概要

Amazon GuardDutyはAWS上の様々な脅威を検知するサービスです。EC2が外部からのスキャンやマルウェアの感染、C&Cサーバーとの通信やコインマイニング、IAM情報の漏洩やS3への不正アクセスなど様々なタイプの脅威を検知できます。

これまではVPCに流れる通信のIPアドレスやDNSのログに基づきマルウェアに関するアクティビティを検知していましたが、実際にEC2の内部については確認していませんでした。

今回のアップデートではもともと検知していたマルウェアに関するアクティビティを発見した際に、GuardDutyが追加でEC2やコンテナに関連するEBSに対してマルウェアスキャンを実施し、実際にマルウェアのファイルを検知する機能に対応しました!

この機能の登場以前、不審なアクティビティを検知してからマルウェアのスキャンを行うのはユーザーの作業でした。ユーザーがアラートを検知し、様々な判断を行い、関係者の承認を取り、時間をかけた後、危険な可能性のあるEC2インスタンスに接続し、商用あるいはオープンなマルウェアスキャンツールをセットアップし、スキャンしていました。

このアップデートにより、脅威を検知してから具体的なマルウェアの特定まで、自動化された素早く安全な仕組みで対応することが可能になりました。

更にこの情報はAWS Security Hubにも連携され、次の分析や対応のアクションにつなげることが可能です。

マルウェア検知させてみた

それでは実際にやっていきましょう。私の手元の環境では既にGuardDutyが有効化されているので、Malware Protectionの機能を有効化するところから始めて、実際にマルウェアスキャンさせてどう見えるか確認していきます。手順や参考情報は既にユーザーガイドにも上がっています。

ちなみに、ぼちぼちハマったのでその話も後で補足を入れます。これから検証するぞって方はそちらまで目を通してから実施してください。

Malware Protectionの有効化

まずGuardDutyの画面にアクセスします。ポップアップや左カラムからMalware Protectionへの誘導がありますのでここから移動します。

Malware Protectionの有効化を実施します。「有効にする」を押します。

ポップアップが出てきて動作について説明があります。有効にします。

有効化できました。ついでに下の方にスナップショットを保持するかの設定がありますので、せっかくなので保持するようにONにしておきます。

EC2を作成してマルウェアを検知させる

それではEC2を作ってマルウェアを仕込んで検知させていきます。といってもEICARですけどね。

マルウェアスキャンを開始するトリガーとなるのは特定のFinding Typesの検知です。対象のリストはこちらにあります。

まず適当にEC2を作ります。今回はAmazon Linux 2を利用しました。

起動したらEICARを仕込みます。下記のような感じ。

[ec2-user@ip-172-31-3-139 ~]$ wget https://secure.eicar.org/eicar.com
--2022-07-26 17:32:16--  https://secure.eicar.org/eicar.com
Resolving secure.eicar.org (secure.eicar.org)... 89.238.73.97, 2a00:1828:1000:2497::2
Connecting to secure.eicar.org (secure.eicar.org)|89.238.73.97|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 68
Saving to: ‘eicar.com’

100%[===================================================================================================================>] 68          --.-K/s   in 0s

2022-07-26 17:32:17 (9.91 MB/s) - ‘eicar.com’ saved [68/68]

[ec2-user@ip-172-31-3-139 ~]$ wget https://secure.eicar.org/eicar_com.zip
--2022-07-26 17:32:25--  https://secure.eicar.org/eicar_com.zip
Resolving secure.eicar.org (secure.eicar.org)... 89.238.73.97, 2a00:1828:1000:2497::2
Connecting to secure.eicar.org (secure.eicar.org)|89.238.73.97|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 184 [application/zip]
Saving to: ‘eicar_com.zip’

100%[===================================================================================================================>] 184         --.-K/s   in 0s

2022-07-26 17:32:26 (25.3 MB/s) - ‘eicar_com.zip’ saved [184/184]

[ec2-user@ip-172-31-3-139 ~]$ ls -al
total 20
drwx------ 3 ec2-user ec2-user 112 Jul 26 17:32 .
drwxr-xr-x 4 root     root      38 Jul 26 17:31 ..
-rw-r--r-- 1 ec2-user ec2-user  18 Jul 15  2020 .bash_logout
-rw-r--r-- 1 ec2-user ec2-user 193 Jul 15  2020 .bash_profile
-rw-r--r-- 1 ec2-user ec2-user 231 Jul 15  2020 .bashrc
-rw-rw-r-- 1 ec2-user ec2-user  68 Jul  1  2020 eicar.com
-rw-rw-r-- 1 ec2-user ec2-user 184 Jul  1  2020 eicar_com.zip
drwx------ 2 ec2-user ec2-user  29 Jul 26 17:20 .ssh

仕込んだら次に、不審なアクティビティを発生させます。マルウェアをダウンロードしてくるだけでは、GuardDutyはマルウェアを検知しません。(なので既存のアンチマルウェアが活躍する場面は十分ありますし、ちゃんと使いましょうね)

今回はコインマイニングを検知する下記手法にしました。

[ec2-user@ip-172-31-3-139 ~]$ nslookup pool.supportxmr.com
Server:         172.31.0.2
Address:        172.31.0.2#53

Non-authoritative answer:
pool.supportxmr.com     canonical name = pool-phx.supportxmr.com.
Name:   pool-phx.supportxmr.com
Address: 192.110.160.114
Name:   pool-phx.supportxmr.com
Address: 107.178.104.10

[ec2-user@ip-172-31-3-139 ~]$ curl pool.supportxmr.com
Mining Pool Online

これで仕込みは完了です。

GuardDutyの検知を確認

しばらくすると無事(?)マイニングのFinding TypesであるCryptoCurrency:EC2/BitcoinTool.Bを検知しました。

これに伴いマルウェアスキャンが開始されました。GuardDutyのマネジメントコンソール左カラムに新しく追加された「マルウェアスキャン」画面から確認ができます。スキャンが開始されステータスが「Running」となっています。

スキャンの詳細画面では、どのGuardDuty Findingsからトリガーされたか、対象のEC2やボリューム、出力先のCloudWatch Logsの情報などが表示されます。

ログのリンクはCloudWatch Logsインサイトのクエリ画面でした。ワタシ的には、直接ログストリームを確認するほうが良さそうだと感じました。

実際のログは以下のような感じで出力されています。EC2_SCAN_STARTEDというイベントです。

{
    "eventDetails": {
        "accountId": "999999999999",
        "eventType": "EC2_SCAN_STARTED",
        "eventTime": "2022-07-26T17:40:03.093Z",
        "detectorId": "6cbf****************************",
        "schemaVersion": "1.0"
    },
    "scanRequestDetails": {
        "requestType": "GUARDDUTY_FINDING_INITIATED",
        "scanId": "db3e****************************",
        "guardDutyRequestDetails": {
            "findingId": "98c1****************************"
        }
    },
    "resourceDetails": {
        "resourceType": "EC2_INSTANCE",
        "instanceDetails": {
            "instanceId": "i-07a**************",
            "volumeDetailsList": [
                {
                    "volumeId": "vol-046**************",
                    "deviceName": "/dev/xvda",
                    "volumeSizeGb": 8
                }
            ]
        }
    }
}

しばらくするとマルウェアを無事(?)検知しました。Execution:EC2/MaliciousFileのFinding Typesです。詳細を確認しましょう。2つのEICARファイルについて検知しています。ファイルハッシュをベースに検知し、そのファイルの名前/パス/重要度などが確認できます。

詳細なFindingsの中には下記のように書かれています。zipファイルに対しても適切に機能していることがわかります。

"ThreatDetectedByName": {
  "ItemCount": 2,
  "UniqueThreatNameCount": 1,
  "Shortened": false,
  "ThreatNames": [
    {
      "Name": "EICAR-Test-File (not a virus)",
      "Severity": "HIGH",
      "ItemCount": 2,
      "FilePaths": [
        {
          "FilePath": "/home/ec2-user/eicar.com",
          "VolumeArn": "arn:aws:ec2:us-west-2:999999999999:volume/vol-046**************",
          "Hash": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
          "FileName": "eicar.com"
        },
        {
          "FilePath": "/home/ec2-user/eicar_com.zip=>eicar.com",
          "VolumeArn": "arn:aws:ec2:us-west-2:999999999999:volume/vol-046**************",
          "Hash": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
          "FileName": "eicar_com.zip=>eicar.com"
        }
      ]
    }
  ]
}

マルウェアスキャンの画面ではスキャン結果の詳細も確認できます。スキャン結果はInfectedでした。スキャンにかかった時間は約7分です。スキャンした容量は1.52GB、ファイル数は44240でした。スナップショットを取得してスキャンしていると考えると妥当な時間な気がしますね。容量が増えたらどれくらいスキャン時間が増えるのか気になります。

マルウェアスキャンをトリガーしたFindingsに戻ってくると、スキャンも含めたタイムラインが確認できました。トリガー元の検知からスキャンの開始まで約3分、スナップショットを取得してスキャンを完了するまで約7分です。スキャン完了の次の瞬間にはExecution:EC2/MaliciousFileが検知されています。ちなみにマイニングのアクティビティを発生させてから検知までは約5分でした。

スキャンが完了した内容もCloudWatch Logsに出力されました。下記のようになっています。

{
    "eventDetails": {
        "accountId": "999999999999",
        "eventType": "EC2_SCAN_COMPLETED",
        "eventTime": "2022-07-26T17:47:16Z",
        "detectorId": "6cbf****************************",
        "schemaVersion": "1.0",
        "adminAccountId": "999999999999"
    },
    "scanRequestDetails": {
        "requestType": "GUARDDUTY_FINDING_INITIATED",
        "scanId": "db3e****************************",
        "guardDutyRequestDetails": {
            "findingId": "98c1****************************"
        }
    },
    "resourceDetails": {
        "resourceType": "EC2_INSTANCE",
        "instanceDetails": {
            "instanceId": "i-07a**************",
            "volumeDetailsList": [
                {
                    "volumeId": "vol-046**************",
                    "deviceName": "/dev/xvda",
                    "volumeSizeGb": 8,
                    "volumeSnapshotId": "snap-024**************"
                }
            ]
        }
    },
    "scanResultsSummary": {
        "scanResultStatus": "THREATS_FOUND",
        "scannedItemCount": {
            "totalGb": 2,
            "files": 44240
        }
    }
}

取得されたスナップショットを確認します。GuardDutyScanId / GuardDutyExcluded / GuardDutyFindingDetectedの3つのタグが付いていました。KMSキーはEC2と同じものが利用されていました。

一通り動作確認できました。

ハマった内容

東京リージョンでの動作確認

対応リージョンとしては、下記を除くすべてのリージョンとなっています。

  • AWS China (Beijing)
  • AWS China (Ningxia)
  • AWS GovCloud (US-East)
  • AWS GovCloud (US-West)

つまりほぼすべてのリージョンに対応しています。

しかしながら、この動作確認をしている2022/07/27現在では、東京リージョンにこの機能は展開されていませんでした。多分しばらくしたら展開されると思いますが、今回はオレゴンで動作確認しました。

[2022/07/27 16:55追記]東京リージョンでのMalware Protection展開を確認できました!心置きなく使いましょう。

KMS起因のスキャン失敗

始め、私の環境のデフォルト設定で作成したEC2で動作確認していましたが、マルウェアスキャンが失敗しました。下記のようなログがCloudWatch Logsに出力されました。

{
    "eventDetails": {
        "accountId": "999999999999",
        "eventType": "EC2_SCAN_SKIPPED",
        "eventTime": "2022-07-26T15:50:02.017Z",
        "detectorId": "6cbf****************************",
        "schemaVersion": "1.0"
    },
    "scanRequestDetails": {
        "requestType": "GUARDDUTY_FINDING_INITIATED",
        "guardDutyRequestDetails": {
            "findingId": "62c1****************************"
        }
    },
    "resourceDetails": {
        "resourceType": "EC2_INSTANCE",
        "instanceDetails": {
            "instanceId": "i-001**************",
            "volumeDetailsList": [
                {
                    "volumeId": "vol-0db**************",
                    "deviceName": "/dev/xvda",
                    "volumeSizeGb": 8,
                    "skipReason": "UNSUPPORTED_KEY_ENCRYPTION"
                }
            ]
        }
    }
}

UNSUPPORTED_KEY_ENCRYPTIONとなっていて、KMSキーが問題になっていることがわかります。今回利用しているのはAWSのデフォルトEBSキーです。これを確認しに行きました。するとキーポリシーは下記のようになっていました。

"Action": [
    "kms:Encrypt",
    "kms:Decrypt",
    "kms:ReEncrypt*",
    "kms:GenerateDataKey*",
    "kms:CreateGrant",
    "kms:DescribeKey"
],
"Resource": "*",
"Condition": {
    "StringEquals": {
        "kms:CallerAccount": "999999999999",
        "kms:ViaService": "ec2.us-west-2.amazonaws.com"
    }

あまり細かく確認していないので推測も含みますが、kms:ViaServiceによりEC2からの呼び出しのみ許可されていて、GuardDutyから利用できないようになっていると考えました。

というわけで新しくユーザー定義のKMSキーを作成しました。下記のようにGuardDutyのマルウェアスキャン用IAM Roleに権限を与えたところ、スキャンできました。

GuardDuty Testerの起動失敗

AWSブログではGuardDuty Testerを利用して検知させています。これは以前からある仕組みで下記ブログでも紹介されています。

しかしながら、今回これを利用しようとしたところ、CloudFormationの展開に失敗しました。

Windowsサーバーのインスタンスの作成で下記エラーが発生しました。

Instance i-06c************** failed to stabilize. Current state: shutting-down. Reason: Server.InternalError: Internal error on launch

何度かトライしたり、別リージョンで確認したり、該当AMIを手動で立ち上げたりしても同じようなエラーになったため、GuardDuty Testerの問題と言うよりこのAMIのとEC2の問題のようだったので今回は利用しませんでした。

代わりにGuardDuty Testerの内容を解釈し、動作原理を理解するのに役立てました。

その他周辺の状況確認

関連するリソースや見え方などのTipsを書いていきます。

追加されたFinding Types

下記に一覧があります。

Malware Protection finding types - Amazon GuardDuty

  • Execution:EC2/MaliciousFile
  • Execution:ECS/MaliciousFile
  • Execution:Kubernetes/MaliciousFile
  • Execution:Container/MaliciousFile
  • Execution:EC2/SuspiciousFile
  • Execution:ECS/SuspiciousFile
  • Execution:Kubernetes/SuspiciousFile
  • Execution:Container/SuspiciousFile

EC2とECSとEKSと、あとECSクラスターでもKubernetesクラスターでもない単体コンテナに対して、悪意のあるファイルと疑わしい(アドウェア、スパイウェア、デュアルユースツールなどの望ましくない可能性のあるプログラム)の検知があります。

スキャン例外の登録

Malware Protectionの設定画面から、スキャンオプションとして例外の登録ができます。タグによりスキャン対象を明示的に指定するか、スキャンの除外対象を明示的に指定できます。

タグを追加するときにはどちらか片方しか選択できません。

選択すると、タグの設定画面に切り替わります。この段階ではまだ保存されません。

編集中にもどちらの方式にするか選択できますが、変更時には既存の設定がクリアされるようです。

おそらくこの設定に合わせてService-Linked Roleのポリシーが追加されるのでは?と考えています。

スキャンオプションについてはこちらのユーザーガイドに詳細があります。

IAM Roleの設定

マルウェアスキャンのために既存のService-Linked Roleとは別のIAM Roleが作成されます。

AWSServiceRoleForAmazonGuardDutyMalwareProtectionという名前で、AmazonGuardDutyMalwareProtectionServiceRolePolicyというAWSマネージドポリシーがアタッチされていました。

ポリシーはEBSのスナップショットの閲覧や取得、KMS操作、ログ出力などが含まれています。

GuardDutyExcludedタグがtrueの場合にスナップショットの取得などができないConditionになっています。

EBS暗号化の対応

マルウェアスキャンは対象のEBSが暗号化されていても動作します。ただ上記でハマっていたように、KMSのキーポリシーも含め適切に設定していく必要があります。(逆に言うと、そこを絞ればスキャンさせないことができる)

元のEBSが暗号化されていなくても、マルウェアスキャンが作成するEBSスナップショットは暗号化されます。その場合は独自のキーが利用されるとのことでした。

CloudTrailでのトラッキング

マルウェアスキャンは該当のIAM Roleで実行されることから、CloudTrailでのトラッキングが簡単にできます。

ユーザー名にGuardDutyMalwareProtectionを指定すると確認できました。

Malware Protectionのマルチアカウント連携

GuardDutyのマルチアカウント管理の機能を利用してMalware Protectionも利用できます。自動で有効化する設定が可能です。

既存のアカウントに対してはService-Linked Roleが必要となるため、Malware Protectionを有効化できません。ワークアラウンドとして一度関連付けを解除してから再登録する方法が提示されています。詳細はこちらをご確認ください。

まとめ

GuardDutyのマルウェアスキャンについて確認しました。

これまでユーザーが頑張っていた運用がまた1つ簡単になりました。控えめに言って最高ですね。

Malware Protectionはスキャンした容量単位の料金ですから、有効化しない手はないでしょう。すぐ有効化しましょう!