Docker SBOM: Keeping a Check on Security Risks

0
733
Docker-SBOM

The Log4j vulnerability and SolarWinds supply chain attack have made us realise that software supply chains are at great risk of being targeted by attackers. The Docker SBOM helps detect these risks.

Software supply chain security comprises everything required to build, deliver and run software anywhere with confidence. It ensures that not only software but the infrastructure, operating systems, source code repositories, registries, developers who wrote it, and the cloud services it uses don’t pose any threats.

The Software Bill of Materials (SBOM) has emerged as the first step to ensure software security.

What is SBOM and how does it help businesses?

An SBOM is a list of software components that build the software product. It details the software package, content, licence, and certificate information, just like packaged food items contain ingredients and other information.

SBOMs help organisations know and keep track of all software components along with other details, such as:

  • Determining all the runtime dependencies of the software
  • Keeping track of critical updates and patches
  • Reducing supply chain attacks and ensuring the organisation doesn’t use vulnerable components
  • Detecting licence and certificate-related issues

The National Telecommunications and Information Administration (NTIA) has listed the minimum requirements for the SBOM, which are:

  • Software supplier and author of SBOM
  • Information about software vendors
  • Software component name and its version
  • Unique identifier for each component
  • Relationship of the component with other components and packages
  • Time stamp of SBOM creation

SBOM standards

To make organisations adopt SBOM quickly, several standards have been defined for generating them. A defined schema provides a format for listing software components, and the most widely used are Software Package Data Exchange (SPDX) and CycloneDX.

SPDX: SPDX is an SBOM format developed by the Linux Foundation. It shows relationships between software components, licences, and copyrights associated with the software. It can be stored in different file formats, such as SPDX and JSON. It defines three elements: documents (metadata about the SBOM), packages (groups of elements), and files (single files).

CycloneDX: This lightweight SBOM standard is maintained by the OWASP community and built on top of SPDX. It gives security-related information such as supplier, manufacturer, target components, etc. It can be stored in different file formats, such as XML and JSON. It gets divided into components, services, and dependencies.

Docker, too, has recently introduced an SBOM format for container images. It has announced the docker sbom CLI command in Docker Desktop 4.7.0 as a CLI plugin, which lists all the components of the container image. It is an experimental functionality for now, which has been developed as an open source collaboration with Anchore through the Syft tool.

Syft is a tool for generating SBOMs from container images and file systems. It can convert SBOMs to different formats.

Figure 1: Different sub-commands with docker sbom
Figure 1: Different sub-commands with docker sbom

Installation of the Docker CLI plugin

  • As a pre-requisite, Docker/Docker Desktop must be installed on your system. Upgrade the Docker desktop if its version is less than 4.7.0.
  • Install the docker sbom plugin.
curl -sSfL https://raw.githubusercontent.com/docker/sbom-cli-plugin/main/install.sh | sh -s —
  • Check its version and verify installation:
docker sbom version
Note: If you are using Docker as a CLI tool, then before installing docker sbom create a /root/.docker directory. More information can be found at https://github.com/docker/sbom-cli-plugin/issues/25.

Different Docker SBOM commands

  • To check all options related to docker sbom, type:
docker sbom —help

To list the software components of an NGINX Docker image, type:

docker sbom —help

By default, the output will be in a table format. From the output given below, it can be inferred that the first image is pulled if not present locally, then it’s loaded and processed further, and then the software elements get listed along with its version and package type.

root@master:~# docker sbom nginx:latest
Syft v0.46.3
√ Pulled image           
√ Loaded image           
√ Parsed image           
 Cataloged packages     
[143 packages]
NAME                       VERSION                         TYPE        
adduser                    3.118                           deb          
apt                        2.2.4                           deb          
base-files                 11.1+deb11u5                    deb          
base-passwd                3.5.51                          deb          
bash                       5.1-2+deb11u1                   deb          
bsdutils                   1:2.36.1-8+deb11u1              deb          
ca-certificates            20210119                        deb          
coreutils                  8.32-4+b1                       deb          
curl                       7.74.0-1.3+deb11u3              deb          
dash                       0.5.11+git20200708+dd9ef66-5    deb          
debconf                    1.5.77                          deb          
debian-archive-keyring     2021.1.1                        deb          
debianutils                4.11.2                          deb          
diffutils                  1:3.7-5                         deb          
dpkg                       1.20.12                         deb          
. . .                      . . .                           . . .
ncurses-bin                6.2+20201114-2                  deb          
nginx                      1.23.2-1~bullseye               deb          
nginx-module-geoip         1.23.2-1~bullseye               deb          
nginx-module-image-filter  1.23.2-1~bullseye               deb          
nginx-module-njs           1.23.2+0.7.7-1~bullseye         deb          
nginx-module-xslt          1.23.2-1~bullseye               deb          
openssl                    1.1.1n-0+deb11u3                deb          
passwd                     1:4.8.1-1                       deb          
perl-base                  5.32.1-4+deb11u2                deb          
readline-common            8.1-1                           deb          
sed                        4.7-1                           deb          
sensible-utils             0.0.14                          deb          
sysvinit-utils             2.96-7+deb11u1                  deb          
tar                        1.34+dfsg-1                     deb          
tzdata                     2021a-1+deb11u8                 deb          
ucf                        3.0043                          deb          
util-linux                 2.36.1-8+deb11u1                deb          
zlib1g                     1:1.2.11.dfsg-2+deb11u2         deb
  • To list the software components of a Node.js application, type:
