話題の記事

TrivyでAWSアカウントのセキュリティスキャンができるようになりました

TrivyでAWSアカウントのセキュリティスキャンができるようになりました。
2022.08.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

中山です

trivyのv0.31.0でAWSアカウントのセキュリティスキャンができるようになりました。

feat: Add AWS Cloud scanning (#2493)

Releases / v0.31.0

なお、v0.31.0でスキャンを実行するとクラッシュするバグがあり、すぐにv0.31.2がリリースされました。

Releases / v0.31.2

どんな感じか気になったので、軽く触っておこうと思います。

ドキュメントを確認

まずはドキュメントを確認します。

Amazon Web Services

ポイントになると思った点をまとめます。

  • CIS AWS Foundations Benchmark standardに準拠したチェックが可能
  • 認証方法はAWS CLIと同じ
  • すべてのAWSリソースに対する参照権限が必要 (ReadOnlyAccess)
  • サービス・リージョン・リソース(ARN)でのフィルタリングが可能
  • デフォルトで24時間スキャン結果がキャッシュされる(コマンド実行時のオプションでキャッシュを強制的に更新することも可能)
  • 現時点では実験的な機能という位置づけのため、破壊的な変更があり得る

ヘルプを確認

ヘルプも見ておきましょう。

trivy aws --help
$ trivy aws --help
Scan an AWS account for misconfigurations. Trivy uses the same authentication methods as the AWS CLI. See https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html

The following services are supported:
- api-gateway
- athena
- cloudfront
- cloudtrail
- cloudwatch
- codebuild
- documentdb
- dynamodb
- ec2
- ecr
- ecs
- efs
- eks
- elasticache
- elasticsearch
- elb
- emr
- iam
- kinesis
- kms
- lambda
- mq
- msk
- neptune
- rds
- redshift
- s3
- sns
- sqs
- ssm
- workspaces

Usage:
  trivy aws [flags]

Examples:
  # basic scanning
  $ trivy aws --region us-east-1

  # limit scan to a single service:
  $ trivy aws --region us-east-1 --service s3

  # limit scan to multiple services:
  $ trivy aws --region us-east-1 --service s3 --service ec2

  # force refresh of cache for fresh results
  $ trivy aws --region us-east-1 --update-cache


Report Flags
      --dependency-tree        show dependency origin tree (EXPERIMENTAL)
      --exit-code int          specify exit code when any security issues are found
  -f, --format string          format (table, json, sarif, template, cyclonedx, spdx, spdx-json, github, cosign-vuln) (default "table")
      --ignore-policy string   specify the Rego file path to evaluate each vulnerability
      --ignorefile string      specify .trivyignore file (default ".trivyignore")
      --list-all-pkgs          enabling the option will output all packages regardless of vulnerability
  -o, --output string          output file name
      --report string          specify a report format for the output. (all,summary) (default "all")
  -s, --severity string        severities of security issues to be displayed (comma separated) (default "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL")
  -t, --template string        output template

Misconfiguration Flags
      --config-data strings         specify paths from which data for the Rego policies will be recursively loaded
      --config-policy strings       specify paths to the Rego policy files directory, applying config files
      --file-patterns strings       specify config file patterns, available with '--security-checks config'
      --helm-set strings            specify Helm values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
      --helm-set-file strings       specify Helm values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)
      --helm-set-string strings     specify Helm string values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
      --helm-values strings         specify paths to override the Helm values.yaml files
      --include-non-failures        include successes and exceptions, available with '--security-checks config'
      --policy-namespaces strings   Rego namespaces
      --tf-vars strings             specify paths to override the Terraform tfvars files
      --trace                       enable more verbose trace output for custom queries

Cloud Flags
      --max-cache-age duration   The maximum age of the cloud cache. Cached data will be requeried from the cloud provider if it is older than this. (default 24h0m0s)
      --update-cache             Update the cache for the applicable cloud provider instead of using cached results.

AWS Flags
      --account string    The AWS account to scan. It's useful to specify this when reviewing cached results for multipel accounts.
      --arn string        The AWS ARN to show results for. Useful to filter results once a scan is cached.
      --endpoint string   AWS Endpoint override
      --region string     AWS Region to scan
      --service strings   Only scan AWS Service(s) specified with this flag. Can specify multiple services using --service A --service B etc.

Global Flags:
      --cache-dir string          cache directory (default "/home/ec2-user/.cache/trivy")
  -c, --config string             config path (default "trivy.yaml")
  -d, --debug                     debug mode
      --generate-default-config   write the default config to trivy-default.yaml
      --insecure                  allow insecure server connections when using TLS
  -q, --quiet                     suppress progress bar and log output
      --timeout duration          timeout (default 5m0s)
  -v, --version                   show version

コマンドの実行例もあり、非常に親切ですね。(たすかる)

スキャン対象を絞る方法や出力結果のフォーマットの指定方法なども確認できます。

やってみた

以下の流れで試してみます。

  • 実行環境の作成
    • 今回はCloud9を利用
  • 認証情報の設定
  • Trivyのインストール
  • スキャンの実行

