How to use Anchore Inline Image Scanning
By Toul DeGuia-Cranmer
DevOps Engineer
HP Inc. in Houston
Quick Links
- Introduction
- Setup
- Scanning a Local Docker Image with Anchore
- Analysis of results
- How to address the CVE's
1. Introduction
Anchore is a tool that scans Docker images for common vulnerabilities and not so common vulnerabilities if you purchase the paid version. However, the free version is useful and should still be used on your team to avoid the common vulnerabilities.Thankfully, the Anchore team is nice enough to have created an entire shell script to both install the Anchore Database locally and run the Anchore CLI all in one line.
2. Set-up
The only prerequisite is to have Docker installed and a docker image to scan against.
So, pull the latest python based Django image by running the following command.
>$ docker pull django:latest latest: Pulling from library/django 75a822cd7888: Pull complete e4665cede9d1: Pull complete 202a45aa091c: Pull complete 7799136eb561: Pull complete 7a7f9ca3fd40: Pull complete 412f2d081014: Pull complete Digest: sha256:5bfd3f442952463f5bc97188b7f43cfcd6c2f631a017ee2a6fca3cb8992501e8 Status: Downloaded newer image for django:latest docker.io/library/django:latest
3. Scanning a Local Docker Image with Anchore
Now, to scan the image it is as simple as running the below command.
> $ curl -s https://ci-tools.anchore.io/inline_scan-v0.6.0 | bash -s -- -r django:latest Pulling docker.io/anchore/inline-scan:v0.6.0 v0.6.0: Pulling from anchore/inline-scan c8d67acdb2ff: Pulling fs layer 79d11c1a86c4: Pulling fs layer 29e401ba63ed: Pulling fs layer 80ebc2cb4bb5: Pulling fs layer cc792e3974ef: Pulling fs layer ab823a13986c: Pulling fs layer 2804f93eb9d5: Pulling fs layer 5f2abe590f8b: Pulling fs layer f75fc16c556e: Pulling fs layer b76fb0e96d28: Pulling fs layer 88f36ce1e581: Pulling fs layer e0d96f1cdcf6: Pulling fs layer 9c15e755f25a: Pulling fs layer 99f9e30d756f: Pulling fs layer e0467da0b2f4: Pulling fs layer 29f72f52071b: Pulling fs layer f47649d81f49: Pulling fs layer 80ebc2cb4bb5: Waiting cc792e3974ef: Waiting ab823a13986c: Waiting 2804f93eb9d5: Waiting 5f2abe590f8b: Waiting f75fc16c556e: Waiting b76fb0e96d28: Waiting 88f36ce1e581: Waiting e0d96f1cdcf6: Waiting 9c15e755f25a: Waiting 99f9e30d756f: Waiting e0467da0b2f4: Waiting 29f72f52071b: Waiting f47649d81f49: Waiting 79d11c1a86c4: Download complete 80ebc2cb4bb5: Verifying Checksum 80ebc2cb4bb5: Download complete cc792e3974ef: Verifying Checksum cc792e3974ef: Download complete ab823a13986c: Download complete 2804f93eb9d5: Download complete 29e401ba63ed: Verifying Checksum 29e401ba63ed: Download complete f75fc16c556e: Verifying Checksum f75fc16c556e: Download complete b76fb0e96d28: Verifying Checksum b76fb0e96d28: Download complete 88f36ce1e581: Verifying Checksum 88f36ce1e581: Download complete 5f2abe590f8b: Verifying Checksum 5f2abe590f8b: Download complete c8d67acdb2ff: Verifying Checksum c8d67acdb2ff: Download complete 99f9e30d756f: Verifying Checksum 99f9e30d756f: Download complete e0467da0b2f4: Verifying Checksum e0467da0b2f4: Download complete 29f72f52071b: Verifying Checksum 29f72f52071b: Download complete e0d96f1cdcf6: Verifying Checksum e0d96f1cdcf6: Download complete f47649d81f49: Verifying Checksum f47649d81f49: Download complete c8d67acdb2ff: Pull complete 79d11c1a86c4: Pull complete 29e401ba63ed: Pull complete 80ebc2cb4bb5: Pull complete cc792e3974ef: Pull complete ab823a13986c: Pull complete 2804f93eb9d5: Pull complete 5f2abe590f8b: Pull complete f75fc16c556e: Pull complete b76fb0e96d28: Pull complete 88f36ce1e581: Pull complete e0d96f1cdcf6: Pull complete 9c15e755f25a: Verifying Checksum 9c15e755f25a: Download complete 9c15e755f25a: Pull complete 99f9e30d756f: Pull complete e0467da0b2f4: Pull complete 29f72f52071b: Pull complete f47649d81f49: Pull complete Digest: sha256:13276a0fdc98cc40b70814c2d83c8c6400e9da2939c6256bc221ada40f9f8a28 Status: Downloaded newer image for anchore/inline-scan:v0.6.0 docker.io/anchore/inline-scan:v0.6.0 Starting Anchore Engine Starting Postgresql... Postgresql started successfully! Starting Docker registry... Docker registry started successfully! Waiting for Anchore Engine to be available. Status: not_ready... Anchore Engine is available! Preparing django:latest for analysis Getting image source signatures Copying blob sha256:b6ca02dfe5e62c58dacb1dec16eb42ed35761c15562485f9da9364bb7c90b9b3 122.93 MB / 122.93 MB 8s Copying blob sha256:40cc5c729ee12cbf17805f72beb035b2356a9e0a4ec7926a258355fa3713c0dd 7.65 MB / 7.65 MB 0s Copying blob sha256:f72299e7fd5a1ae319466b83cadd42abe15661fd2cf9afa92f49cdd7a534df51 62.12 MB / 62.12 MB 3s Copying blob sha256:4bd3b46a8734dd8cb6f7fee98cb9c9084a9ce4dd0242c9f7659b0f2c660f5692 5.00 KB / 5.00 KB 0s Copying blob sha256:6d0632e611f48587e00a3c093d4afddcbc637995122666b65e08a637ef1603a6 198.79 MB / 198.79 MB 23s Copying blob sha256:e6d982acf7bfa32b3d8187f4e3a680726c5b11fcf49571f92582289198948309 39.89 MB / 39.89 MB 2s Copying config sha256:eb40dcf64078249a33f68fdd8d80624cb81b524c24f50b95fff5c2b40bdc3fdc 6.12 KB / 6.12 KB 0s Writing manifest to image destination Storing signatures Image archive loaded into Anchore Engine using tag -- django:latest Waiting for analysis to complete... Status: not_analyzed. Status: analyzing.................. Status: analyzed Analysis completed! Successfully generated anchore-reports/django_latest-content-os.json. Successfully generated anchore-reports/django_latest-content-python.json. Successfully generated anchore-reports/django_latest-content-java.json. Successfully generated anchore-reports/django_latest-content-files.json. Successfully generated anchore-reports/django_latest-vuln.json. Successfully generated anchore-reports/django_latest-details.json. Successfully generated anchore-reports/django_latest-policy.json. Policy Evaluation - django:latest ----------------------------------------------------------- Image Digest: sha256:84312a8bc641a87981190cc25bbe0e24276e6ef54f8c7fb6b47f83f996514e3b Full Tag: localhost:5000/django:latest Image ID: eb40dcf64078249a33f68fdd8d80624cb81b524c24f50b95fff5c2b40bdc3fdc Status: fail Last Eval: 2020-03-09T15:05:29Z Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060 Final Action: stop Final Action Reason: policy_evaluation Gate Trigger Detail Status dockerfile instruction Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check warn vulnerabilities package MEDIUM Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2017-12794 - https://nvd.nist.gov/vuln/detail/CVE-2017-12794) warn vulnerabilities package MEDIUM Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2017-7233 - https://nvd.nist.gov/vuln/detail/CVE-2017-7233) warn vulnerabilities package MEDIUM Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2017-7234 - https://nvd.nist.gov/vuln/detail/CVE-2017-7234) warn vulnerabilities package CRITICAL Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2019-19844 - https://nvd.nist.gov/vuln/detail/CVE-2019-19844) stop Copying scan reports from 14508-inline-anchore-engine to /c/Users/deguiacr/anchore-reports/ Cleaning up docker container: 14508-inline-anchore-engine
4. Analysis of Results
In the bottom portion of the output from the scan there are links to the common vulnerabilities and exposures webpages with the important pieces of information. The first one that stands out is the CRITICAL vulnerability which is directly related to the version of python (3.4) and the Django package available within it. By copying and pasting the URL to the vulnerability it can be observed what the vulnerability is, which is to have user's accounts taken over if the version of Django is between 1.11.27 and 3.0.1.
Gate Trigger Detail Status dockerfile instruction Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check warn vulnerabilities package MEDIUM Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2017-12794 - https://nvd.nist.gov/vuln/detail/CVE-2017-12794) warn vulnerabilities package MEDIUM Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2017-7233 - https://nvd.nist.gov/vuln/detail/CVE-2017-7233) warn vulnerabilities package MEDIUM Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2017-7234 - https://nvd.nist.gov/vuln/detail/CVE-2017-7234) warn vulnerabilities package CRITICAL Vulnerability found in non-os package type (python) - /usr/local/lib/python3.4/site-packages/Django (CVE-2019-19844 - https://nvd.nist.gov/vuln/detail/CVE-2019-19844) stop
5. How to address the CVE's
The reason there are so many CVE's to begin with is that the docker image django:latest is no longer maintained. Meaning, no one is updating the image to address the CVE's. In general it is not good practice to use third-party images. So to address the CVE's a python official docker image will be used as a base and Django 3.0.4 will be installed on the image.
Create the following Dockerfile
# Dockerfile # The first instruction is what image we want to base our container on FROM python:3.8.2-slim-buster ENV PYTHONUNBUFFERED 1 # create root directory for our project in the container RUN mkdir /wrk # Set the working directory to /music_service WORKDIR /wrk # Copy the current directory contents into the container at /music_service ADD . /wrk/ # Install any needed packages specified in requirements.txt RUN pip install -r requirements.txt
and the following requirements.txt
# requirements.txt Django==3.0.4
Now build the docker image and tag it as django:latest
>$ docker build . -t django:test
and then run an Anchore Inline scan against it.
$ curl -s https://ci-tools.anchore.io/inline_scan-v0.6.0 | bash -s -- -r django:test Pulling docker.io/anchore/inline-scan:v0.6.0 v0.6.0: Pulling from anchore/inline-scan Digest: sha256:13276a0fdc98cc40b70814c2d83c8c6400e9da2939c6256bc221ada40f9f8a28 Status: Image is up to date for anchore/inline-scan:v0.6.0 docker.io/anchore/inline-scan:v0.6.0 Starting Anchore Engine Starting Postgresql... Postgresql started successfully! Starting Docker registry... Docker registry started successfully! Waiting for Anchore Engine to be available. Status: not_ready.. Anchore Engine is available! Preparing django:test for analysis Getting image source signatures Copying blob sha256:f2cb0ecef392f2a630fa1205b874ab2e2aedf96de04d0b8838e4e728e28142da 69.12 MB / 69.12 MB 4s Copying blob sha256:bdc3a0723efad857856e4b39be542e4019b21be175fa125799b7f20ecba677ee 6.98 MB / 6.98 MB 0s Copying blob sha256:64b4e3ecc0d6402f0f2125e49fad276e3556fbabcc04954965a64ce43b52a201 105.46 MB / 105.46 MB 6s Copying blob sha256:df4dc71f749c287bddf0c42b813bd96a27dfdad6c3850c92d394883b795a1e24 4.50 KB / 4.50 KB 0s Copying blob sha256:fe108eef54ea6e8c465bc1f6ddfbedde6cc41af69a930215ff381211983d5154 7.63 MB / 7.63 MB 0s Copying blob sha256:83aa36b21c9979cbcb25082dc2a45b5f0c14a31bd8a4257718d67856f71a3380 1.50 KB / 1.50 KB 0s Copying blob sha256:0290a4ca1adc8d3e32e05b51cc9bc0c3702692d27f760d620e463c4a69fc121b 3.50 KB / 3.50 KB 0s Copying blob sha256:a2f0a3adf092287ca4dd477d3bc4cac7de5df62412da242e1437c5f8eba72de0 42.01 MB / 42.01 MB 2s Copying config sha256:29ac1eb77b196e168ddd2a88f7ab21373819805219320ba34aa8b603aefa1713 8.21 KB / 8.21 KB 0s Writing manifest to image destination Storing signatures Image archive loaded into Anchore Engine using tag -- django:test Waiting for analysis to complete... Status: not_analyzed Status: analyzing.......... Status: analyzed Analysis completed! Successfully generated anchore-reports/django_test-content-os.json. Successfully generated anchore-reports/django_test-content-python.json. Successfully generated anchore-reports/django_test-content-files.json. Successfully generated anchore-reports/django_test-vuln.json. Successfully generated anchore-reports/django_test-details.json. Successfully generated anchore-reports/django_test-policy.json. Policy Evaluation - django:test ----------------------------------------------------------- Image Digest: sha256:84de5ca329d5963798aedf72e73673277a0f04ebf0daf81599941d18e6166dda Full Tag: localhost:5000/django:test Image ID: 29ac1eb77b196e168ddd2a88f7ab21373819805219320ba34aa8b603aefa1713 Status: pass Last Eval: 2020-03-09T16:05:29Z Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060 Final Action: warn Final Action Reason: policy_evaluation Gate Trigger Detail Status dockerfile instruction Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check warn Copying scan reports from 19436-inline-anchore-engine to /c/Users/deguiacr/anchore-reports/ Cleaning up docker container: 19436-inline-anchore-engine
Conclusion
Now, there's no excuse to not build and use secure docker images.