docker sbom oshi36/nodeapp_test:latest
root@master:~# docker sbom oshi36/nodeapp_test:latest
Syft v0.46.3
 Loaded image           
 Parsed image           
 Cataloged packages      [569 packages]
NAME                              VERSION      TYPE
JSONStream                        1.3.5        npm  
abbrev                            1.1.1        npm  
accepts                           1.3.8        npm  
agent-base                        4.2.1        npm  
agent-base                        4.3.0        npm  
agentkeepalive                    3.5.2        npm  
ajv                               5.5.2        npm  
. . .                             . . .        . . .
wrappy                            1.0.2        npm  
write-file-atomic                 2.4.3        npm  
xdg-basedir                       3.0.0        npm  
xtend                             4.0.1        npm  
y18n                              3.2.1        npm  
y18n                              4.0.0        npm  
yallist                           2.1.2        npm  
yallist                           3.0.3        npm  
yargs                             11.1.1       npm  
yargs-parser                      9.0.2        npm  
yarn                              1.22.4       npm  
zlib                              1.2.11-r3    apk
  • To write the SBOM report to a file, use the output flag:
docker sbom oshi36/nodeapp_test:latest —output nodeapp_report

Open the output file nodeapp_report:

cat nodeapp_report
  • To skip paths from docker sbom to scan, use the exclude flag:

From the output given below, it can be seen that docker sbom leaves the elements to be scanned at the /usr/local location.

docker sbom oshi36/nodeapp_test:latest —exclude /usr/local
Syft v0.46.3
√ Loaded image           
√ Parsed image           
√ Cataloged packages      [132 packages]
NAME                    VERSION      TYPE
accepts                 1.3.8        npm  
alpine-baselayout       3.2.0-r3     apk  
alpine-keys             2.1-r2       apk  
apk-tools               2.10.5-r0    apk  
array-flatten           1.1.1        npm  
body-parser             1.20.1       npm  
busybox                 1.31.1-r9    apk  
bytes                   3.1.2        npm  
ca-certificates-cacert  20191127-r1  apk  
call-bind               1.0.2        npm  
content-disposition     0.5.4        npm  
content-type            1.0.4        npm  
cookie                  0.5.0        npm  
cookie-signature        1.0.6        npm  
debug                   2.6.9        npm  
depd                    2.0.0        npm  
destroy                 1.2.0        npm  
ee-first                1.1.1        npm  
encodeurl               1.0.2        npm  
escape-html             1.0.3        npm  
etag                    1.8.1        npm  
. . .                   . . .        . . .  
 
utils-merge             1.0.1        npm  
vary                    1.1.2        npm  
yarn                    1.22.4       npm  
zlib                    1.2.11-r3    apk
  • To get the SBOM of platform-specific container images such as linux/arm64, arm64, etc, use the platform flag:
docker sbom nginx:alpine —platform linux/arm64
  • To get the SBOM report in different SBOM formats such as spdx-json, cyclonedx-json, syft-json, etc, use the format flag:
docker sbom oshi36/nodeapp_test:latest —format spdx-json

In this format, a unique identifier SPDXID is provided for each package and file, along with information about the licence:

{
 "SPDXID": "SPDXRef-DOCUMENT",
 "name": "oshi36/nodeapp_test-latest",
 "spdxVersion": "SPDX-2.2",
 "creationInfo": {
  "created": "2022-12-06T07:40:44.279888063Z",
  "creators": [
   "Organization: Anchore, Inc",
   "Tool: syft-v0.46.3"
  ],
  "licenseListVersion": "3.17"
 },
 "dataLicense": "CC0-1.0",
 "documentNamespace": "https://anchore.com/syft/image/oshi36/nodeapp_test-latest-e729521b-fa8b-43cf-b402-8bde95b26c1f",
 "packages": [
  {
   "SPDXID": "SPDXRef-2a0a99c2a38a6407",
   "name": "JSONStream",
   "licenseConcluded": "NOASSERTION",
   "downloadLocation": "git://github.com/dominictarr/JSONStream.git",
   "externalRefs": [
    {
     "referenceCategory": "SECURITY",
     "referenceLocator": "cpe:2.3:a:JSONStream:JSONStream:1.3.5:*:*:*:*:*:*:*",
     "referenceType": "cpe23Type"
    },
    {
     "referenceCategory": "SECURITY",
     "referenceLocator": "cpe:2.3:a:*:JSONStream:1.3.5:*:*:*:*:*:*:*",
     "referenceType": "cpe23Type"
    },
    {
     "referenceCategory": "PACKAGE_MANAGER",
     "referenceLocator": "pkg:npm/JSONStream@1.3.5",
     "referenceType": "purl"
    }
   ], . . . .
 
docker sbom oshi36/nodeapp_test:latest —format cyclonedx-json

This format has details about supplier, manufacturer and BOM creation tools, along with the component type and its version in the hash.

{
 "SPDXID": "SPDXRef-DOCUMENT",
 "name": "oshi36/nodeapp_test-latest",
 "spdxVersion": "SPDX-2.2",
 "creationInfo": {
  "created": "2022-12-06T07:40:44.279888063Z",
  "creators": [
   "Organization: Anchore, Inc",
   "Tool: syft-v0.46.3"
  ],
  "licenseListVersion": "3.17"
 },
 "dataLicense": "CC0-1.0",
 "documentNamespace": "https://anchore.com/syft/image/oshi36/nodeapp_test-latest-e729521b-fa8b-43cf-b402-8bde95b26c1f",
 "packages": [
  {
   "SPDXID": "SPDXRef-2a0a99c2a38a6407",
   "name": "JSONStream",
   "licenseConcluded": "NOASSERTION",
   "downloadLocation": "git://github.com/dominictarr/JSONStream.git",
   "externalRefs": [
    {
     "referenceCategory": "SECURITY",
     "referenceLocator": "cpe:2.3:a:JSONStream:JSONStream:1.3.5:*:*:*:*:*:*:*",
     "referenceType": "cpe23Type"
    },
    {
     "referenceCategory": "SECURITY",
     "referenceLocator": "cpe:2.3:a:*:JSONStream:1.3.5:*:*:*:*:*:*:*",
     "referenceType": "cpe23Type"
    },
    {
     "referenceCategory": "PACKAGE_MANAGER",
     "referenceLocator": "pkg:npm/JSONStream@1.3.5",
     "referenceType": "purl"
    }
   ], . . . .
 
docker sbom oshi36/nodeapp_test:latest —format cyclonedx-json

This format has details about supplier, manufacturer and BOM creation tools, along with the component type and its version in the hash.

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:c52d49b5-ee5f-46c8-8767-b5f27cdd990e",
  "version": 1,
  "metadata": {
    "timestamp": "2022-12-06T07:43:12Z",
    "tools": [
      {
        "vendor": "anchore",
        "name": "syft",
        "version": "v0.46.3"
      }
    ],
    "component": {
      "bom-ref": "3c49c5c51b864d3e",
      "type": "container",
      "name": "oshi36/nodeapp_test:latest",
      "version": "sha256:d1e152be03b2b120ffd969eb276d59876ae6e7e91510915d6080f0b5c36f1f02"
    }
  },
. . . .
docker sbom oshi36/nodeapp_test:latest —format syft-json

It outputs the SBOM report in Syft’s native JSON format:

{
 "artifacts": [
  {
   "id": "2a0a99c2a38a6407",
   "name": "JSONStream",
   "version": "1.3.5",
   "type": "npm",
   "foundBy": "javascript-package-cataloger",
   "locations": [
    {
     "path": "/usr/local/lib/node_modules/npm/node_modules/JSONStream/package.json",
     "layerID": "sha256:8ca4f4055a7095ff1807ce521287ae7bdd91aa711ae45d5b0f3d1c45ab0adefe"
    }
   ],
   "licenses": [
    "(MIT OR Apache-2.0)"
   ],
   "language": "javascript",
   "cpes": [
    "cpe:2.3:a:JSONStream:JSONStream:1.3.5:*:*:*:*:*:*:*",
    "cpe:2.3:a:*:JSONStream:1.3.5:*:*:*:*:*:*:*"
   ],
   "purl": "pkg:npm/JSONStream@1.3.5",
   "metadataType": "NpmPackageJsonMetadata",
   "metadata": {
    "name": "JSONStream",
    "version": "1.3.5",
    "author": "Dominic Tarr <dominic.tarr@gmail.com> (http://bit.ly/dominictarr)",
    "licenses": [
     "(MIT OR Apache-2.0)"
    ],
. . . .

Log4j 2 vulnerability use case

Log4j 2 is a logging library by Apache and its vulnerability CVE-2021-44228 allows remote code execution from a context that is easily available to an attacker. This vulnerability has been found in Minecraft servers. It allows commands to be typed in chat logs and then sent to the logger.

Currently, CVE-2021-44228 impacts all versions of Log4j 2.x <= 2.14.1. If the container image has Log4j, then can help in finding out its version and deciding whether it’s vulnerable or not.

  • To list the components of jboss/wildfly application server and find whether its Log4j version is vulnerable or not, type:
docker sbom jboss/wildfly | grep log4j

From the output given below it can be seen clearly that Log4j is vulnerable to CVE-2021-44228 due to its version:

1
2
3
4
5
6
7
8
9
10
docker sbom jboss/wildfly | grep log4j
Syft v0.46.3
 Pulled image           
 Loaded image           
 Parsed image           
 Cataloged packages      [1151 packages]
log4j-api                                                     2.14.1                    java-archive 
log4j-jboss-logmanager                                        1.2.2.Final               java-archive 
log4j2-jboss-logmanager                                       1.0.0.Final
              java-archive

To sum up, docker sbom helps in generating the SBOM for the container image, which helps identify and solve any dependency issues.