Cloud9環境の作成手順は割愛します。今回はAmazon Linux2+EC2で環境を作成しました。必要に応じて公式のドキュメント等を確認してください。

Creating an EC2 Environment

また、Cloud9を利用する場合にはマネージメントコンソールにログインする際に利用したユーザー・ロールの権限をシームレスに利用できるため、追加の設定は不要です。 この仕様に関する詳細も必要に応じて公式ドキュメントを確認してください。

AWS managed temporary credentials

AWS managed temporary credentialsを利用する際に認証に関する問題が発生した場合、Cloud9が作成したEC2インスタンスにInstance Profileを設定してAWS managed temporary credentialsを無効化することで問題を回避できる場合があります。必要に応じてご対応ください。

Create and use an instance profile to manage temporary credentials

Trivyのインストール

インストールはこちらのドキュメントを参照してください。

Installation

今回はRPMを利用してインストールします。

rpm -ivh https://github.com/aquasecurity/trivy/releases/download/v0.31.2/trivy_0.31.2_Linux-64bit.rpm

スキャンの実行

コマンドを実行してみます。

trivy aws
[1/31] Scanning api-gateway...
[2/31] Scanning athena...
[3/31] Scanning cloudfront...
[4/31] Scanning cloudtrail...
[5/31] Scanning cloudwatch...
[6/31] Scanning codebuild...
[7/31] Scanning documentdb...
[8/31] Scanning dynamodb...
[9/31] Scanning ec2...
[10/31] Scanning ecr...
[11/31] Scanning ecs...
[12/31] Scanning efs...
[13/31] Scanning eks...
[14/31] Scanning elasticache...
[15/31] Scanning elasticsearch...
[16/31] Scanning elb...
[17/31] Scanning emr...
[18/31] Scanning iam...
[19/31] Scanning kinesis...
[20/31] Scanning kms...
[21/31] Scanning lambda...
[22/31] Scanning mq...
[23/31] Scanning msk...
[24/31] Scanning neptune...
[25/31] Scanning rds...
[26/31] Scanning redshift...
[27/31] Scanning s3...
[28/31] Scanning sns...
[29/31] Scanning sqs...
[30/31] Scanning ssm...
[31/31] Scanning workspaces...

Scan Overview for AWS Account xxxxxxxxxxxx
┌───────────────┬──────────────────────────────────────────────────┬──────────────┐
│               │                Misconfigurations                 │              │
│               ├──────────┬──────────────┬────────┬─────┬─────────┤              │
│ Service       │ Critical │     High     │ Medium │ Low │ Unknown │ Last Scanned │
├───────────────┼──────────┼──────────────┼────────┼─────┼─────────┼──────────────┤
│ api-gateway   │        0 │            0 │      0 │   0 │       0 │ just now     │
│ athena        │        0 │            3 │      0 │   0 │       0 │ just now     │
│ cloudfront    │        1 │            2 │      1 │   0 │       0 │ just now     │
│ cloudtrail    │        0 │            1 │      0 │   1 │       0 │ just now     │
│ cloudwatch    │        0 │            0 │      0 │  16 │       0 │ just now     │
│ codebuild     │        0 │            0 │      0 │   0 │       0 │ just now     │
│ documentdb    │        0 │            0 │      0 │   0 │       0 │ just now     │
│ dynamodb      │        0 │            0 │      0 │   0 │       0 │ just now     │
│ ec2           │       48 │            2 │      0 │  38 │       0 │ just now     │
│ ecr           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ ecs           │        0 │            0 │      0 │   1 │       0 │ just now     │
│ efs           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ eks           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ elasticache   │        0 │            0 │      0 │   0 │       0 │ just now     │
│ elasticsearch │        0 │            0 │      0 │   0 │       0 │ just now     │
│ elb           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ emr           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ iam           │        0 │          191 │      4 │   1 │       0 │ just now     │
│ kinesis       │        0 │            0 │      0 │   0 │       0 │ just now     │
│ kms           │        0 │            0 │     21 │   0 │       0 │ just now     │
│ lambda        │        0 │            0 │      0 │   0 │       0 │ just now     │
│ mq            │        0 │            0 │      0 │   0 │       0 │ just now     │
│ msk           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ neptune       │        0 │            0 │      0 │   0 │       0 │ just now     │
│ rds           │        1 │            0 │      0 │   0 │       0 │ just now     │
│ redshift      │        0 │            0 │      0 │   0 │       0 │ just now     │
│ s3            │        0 │           28 │     10 │   2 │       0 │ just now     │
│ sns           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ sqs           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ ssm           │        0 │            0 │      0 │   0 │       0 │ just now     │
│ workspaces    │        0 │            0 │      0 │   0 │       0 │ just now     │
└───────────────┴──────────┴──────────────┴────────┴─────┴─────────┴──────────────┘

特定のサービスのみのスキャンを実行する事もできます。

