コンテナイメージ脆弱性スキャンツールの Trivy を使ってみた
はじめに
私が携わってる案件では ECR, ECS (Fargate) を使っていますが、コンテナイメージの脆弱性スキャンをやろうと思い ECR Image scanning を使ってみたところ、スキャンが割と雑で悩んでいました。 そこで類似ツールの Trivy を使ってみたら解決できたよという話です。
ECR Image scanning
ECR Image scanning は AWS のフルマネージドコンテナ脆弱性スキャンツールです。AWS で ECS, ECR あたりを使っている方だったら利用経験があったりするのではないでしょうか。
この ECR Image scanning は AWS マネジメントコンソールで「スキャン」ボタンをクリックするだけでお手軽に使える便利なサービスですが、使いにくい点がいくつかあります。
1. カーネルの脆弱性を報告する
ECR image scanning は以下のようにカーネルの脆弱性を報告することがありますが、Fargate を使っている場合だとそもそもホストをどうこうできないので、そんな状態でカーネルの脆弱性を報告されても困るのです。
2. ディストリビューションで未対応の脆弱性を報告する
ディストリビューションで未対応の脆弱性を報告することもあります。例えば、Debian 10 (buster) ベースのコンテナイメージから以下の脆弱性が検出されましたが、
これは、現時点ではディストリビューションで未対応な脆弱性です。
もちろん、ディストリビューションで未対応だからといって無条件で対応しなくていいというわけではありませんが、せめてディストリビューションで対応しているものと未対応のものを分けて表示してくれるともっと使いやすいのになーと思ったりします。
Trivy
Trivy は Teppei Fukuda という方が開発し、イスラエルの Aqua Security Software 社に買収されたコンテナイメージの脆弱性スキャンツールです。
Trivy には --ignore-unfixed
オブションがあり、これをつけることによってディストリビューションで未対応の脆弱性を無視することができました。
試しに手元で nginx のコンテナイメージに対して --ignore-unfixed
なし/ありでスキャンしてみましたが以下のような結果になりました。
オプションなし
$ trivy --severity=HIGH,CRITICAL nginx 2020-12-27T11:46:35.326+0900 WARN You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed 2020-12-27T11:46:39.028+0900 INFO Detecting Debian vulnerabilities... nginx (debian 10.5) =================== Total: 51 (HIGH: 48, CRITICAL: 3) +------------------+------------------+----------+-----------------------+-----------------------+--------------------------------------------------------------+ | LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE | +------------------+------------------+----------+-----------------------+-----------------------+--------------------------------------------------------------+ | curl | CVE-2020-8169 | HIGH | 7.64.0-4+deb10u1 | | libcurl: partial password leak | | | | | | | over DNS on HTTP redirect | + +------------------+ + +-----------------------+--------------------------------------------------------------+ | | CVE-2020-8177 | | | | curl: Incorrect argument check | | | | | | | can allow remote servers to | | | | | | | overwrite local files... | + +------------------+ + +-----------------------+--------------------------------------------------------------+ | | CVE-2020-8231 | | | | curl: Expired pointer | | | | | | | dereference via multi API with | | | | | | | `CURLOPT_CONNECT_ONLY` option | | | | | | | set | + +------------------+ + +-----------------------+--------------------------------------------------------------+ | | CVE-2020-8285 | | | | curl: malicious FTP server can | | | | | | | trigger stack overflow when | | | | | | | CURLOPT_CHUNK_BGN_FUNCTION is | | | | | | | used... | + +------------------+ + +-----------------------+--------------------------------------------------------------+ | | CVE-2020-8286 | | | | curl: inferior OCSP | | | | | | | verification | +------------------+------------------+ +-----------------------+-----------------------+--------------------------------------------------------------+ | gcc-8-base | CVE-2018-12886 | | 8.3.0-6 | | gcc: spilling of stack | ...(snip)...
オプションあり
$ trivy --severity=HIGH,CRITICAL --ignore-unfixed=true nginx chore/change-workflow 2020-12-27T11:46:46.067+0900 WARN You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed 2020-12-27T11:46:46.156+0900 INFO Detecting Debian vulnerabilities... nginx (debian 10.5) =================== Total: 17 (HIGH: 17, CRITICAL: 0) +------------------+------------------+----------+-----------------------+-----------------------+------------------------------------+ | LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE | +------------------+------------------+----------+-----------------------+-----------------------+------------------------------------+ | libgssapi-krb5-2 | CVE-2020-28196 | HIGH | 1.17-3 | 1.17-3+deb10u1 | krb5: unbounded recursion | | | | | | | via an ASN.1-encoded | | | | | | | Kerberos message in | | | | | | | lib/krb5/asn.1/asn1_encode.c | | | | | | | may lead... | +------------------+------------------+ +-----------------------+-----------------------+------------------------------------+ | libjpeg62-turbo | CVE-2020-13790 | | 1:1.5.2-2 | 1:1.5.2-2+deb10u1 | libjpeg-turbo: heap-based | | | | | | | buffer over-read in | | | | | | | get_rgb_row() in rdppm.c | +------------------+------------------+ +-----------------------+-----------------------+------------------------------------+ ...(snip)...
このように --ignore-unfixed
オブションをつけるとディストリビューションで未対応の脆弱性がフィルタされて、検出件数が 51 から 17 になりました。
また、Trivy ではカーネルの脆弱性を検出しなかったのですが、これは ECR Image scanning とスキャン方法が違うことに起因してるんですかねー。(強いひと教えて)
GitHub Actions のワークフローに組み込む
Trivy の GitHub Action があるので GitHub Actions で CI 環境を構築している方はすぐに導入できます。
私が携わっている案件では、以下のようなワークフローファイルを書いて、ビルドしたコンテナイメージを ECR から引っ張ってきてスキャンするようにしています。
...(sinp)... container-security-scan: needs: build runs-on: ubuntu-latest env: ECR_REPOSITORY_IMAGE_TAGGED: ${{ needs.build.outputs.repository_url }} steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_ACCESS_SECRET_KEY }} aws-region: ap-northeast-1 - name: Login to Amazon ECR uses: aws-actions/amazon-ecr-login@v1 - name: Pull Docker image run: | docker pull $ECR_REPOSITORY_IMAGE_TAGGED - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: ${{ env.ECR_REPOSITORY_IMAGE_TAGGED }} format: "table" exit-code: "1" ignore-unfixed: true severity: "CRITICAL,HIGH"
おわりに
今のところ Trivy には満足しています。