trivy aws --service s3
Resource Summary for Service 's3' (AWS Account xxxxxxxxxxxx)
┌─────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────┐
│                                                                             │            Misconfigurations             │
│                                                                             ├──────────┬──────┬────────┬─────┬─────────┤
│ Resource                                                                    │ Critical │ High │ Medium │ Low │ Unknown │
├─────────────────────────────────────────────────────────────────────────────┼──────────┼──────┼────────┼─────┼─────────┤
│ arn:aws:s3:::aws-athena-query-results-xxxxxxxxxxxx-ap-northeast-1           │        0 │    6 │      2 │   1 │       0 │
│ arn:aws:s3:::cf-templates-yyyyyyyyyy-ap-northeast-1                         │        0 │    2 │      2 │   0 │       0 │
│ arn:aws:s3:::dummy-000                                                      │        0 │    2 │      2 │   0 │       0 │
│ arn:aws:s3:::dummy-001                                                      │        0 │    6 │      2 │   0 │       0 │
│ arn:aws:s3:::dummy-002                                                      │        0 │    6 │      1 │   0 │       0 │
│ arn:aws:s3:::dummy-003                                                      │        0 │    6 │      1 │   1 │       0 │
└─────────────────────────────────────────────────────────────────────────────┴──────────┴──────┴────────┴─────┴─────────┘

This scan report was loaded from cached results. If you'd like to run a fresh scan, use --update-cache.

リソース単位で詳細な結果を確認することも可能です。

各是正項目に記載のあるリンク先には、問題の詳細や是正方法に関する記載があります。

trivy aws --arn arn:aws:s3:::aws-athena-query-results-xxxxxxxxxxxx-ap-northeast-1
Results for 'arn:aws:s3:::aws-athena-query-results-xxxxxxxxxxxx-ap-northeast-1' (AWS Account xxxxxxxxxxxx)


arn:aws:s3:::aws-athena-query-results-xxxxxxxxxxxx-ap-northeast-1 (cloud)

Tests: 9 (SUCCESSES: 0, FAILURES: 9, EXCEPTIONS: 0)
Failures: 9 (UNKNOWN: 0, LOW: 1, MEDIUM: 2, HIGH: 6, CRITICAL: 0)

HIGH: No public access block so not blocking public acls
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
S3 buckets should block public ACLs on buckets and any objects they contain. By blocking, PUTs with fail if the object has any public ACL a.

See https://avd.aquasec.com/misconfig/avd-aws-0086



HIGH: No public access block so not blocking public policies
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
S3 bucket policy should have block public policy to prevent users from putting a policy that enable public access.

See https://avd.aquasec.com/misconfig/avd-aws-0087



HIGH: Bucket does not have encryption enabled
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
S3 Buckets should be encrypted to protect the data that is stored within them if access is compromised.

See https://avd.aquasec.com/misconfig/avd-aws-0088



MEDIUM: Bucket does not have logging enabled
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Buckets should have logging enabled so that access can be audited.

See https://avd.aquasec.com/misconfig/avd-aws-0089



MEDIUM: Bucket does not have versioning enabled
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Versioning in Amazon S3 is a means of keeping multiple variants of an object in the same bucket. 
You can use the S3 Versioning feature to preserve, retrieve, and restore every version of every object stored in your buckets. 
With versioning you can recover more easily from both unintended user actions and application failures.

See https://avd.aquasec.com/misconfig/avd-aws-0090



HIGH: Bucket does not encrypt data with a customer managed key.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Encryption using AWS keys provides protection for your S3 buckets. To increase control of the encryption and manage factors like rotation use customer managed keys.

See https://avd.aquasec.com/misconfig/avd-aws-0132



HIGH: No public access block so not ignoring public acls
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
S3 buckets should ignore public ACLs on buckets and any objects they contain. By ignoring rather than blocking, PUT calls with public ACLs will still be applied but the ACL will be ignored.

See https://avd.aquasec.com/misconfig/avd-aws-0091



HIGH: No public access block so not restricting public buckets
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
S3 buckets should restrict public policies for the bucket. By enabling, the restrict_public_buckets, only the bucket owner and AWS Services can access if it has a public policy.

See https://avd.aquasec.com/misconfig/avd-aws-0093



LOW: Bucket does not have a corresponding public access block.
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
The "block public access" settings in S3 override individual policies that apply to a given bucket, meaning that all public access can be controlled in one central types for that bucket. It is therefore good practice to define these settings for each bucket in order to clearly define the public access that can be allowed for it.

See https://avd.aquasec.com/misconfig/avd-aws-0094




This scan report was loaded from cached results. If you'd like to run a fresh scan, use --update-cache.

まとめ

以上のように、trivyでAWSアカウントのスキャンを行えるようになりました。

ローカル環境で手軽にスキャンを実行できて非常に良いですね。個人的にはARN指定でスキャンできるのがありがたいです。 CI/CD環境への組み込みも簡単にできそうです。

現時点では実験的な機能という位置づけですが、そのうちサポート対象のサービス拡大や安定性の向上も図られると思いますので注目しておきたいと思います。

追記

YouTubeに解説動画もアップロードされていました。