0% found this document useful (0 votes)
30 views58 pages

Docker IT Audit

This document provides guidance for establishing a secure configuration for Docker Engine v26.1.4, targeting system administrators and security personnel. It includes best practices for host machine preparation, auditing configurations, and ensuring Docker is up to date. Additionally, it outlines security settings for the Docker daemon to enhance overall security and mitigate vulnerabilities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as XLSX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views58 pages

Docker IT Audit

This document provides guidance for establishing a secure configuration for Docker Engine v26.1.4, targeting system administrators and security personnel. It includes best practices for host machine preparation, auditing configurations, and ensuring Docker is up to date. Additionally, it outlines security settings for the Docker daemon to enhance overall security and mitigate vulnerabilities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as XLSX, PDF, TXT or read online on Scribd
You are on page 1/ 58

This document provides presrciptive guidance for establishing a secure

configration posture for Docker Engine v26.1.4 and intended for system and
application administrators, security specialists, auditors, help desk, and platform
deployment personnel who plan to develop, deploy, assess, or secure solutions
that incorporate Docker Engine 26.1 or later technology on Linux based platforms.
This section covers security recommendations that you should follow to prepare the host machine that you plan to us
infrastructure
Control security
Control namebest practices would buildDescription
a solid and secure foundation for executing containerized workloads
ref.
1.1.1 Ensure separate partition for containers Create a separate partition for
/var/lib/docker.

1.1.2 Ensure only trusted users control Ensure only trusted users are part of the
Docker daemon docker group.

1.1.3 Ensure auditing is configured for Audit all Docker daemon activities.
Docker daemon
1.1.4 Ensure auditing is configured for Audit /run/containerd directory.
/run/containerd

1.1.5 Ensure auditing is configured for Audit /var/lib/docker directory.


/var/lib/docker

1.1.6 Ensure auditing is configured for Audit /etc/docker directory.


/etc/docker

1.1.7 Ensure auditing is configured for Audit docker.service file.


docker.service

1.1.8 Ensure auditing is configured for Audit containerd.sock file.


containerd.sock

1.1.9 Ensure auditing is configured for Audit docker.sock file.


docker.sock

1.1.10 Ensure auditing is configured for Audit /etc/default/docker file.


/etc/default/docker

1.1.11 Ensure auditing is configured for Audit /etc/docker/daemon.json file.


/etc/docker/daemon.json
1.1.12 Ensure auditing is configured for Audit /etc/containerd/config.toml file.
/etc/containerd/config.toml

1.1.13 Ensure auditing is configured for Audit /etc/sysconfig/docker file.


/etc/sysconfig/docker

1.1.14 Ensure auditing is configured for Audit /usr/bin/containerd file.


/usr/bin/containerd

1.1.15 Ensure auditing is configured for Audit /usr/bin/containerd-shim file.


/usr/bin/containerd-shim

1.1.16 Ensure auditing is configured for Audit /usr/bin/containerd-shim-runc-v1 file.


/usr/bin/containerd-shim-runc-v1

1.1.17 Ensure auditing is configured for Audit /usr/bin/containerd-shim-runc-v2 file.


/usr/bin/containerd-shim-runc-v2

1.1.18 Ensure auditing is configured for Audit /usr/bin/runc file.


/usr/bin/runc

1.2.1 Ensure the container host has been A container host is able to run one or
Hardened (Manual) more containers. It is of utmost
importance to harden the host to mitigate
host security misconfiguration.

1.2.2 Ensure that the version of Docker is up Frequent releases for Docker are issued
to date (Manual) which address security vulnerabilities,
resolve product bugs and bring in new
functionality. You should keep a tab on
these product updates and upgrade as
frequently as possible in line with the
general IT security policy of your
organization.
are the host machine that you plan to use for executing containerized workloads. Securing the Docker host and following your
n for executing
Auditcontainerized
Check workloads. Remediation steps (if not compliant)
Check partition configuration. For new installations, create a
separate partition for /var/lib/docker.
At the Docker host execute one of the below For existing systems, use Logical
commands: Volume Manager (LVM) within Linux to
grep '/var/lib/docker\s' /proc/mounts create a new partition.

This should return the partition details for the


/var/lib/docker mountpoint.
mountpoint -- "$(docker info -f
'{{ .DockerRootDir }}')"

This should return whether the configured root


directory is a mount point.

Execute the following command on the docker host: Remove untrusted users from the
getent group docker. docker group and do not map sensitive
Ensure only trusted users are members. directories from host to container.
Verify audit rules for Docker daemon using: Add audit rules for Docker daemon and
auditctl -l | grep /usr/bin/dockerd. restart auditd if not compliant.
Verify audit rules using: Add an audit rule for /run/containerd
auditctl -l | grep /run/containerd. in /etc/audit/rules.d/audit.rules and
restart auditd.
Verify audit rules using: Add an audit rule for /var/lib/docker
auditctl -l | grep /var/lib/docker. in /etc/audit/rules.d/audit.rules and
restart auditd.
Verify audit rules using: Add an audit rule for /etc/docker in
auditctl -l | grep /etc/docker. /etc/audit/rules.d/audit.rules and restart
auditd.
Find file location: If the file exists, add an audit rule for
systemctl show -p FragmentPath docker.service docker.service in
If file exists, check audit rules: /etc/audit/rules.d/audit.rules and restart
auditctl -l | grep docker.service. auditd.
Find file location: If the file exists, add an audit rule for
grep 'containerd.sock' /etc/containerd/config.toml containerd.sock in
If file exists, check audit rules: /etc/audit/rules.d/audit.rules and restart
auditctl -l | grep containerd.sock auditd.
Find file location: If the file exists, add an audit rule for
systemctl show -p FragmentPath docker.sock docker.sock in
Locate socket file: /etc/audit/rules.d/audit.rules and restart
grep ListenStream <FragmentPath> auditd.
Check audit rules:
auditctl -l | grep docker.sock.

Check audit rules: If not audited, add an audit rule for


auditctl -l | grep /etc/default/docker. /etc/default/docker in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /etc/docker/daemon.json. /etc/docker/daemon.json in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /etc/containerd/config.toml. /etc/containerd/config.toml in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /etc/sysconfig/docker. /etc/sysconfig/docker in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /usr/bin/containerd. /usr/bin/containerd in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /usr/bin/containerd-shim. /usr/bin/containerd-shim in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /usr/bin/containerd-shim-runc-v1. /usr/bin/containerd-shim-runc-v1 in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /usr/bin/containerd-shim-runc-v2. /usr/bin/containerd-shim-runc-v2 in
/etc/audit/rules.d/audit.rules and restart
auditd.
Check audit rules: If not audited, add an audit rule for
auditctl -l | grep /usr/bin/runc. /usr/bin/runc in
/etc/audit/rules.d/audit.rules and restart
auditd.
Ensure that the host specific security guidelines are You may consider various CIS Security
followed. Ask the system administrators which security Benchmarks for your container host. If
benchmark the current host system should currently be you have other security guidelines or
compliant with and check that security standards regulatory requirements to adhere to,
associated with this standard are currently in place. please follow them as suitable in your
environment.

By staying up to date on Docker updates, You should monitor versions of Docker


vulnerabilities in the software can be mitigated. An releases and make sure your software
experienced attacker may be able to exploit known is updated as required.
vulnerabilities resulting in them being able to attain
inappropriate access or to elevate their privileges. If
you do not ensure that Docker is running at the most
current release consistent with the requirements of of
your application, you may introduce unwanted
behaviour and it is therefore important to ensure that
you monitor software versions and upgrade in a timely
fashion.

You should execute the command below in order to


verify that the Docker version is up to date in line with
the requirements of the application you are running. It
should be noted that it is not a security requirement to
be at the most up to date version, provided the version
you are using does not contain any critical or high
security vulnerabilities. docker version
g the Docker host and following your
Default value Compliance Status
By default, /var/lib/docker is mounted
under the / or /var partitions depending
on OS configuration.

Not Applicable

By default, Docker daemon is not


audited.
By default, Docker related files and
directories are not audited.

By default, Docker related files and


directories are not audited.

By default, Docker related files and


directories are not audited.

By default, Docker related files and


directories are not audited. The file
docker.service may not be present.

By default, Docker related files and


directories are not audited. The file
containerd.sock may not be present.

By default, Docker related files and


directories are not audited. The file
docker.sock may not be present.

By default, Docker related files and


directories are not audited. The file
/etc/default/docker may not be present.

By default, Docker related files and


directories are not audited. The file
/etc/docker/daemon.json may not be
present.
By default, Docker related files and
directories are not audited. The file
/etc/containerd/config.toml may not be
present.
By default, Docker related files and
directories are not audited. The file
/etc/sysconfig/docker may not be
present.
By default, Docker related files and
directories are not audited. The file
/usr/bin/containerd may not be present.

By default, Docker related files and


directories are not audited. The file
/usr/bin/containerd-shim may not be
present.
By default, Docker related files and
directories are not audited. The file
/usr/bin/containerd-shim-runc-v1 may not
be present.
By default, Docker related files and
directories are not audited. The file
/usr/bin/containerd-shim-runc-v2 may not
be present.
By default, Docker related files and
directories are not audited. The file
/usr/bin/runc may not be present.

By default, the host has factory setting


and is not hardened.

Not applicable
This section lists the recommendations that alter and secure the behavior of the Docker daemon. The settings that are
Control ref. Control name Description
2.1 Run the Docker daemon as a non- Run Docker daemon in rootless mode to
root user, if possible enhance security.
2.2 Ensure network traffic is restricted Restrict inter-container communication on
between containers on the default the default network bridge.
bridge

2.3 Ensure the logging level is set to Set Docker daemon log level to 'info'.
'info'

2.4 Ensure Docker is allowed to make The Docker daemon should be allowed to
changes to iptables make changes to iptables.

2.5 Ensure insecure registries are not Avoid using insecure registries that do
used not have valid certificates or TLS.

2.6 Ensure aufs storage driver is not Do not use aufs as the storage driver.
used

2.7 Ensure TLS authentication for Use TLS authentication for Docker
Docker daemon is configured daemon if exposed over a network.

2.8 Ensure the default ulimit is Set appropriate ulimit options for resource
configured appropriately control.

2.9 Enable user namespace support Enable user namespace support to


enhance container security.
2.10 Ensure the default cgroup usage has Confirm correct use of cgroup parents.
been confirmed

2.11 Ensure base device size is not Only increase base device size if
changed until needed necessary.

2.12 Ensure authorization for Docker Use authorization plugins to control


client commands is enabled access to Docker client commands.

2.13 Ensure centralized and remote Enable centralized logging for Docker
logging is configured daemon.

2.14 Ensure containers are restricted from Restrict containers from gaining
acquiring new privileges additional privileges.

2.15 Ensure live restore is enabled Enable live restore to prevent container
downtime.
2.16 Ensure Userland Proxy is Disabled Disable the userland proxy if hairpin NAT
is available.
2.17 Ensure a daemon-wide custom Use a custom seccomp profile to restrict
seccomp profile is applied if system calls.
2.18 appropriate
Ensure experimental features are not Avoid using experimental features in
implemented in production production.
the Docker daemon. The settings that are under this section affect ALL container instances.
Audit Check Remediation steps (if not
Check running processes: compliant)
Follow Docker documentation to install
ps -fe | grep 'dockerd'. the Docker daemon as a non-root
Check network settings: user.
Edit daemon.json to disable ICC:
docker network ls --quiet | xargs docker {"icc": false} or use dockerd --
network inspect --format '{{ .Name }}: icc=false.
{{ .Options }}'.
Should return
com.docker.network.bridge.enable_icc:false.
Check daemon settings: Edit daemon.json to set log-level: 'info'
ps -ef | grep dockerd. or start dockerd with --log-
Review /etc/docker/daemon.json for 'log-level': level='info'.
'info'.
Check daemon settings: Do not run Docker with --
ps -ef | grep dockerd. iptables=false.
Ensure --iptables is either not present or not set
to false.
Check Docker info: Ensure no insecure registries are in
docker info --format 'Insecure Registries: use.
{{.RegistryConfig.InsecureRegistryCIDRs}}'.
Check storage driver: Do not start Docker with dockerd --
docker info --format 'Storage Driver: storage-driver aufs.
{{ .Driver }}'.
Shoulddaemon
Check not return 'aufs'.
settings: Follow Docker documentation to
ps -ef | grep dockerd. configure TLS authentication.
Ensure --tlsverify, --tlscacert, --tlscert, and --
tlskey are present.
Check daemon settings: Configure ulimit in daemon.json or
ps -ef | grep dockerd. start dockerd with --default-ulimit.
Ensure --default-ulimit parameter is set.
Check user namespace settings: Start Docker with --userns-
docker info --format '{{ .SecurityOptions }}'. remap=default.
Check daemon settings: Do not modify --cgroup-parent unless
ps -ef | grep dockerd. necessary.
Ensure --cgroup-parent is either not set or is set
appropriately.
Check daemon settings: Do not set --storage-opt dm.basesize
ps -ef | grep dockerd. unless required.
Should not show --storage-opt dm.basesize.
Check daemon settings: Install and configure an authorization
ps -ef | grep dockerd. plugin.
Ensure --authorization-plugin is set.
Check logging driver: Start Docker with dockerd --log-
docker info --format '{{ .LoggingDriver }}'. driver=syslog --log-opt syslog-
address=tcp://192.xxx.xxx.xxx.
Check daemon settings: Start Docker with dockerd --no-new-
ps -ef | grep dockerd. privileges.
Ensure --no-new-privileges is present.
Check daemon settings: Start Docker with dockerd --live-
docker info --format restore.
'{{ .LiveRestoreEnabled
Check daemon settings: }}'. Start Docker with dockerd --userland-
ps -ef | grep dockerd. proxy=false.
Ensure --userland-proxy=false.
Check seccomp profile: Start Docker with dockerd --seccomp-
docker info --format '{{ .SecurityOptions }}'. profile </path/to/seccomp/profile>.
Check Docker version: Do not start Docker with --
docker version --format experimental in production.
'{{ .Server.Experimental }}'.
stances.
Default value Compliance Status
The Docker daemon runs as the root user
by default.
By default, all inter-container
communication is allowed on the default
network bridge.

By default, Docker daemon is set to log


level 'info'.

By default, iptables is set to true.

By default, Docker assumes all but local


registries are secure.

By default, Docker uses overlay2 as the


storage driver.

By default, TLS authentication is not


configured.

By default, no ulimit is set.

By default, user namespace is not


remapped.
By default, Docker daemon uses /docker
for cgroup.

The default base device size is 10G.

By default, authorization plugins are not


enabled.

By default, container logs are stored as


JSON files.

By default, containers are not restricted


from acquiring new privileges.

By default, live restore is not enabled.

By default, userland proxy is enabled.


By default, Docker applies a default
seccomp profile.
By default, experimental features are
disabled.
This section covers Docker related files and directory permissions and ownership. Keeping the files and directories, th
Control ref. Control name Description
3.1 Ensure that the docker.service file You should verify that the docker.service
ownership is set to root:root (Automated) file ownership and group ownership are
correctly set to root.

3.2 Ensure that docker.service file You should verify that the docker.service
permissions are appropriately set file permissions are either set to 644 or to
(Automated) a more restrictive value.

3.3 Ensure that docker.socket file ownership You should verify that the docker.socket
is set to root:root (Automated) file ownership and group ownership are
correctly set to root.

3.4 Ensure that docker.socket file You should verify that the file permissions
permissions are set to 644 or more on the docker.socket file are correctly set
restrictive (Automated) to 644 or more restrictively.

3.5 Ensure that the /etc/docker directory You should verify that the /etc/docker
ownership is set to root:root (Automated) directory ownership and group ownership
is correctly set to root.

3.6 Ensure that /etc/docker directory You should verify that the /etc/docker
permissions are set to 755 or more directory permissions are correctly set to
restrictively (Automated) 755 or more restrictively.
3.7 Ensure that registry certificate file You should verify that all the registry
ownership is set to root:root (Manual) certificate files (usually found under
/etc/docker/certs.d/<registry-name>
directory) are individually owned and
group owned by root.
3.8 Ensure that registry certificate file Verify registry certificate file permissions
permissions are set to 444 or more are set to 444 or more restrictively.
restrictively
3.9 Ensure that TLS CA certificate file Verify TLS CA certificate file ownership is
ownership is set to root:root set to root:root.
3.10 Ensure that TLS CA certificate file Verify TLS CA certificate file permissions
permissions are set to 444 or more are set to 444 or more restrictively.
restrictively
3.11 Ensure that Docker server certificate file Verify Docker server certificate file
ownership is set to root:root ownership is set to root:root.
3.12 Ensure that the Docker server certificate Verify Docker server certificate file
file permissions are set to 444 or more permissions are set to 444 or more
restrictively restrictively.
3.13 Ensure that the Docker server certificate Verify Docker server certificate key file
key file ownership is set to root:root ownership is set to root:root.
3.14 Ensure that the Docker server certificate Verify Docker server certificate key file
key file permissions are set to 400 permissions are set to 400.
3.15 Ensure that the Docker socket file Verify Docker socket file is owned by root
ownership is set to root:docker and group owned by docker.
3.16 Ensure that the Docker socket file Verify Docker socket file has permissions
permissions are set to 660 or more of 660 or more restrictive.
restrictively
3.17 Ensure that the daemon.json file Verify daemon.json file is owned and
ownership is set to root:root group owned by root.
3.18 Ensure that daemon.json file Verify daemon.json file has permissions
permissions are set to 644 or more of 644 or more restrictive.
3.19 restrictive
Ensure that the /etc/default/docker file Verify /etc/default/docker file is owned
ownership is set to root:root and group owned by root.
3.20 Ensure that the /etc/default/docker file Verify /etc/default/docker file has
permissions are set to 644 or more permissions of 644 or more restrictive.
restrictively
3.21 Ensure that the /etc/sysconfig/docker file Verify /etc/sysconfig/docker file has
permissions are set to 644 or more permissions of 644 or more restrictive.
restrictively
3.22 Ensure that the /etc/sysconfig/docker file Verify /etc/sysconfig/docker file is owned
ownership is set to root:root and group owned by root.
3.23 Ensure that the Containerd socket file Verify Containerd socket file is owned
ownership is set to root:root and group owned by root.
3.24 Ensure that the Containerd socket file Verify Containerd socket file has
permissions are set to 660 or more permissions of 660 or more restrictive.
restrictively
hip. Keeping the files and directories, that may contain sensitive parameters, secure is important for correct and secure functionin
Audit Check Remediation steps (if not compliant)
Step 1: Find out the file location: Step 1: Find out the file location: systemctl show -
systemctl show -p FragmentPath docker.service p FragmentPath docker.service
Step 2: If the file does not exist, this recommendation is Step 2: If the file does not exist, this
not applicable. If the file exists, execute the command recommendation is not applicable. If the file does
below including the correct file path in order to verify that exist, you should execute the command below,
the file is owned and group owned by root. For example: including the correct file path, in order to set the
stat -c %U:%G /usr/lib/systemd/system/docker.service ownership and group ownership for the file to root.
| grep -v root:root For example,
The command above should not return anything.
chown root:root
/usr/lib/systemd/system/docker.service
The docker.service file contains sensitive parameters that Step 1: Find out the file location: systemctl show -
may alter the behavior of the Docker daemon. It should p FragmentPath docker.service
therefore not be writable by any other user other than root Step 2: If the file does not exist, this
in order to ensure that it can not be modified by less recommendation is not applicable. If the file exists,
privileged users. execute the command below, including the correct
file path in order to verify that the file permissions
are set to 644 or a more restrictive value. For
example: stat -c %a
/usr/lib/systemd/system/docker.service
Step 1: Find out the file location: Step 1: Find out the file location: systemctl show -
systemctl show -p FragmentPath docker.socket p FragmentPath docker.socket
Step 2: If the file does not exist, this recommendation is Step 2: If the file does not exist, this
not applicable. If the file exists, execute the command recommendation is not applicable. If the file exists,
below, including the correct file path to verify that the file is execute the command below, including the correct
owned and group-owned by root. For example, file path to set the ownership and group ownership
stat -c %U:%G /usr/lib/systemd/system/docker.socket for the file to root. For example,
| grep -v root:root
The command above should not return a value. chown root:root
/usr/lib/systemd/system/docker.socket

Step 1: Find out the file location: Step 1: Find out the file location: systemctl show -
systemctl show -p FragmentPath docker.socket p FragmentPath docker.socket
Step 2: If the file does not exist, this recommendation is Step 2: If the file does not exist, this
not applicable. If the file exists, you should execute the recommendation is not applicable. If the file does
command below, including the correct file path in order to exist, you should execute the command below,
verify that the file permissions are set to 644 or more including the correct file path to set the file
restrictively. For example: permissions to 644. For example,
stat -c %a /usr/lib/systemd/system/docker.socket chmod 644 /usr/lib/systemd/system/docker.socket

You should execute the command below to verify that the To resolve this issue you should run the following
directory is owned and group owned by root: command: chown root:root /etc/docker
stat -c %U:%G /etc/docker | grep -v root:root This sets the ownership and group ownership for
This command should not return any data. the directory to root.
You should execute the command below to verify that the You should run the following command: chmod
directory has permissions of 755 or more restrictive ones: 755 /etc/docker
stat -c %a /etc/docker This sets the permissions for the directory to 755.
You should execute the command below to verify that the The following command could be executed:
registry certificate files are individually owned and group
owned by root: chown root:root /etc/docker/certs.d/<registry-
name>/*
stat -c %U:%G /etc/docker/certs.d/* | grep -v root:root

The above command should not return any value.


find /etc/docker/certs.d/ -type f -exec stat -c "%a %n" Run: find /etc/docker/certs.d/ -type f -exec
{} \; chmod 0444 {} \;

stat -c %U:%G <path to TLS CA certificate file> | grep - Run: chown root:root <path to TLS CA
v root:root certificate file>
stat -c %a <path to TLS CA certificate file> Run: chmod 444 <path to TLS CA certificate
file>

stat -c %U:%G <path to Docker server certificate file> | Run: chown root:root <path to Docker server
grep -v root:root certificate file>
stat -c %a <path to Docker server certificate file> Run: chmod 444 <path to Docker server
certificate file>

stat -c %U:%G <path to Docker server certificate key Run: chown root:root <path to Docker server
file> | grep -v root:root certificate key file>
stat -c %a <path to Docker server certificate key file> Run: chmod 400 <path to Docker server
certificate key file>
stat -c %U:%G /var/run/docker.sock | grep -v chown root:docker /var/run/docker.sock
root:docker
stat -c %a /var/run/docker.sock chmod 660 /var/run/docker.sock

stat -c %U:%G /etc/docker/daemon.json | grep -v chown root:root /etc/docker/daemon.json


root:root
stat -c %a /etc/docker/daemon.json chmod 644 /etc/docker/daemon.json

stat -c %U:%G /etc/default/docker | grep -v root:root chown root:root /etc/default/docker

stat -c %a /etc/default/docker chmod 644 /etc/default/docker

stat -c %a /etc/sysconfig/docker chmod 644 /etc/sysconfig/docker

stat -c %U:%G /etc/sysconfig/docker | grep -v chown root:root /etc/sysconfig/docker


root:root
stat -c %U:%G /run/containerd/containerd.sock | grep - chown root:root
v root:root /run/containerd/containerd.sock
stat -c %a /run/containerd/containerd.sock chmod 660 /run/containerd/containerd.sock
rrect and secure functioning of Docker daemon.
Default value Compliance Status
This file may not be present on the system
and if it is not, this recommendation is not
applicable. By default, if the file is present,
the correct permissions are for the
ownership and group ownership to be set
to "root".

This file may not be present on the system.


In that case, this recommendation is not
applicable. By default, if the file is present,
the file permissions are correctly set to
644.

This file may not be present on the system.


In that case, this recommendation is not
applicable. By default, if the file is present,
the ownership and group ownership for it
should be set to root.

This file may not be present on the system


and in that case, this recommendation is
not applicable. By default, if the file is
present, the permissions should be set to
644 or more restrictively.

By default, the ownership and group


ownership for this directory is correctly set
to root.

By default, the permissions for this


directory are set to 755.

By default, the individual ownership and


group ownership for registry certificate files
is correctly set to root.
Permissions might not be 444 by default.

Ownership is correctly set to root by


default.
Permissions might not be 444 by default.

Ownership is correctly set to root by


default.
Permissions might not be 444 by default.

Ownership is correctly set to root by


default.
Permissions might not be 400 by default.

Correctly set to root:docker by default

Correctly set to 660 by default

Not applicable if file does not exist

Not applicable if file does not exist

Not applicable if file does not exist

Not applicable if file does not exist

Not applicable if file does not exist

Not applicable if file does not exist

Correctly set to root:root by default

Correctly set to 660 by default


Container base images and build files govern the fundamentals of how a container instance from a particular image wo
your containerized
Control ref. Controlinfrastructure.
name Below are some of the recommendations that you should follow for container base i
Description
4.1 Ensure that a user for the container Containers should run as a non-root
has been created user.

4.2 Ensure that containers use only Ensure container images are either
trusted base images built from scratch or based on a trusted
image.
4.3 Ensure that unnecessary packages Containers should not have
are not installed in the container unnecessary software packages to
minimize attack surface.
4.4 Ensure images are scanned and Images should be frequently scanned
rebuilt to include security patches for vulnerabilities and rebuilt to include
patches.
4.5 Ensure Content trust for Docker is Enable content trust to verify image
Enabled provenance using digital signatures.
4.6 Ensure HEALTHCHECK instructions HEALTHCHECK ensures the Docker
have been added to container engine checks container health.
images
4.7 Ensure update instructions are not Avoid using `apt-get update` or `yum
used alone in Dockerfiles update` alone in Dockerfiles.
4.8 Ensure setuid and setgid Remove setuid and setgid permissions
permissions are removed to prevent privilege escalation attacks.
4.9 Ensure that COPY is used instead of Use COPY instead of ADD in
ADD in Dockerfiles Dockerfiles to avoid security risks from
4.1 Ensure secrets are not stored in remote URLs.secrets in Dockerfiles as
Avoid storing
Dockerfiles they are visible in image history.
4.11 Ensure only verified packages are Verify package authenticity before
installed installing them into images.
4.12 Ensure all signed artifacts are Validate artifact signatures before
validated uploading to package registry.
container instance from a particular image would behave. Ensuring that you are using proper base images and appropriate build f
ns that you should follow for container base images and build files to ensure that your containerized infrastructure is secure.
Audit Check
Run:
docker ps --quiet | xargs --max-args=1 -I{} docker exec
{} cat /proc/1/status | grep '^Uid:' | awk '{print $3}'

to check if containers are running as root.


Run: docker images and review image origins. Check
image history with docker history <imageName>

List installed packages in running containers using: `docker


exec $INSTANCE_ID rpm -qa`.

Run vulnerability scanning tools or package managers


inside the container to check for available security patches.

Run: echo $DOCKER_CONTENT_TRUST, expected


output: 1.
Inspect images for HEALTHCHECK instructions using:
docker inspect --format='{{ .Config.Healthcheck }}'
<IMAGE>
Run: docker history <Image_ID> to check if updates are
applied in a single line.
Run: docker export <IMAGE ID> | tar -tv 2>/dev/null |
grep -E '^[-rwx].*(s|S).*\s[0-9]'
Run: docker history <IMAGE ID> or inspect Dockerfile for
ADD instructions.
Run: docker history <IMAGE ID> or inspect Dockerfile for
secrets.
Run: docker history <IMAGE ID> to check package
installation methods.
Ensure every artifact in the package is validated with its
signature.
. Ensuring that you are using proper base images and appropriate build files can be very important for building
build files toRemediation
ensure that steps
your containerized infrastructure is secure.
(if not compliant) Default value Compliance Status
Ensure Dockerfile contains `USER <username or ID>` Containers run with root privileges
and create a user inside the container if needed. by default.

Use Docker Content Trust, validate image history, and Not Applicable.
scan images for vulnerabilities.

Use minimal base images and avoid installing Not Applicable.


unnecessary packages.

Rebuild images with updated base images and restart Containers and images are not
containers with patched images. automatically updated.

Enable content trust with `export Content trust is disabled by


DOCKER_CONTENT_TRUST=1`. default.
Rebuild images with HEALTHCHECK instructions. HEALTHCHECK is not set by
default.

Combine update instructions with package installation Docker does not enforce update
and use version pinning. restrictions.
Remove setuid/setgid bits with `RUN find / -perm Not Applicable.
/6000 -type f -exec chmod a-s {} \; || true` in Dockerfile.
Replace ADD instructions with COPY. Not Applicable.

Use secret management tools like Docker BuildKit. No restrictions on storing secrets
in Dockerfiles.
Use secure package distribution mechanisms (GPG Not Applicable.
keys, etc.).
Validate every artifact signature automatically. Not Applicable.
There are many security implications associated with the ways that containers are started. Some runtime parameters c
therefore
Control very important
Control nameto verify the way in which containers are started, and which parameters are associated with th
Description
ref.
5.1 Ensure swarm mode is not Enabled, Do not enable swarm mode on a Docker
if not needed (Manual) engine instance unless this is needed.

5.2 Ensure that, if applicable, an AppArmor is an effective and easy-to-use


AppArmor Profile is enabled (Manual) Linux application security system. It is
available on some Linux distributions by
default, for example, on Debian and Ubuntu.

5.3 Ensure that, if applicable, SELinux SELinux is an effective and easy-to-use


security options are set (Manual) Linux application security system. It is
available by default on some distributions
such as Red Hat and Fedora.
5.4 Ensure that Linux kernel capabilities By default, Docker starts containers with a
are restricted within containers restricted set of Linux kernel capabilities. This
(Manual) means that any process can be granted the
required capabilities instead of giving it root
access. Using Linux kernel capabilities,
processes in general do not need to run as
the root user.

5.5 Ensure that privileged containers are Using the --privileged flag provides all Linux
not used (Manual) kernel capabilities to the container to which it
is applied and therefore overwrites the --cap-
add and --cap-drop flags. For this reason you
should ensure that it is not used.

5.6 Ensure sensitive host system You should not allow sensitive host system
directories are not mounted on directories such as those listed below to be
containers (Manual) mounted as container volumes, especially in
read-write mode.
/
/boot
/dev
/etc
/lib
/lib64
/proc
/sys
/usr
5.7 Ensure sshd is not run within The SSH daemon should not be running
containers (Manual) within the container. You should SSH into the
Docker host, and use docker exec to enter a
container.

5.8 Ensure privileged ports are not The TCP/IP port numbers below 1024 are
mapped within containers (Manual) considered privileged ports. Normal users
and processes are not allowed to use them
for various security reasons. Docker does,
however allow a container port to be mapped
to a privileged port.

5.9 Ensure that only needed ports are The dockerfile for a container image defines
open on the container (Manual) the ports which are opened by default on a
container instance. The list of ports are
relevant to the application you are running
within the container and should only be open
if they are needed.

5.10 Ensure that the host's network When the networking mode on a container is
namespace is not shared (Manual) set to --net=host, the container is not placed
inside a separate network stack. Effectively,
applying this option instructs Docker to not
containerize the container's networking. The
consequence of this is that the container
lives "outside" in the main Docker host and
has full access to its network interfaces.
5.11 Ensure that the memory usage for By default, all containers on a Docker host
containers is limited (Manual) share resources equally. By using the
resource management capabilities of the
Docker host, you can control the amount of
memory that a container is able to use.

5.12 Ensure that CPU priority is set By default, all containers on a Docker host
appropriately on containers (Manual) share resources equally. By using the
resource management capabilities of the
Docker host you can control the host CPU
resources that a container may consume.
5.13 Ensure that the container's root The container's root filesystem should be
filesystem is mounted as read only treated as a 'golden image' by using Docker
(Manual) run's --read-only option. This prevents any
writes to the container's root filesystem at
container runtime and enforces the principle
of immutable infrastructure.

5.14 Ensure that incoming container traffic By default, Docker containers can make
is bound to a specific host interface connections to the outside world, but the
(Manual) outside world cannot connect to containers
and each outgoing connection will appear to
originate from one of the host machine's own
IP addresses. You should only allow
container services to be contacted through a
specific external interface on the host
machine.
5.15 Ensure that the 'on-failure' container By using the --restart flag in the docker run
restart policy is set to '5' (Manual) command you can specify a restart policy for
how a container should or should not be
restarted on exit. You should choose the on-
failure restart policy and limit the restart
attempts to 5.

5.16 Ensure that the host's process The Process ID (PID) namespace isolates
namespace is not shared (Manual) the process ID space, meaning that
processes in different PID namespaces can
have the same PID. This creates process
level isolation between the containers and
the host.

5.17 Ensure that the host's IPC IPC (POSIX/SysV IPC) namespace provides
namespace is not shared (Manual) separation of named shared memory
segments, semaphores and message
queues. The IPC namespace on the host
should therefore not be shared with
containers and should remain isolated.
5.18 Ensure that host devices are not Host devices can be directly exposed to
directly exposed to containers containers at runtime. Do not directly expose
(Manual) host devices to containers, especially to
containers that are not trusted.

5.19 Ensure that the default ulimit is The default ulimit is set at the Docker
overwritten at runtime if needed daemon level. However, if you need to, you
(Manual) may override the default ulimit setting during
container runtime.

5.20 Ensure mount propagation mode is Mount propagation mode allows mounting
not set to shared (Manual) volumes in shared, slave or private mode on
a container. Do not use shared mount
propagation mode unless explicitly needed.

5.21 Ensure that the host's UTS UTS namespaces provide isolation between
namespace is not shared (Manual) two system identifiers: the hostname and the
NIS domain name. It is used to set the
hostname and the domain which are visible
to running processes in that namespace.
Processes running within containers do not
typically require to know either the hostname
or the domain name. The UTS namespace
should therefore not be shared with the host.
5.22 Ensure the default seccomp profile is Seccomp filtering provides a means for a
not Disabled (Manual) process to specify a filter for incoming system
calls. The default Docker seccomp profile
works on a whitelist basis and allows for a
large number of common system calls, whilst
blocking all others. This filtering should not
be disabled unless it causes a problem with
your container application usage.

5.23 Ensure that docker exec commands You should not use docker exec with the --
are not used with the privileged privileged option.
option (Manual)

5.24 Ensure that docker exec commands You should not use docker exec with the --
are not used with the user=root user=root option.
option (Manual)

5.25 Ensure that cgroup usage is It is possible to attach to a particular cgroup


confirmed (Manual) when a container is instantiated. Confirming
cgroup usage would ensure that containers
are running in defined cgroups.

5.26 Ensure that the container is restricted You should restrict the container from
from acquiring additional privileges acquiring additional privileges via suid or sgid
(Manual) bits.

5.27 Ensure that container health is If the container image does not have an
checked at runtime (Manual) HEALTHCHECK instruction defined, you
should use the --health-cmd parameter at
container runtime to check container health.
5.28 Ensure that Docker commands You should always ensure that you are using
always make use of the latest version the latest version of the images within your
of their image (Manual) repository and not cached older versions.

5.29 Ensure that the PIDs cgroup limit is You should use the --pids-limit flag at
used (Manual) container runtime.

5.30 Ensure that Docker's default bridge You should not use Docker's default bridge
"docker0" is not used (Manual) docker0. Instead you should use Docker's
user-defined networks for container
networking.

5.31 Ensure that the host's user You should not share the host's user
namespaces are not shared (Manual) namespaces with containers running on it.

5.32 Ensure that the Docker socket is not The Docker socket docker.sock should not
mounted inside any containers be mounted inside a container.
(Manual)
are started. Some runtime parameters can be supplied that have security consequences that could compromise the host and the
which parameters are associated with them. Container runtime
Audit Check configuration
Remediation should
steps (if notbe reviewed in line with organizational secur
compliant)

Review the output of If swarm mode has been enabled on a system in


docker info --format '{{ .Swarm }}' error, you should run the command below:
If the output includes active true it indicates that docker swarm leave
swarm mode has been activated on the Docker
engine. In this case, you should confirm if swarm
mode on the Docker engine instance is actually
needed.

You should run the command below: If AppArmor is applicable for your Linux OS, you
docker ps --quiet --all | xargs docker inspect -- should enable it.
format '{{ .Id }}: 1.Verify AppArmor is installed.
AppArmorProfile={{ .AppArmorProfile }}' 2.Create or import a AppArmor profile for Docker
This command should return a valid AppArmor containers.
Profile for each container instance. 3.Enable enforcement of the policy.
4.Start your Docker container using the customized
AppArmor profile.
For example:
docker run --interactive --tty --security-
opt="apparmor:PROFILENAME" ubuntu /bin/bash
Alternatively, Docker's default AppArmor policy can
be used.

You should run the following command If SELinux is applicable for your Linux OS, you should
docker ps --quiet --all | xargs docker inspect -- use it.
format '{{ .Id }}: 1.Set the SELinux State.
SecurityOpt={{ .HostConfig.SecurityOpt }} 2.Set the SELinux Policy.
MountLabel={{ .MountLabel }} 3.Create or import a SELinux policy template for
ProcessLabel={{ .ProcessLabel }}' Docker containers.
4.Start Docker in daemon mode with SELinux
This command returns all the security options enabled.
currently configured on the containers listed. Note For example:
that even if an empty SecurityOpt is returned, the
MountLabel and ProcessLabel values will indicate if docker daemon --selinux-enabled
SELinux is in use. or by adding the following to the daemon.json
configuration file:

{ "selinux-enabled": true }

5. Start your Docker container using the security


options.
For example,

docker run --interactive --tty --security-opt


label=level:TopSecret centos /bin/bash
You should run the following command: You should execute the command below to add
docker ps --quiet --all | xargs docker inspect -- required capabilities:
format '{{ .Id }}: CapAdd={{ .HostConfig.CapAdd docker run --cap-add={"Capability 1","Capability
}} CapDrop={{ .HostConfig.CapDrop }}' 2"} <Run arguments> <Container Image Name or
ID> <Command>
Verify that the added and deleted Linux kernel You should execute the command below to remove
capabilities are in line with the ones needed by the unneeded capabilities:
container process in each container instance. docker run --cap-drop={"Capability 1","Capability
Specifically, ensure that the NET_RAW capability is 2"} <Run arguments> <Container Image Name or
removed if not required. ID> <Command>
Alternatively, you could remove all the currently
configured capabilities and then restore only the ones
you specifically use:
docker run --cap-drop=all --cap-add={"Capability
1","Capability 2"} <Run arguments> <Container
Image Name or ID> <Command>
Note that some settings also can be configured using
the --sysctl option, reducing the need for container
capabilities even further. This includes unprivileged
ICMP echo sockets without NET_RAW and allow
opening any port less than 1024 without
NET_BIND_SERVICE. Adding and removing
capabilities are also possible when the docker service
command is used:
docker service create --cap-drop=all --cap-
add={"Capability 1","Capability 2"} <Run
arguments> <Container Image Name or ID>
<Command>

You should run the command below: You should not run containers with the --privileged
docker ps --quiet --all | xargs docker inspect -- flag. For example, do not start a container using the
format '{{ .Id }}: command below:
Privileged={{ .HostConfig.Privileged }}'
docker run --interactive --tty --privileged centos
The above command should return /bin/bash
Privileged=false for each container instance.

You should run the following command: You should not mount directories which are security
docker ps --quiet --all | xargs docker inspect -- sensitive on the host within containers, especially in
format '{{ .Id }}: Volumes={{ .Mounts }}' read-write mode.

This command returns a list of currently mapped


directories and indicates whether they are mounted
in read-write mode for each container instance.
List all the running instances of containers by Uninstall the SSH daemon from the container and
executing below command: use and use docker exec to enter a container on the
docker ps --quiet remote host.
docker exec --interactive --tty <CONTAINER ID>
For each container instance, execute the below sh
command: OR
docker attach <CONTAINER ID>
docker exec <CONTAINER ID> ps -el

Ensure that there is no process for SSH server.

You can list all running containers instances and You should not map container ports to privileged host
their port mappings by executing the command ports when starting a container. You should also,
below: ensure that there is no such container to host
docker ps --quiet | xargs docker inspect -- privileged port mapping declarations in the Dockerfile.
format '{{ .Id }}: Ports={{ .NetworkSettings.Ports
}}'

You should then review the list and ensure that


container ports are not mapped to host port
numbers below 1024.

You should list all the running instances of You should ensure that the Dockerfile for each
containers and their associated port mappings by container image only exposes needed ports. You can
executing the command below: also completely ignore the list of ports defined in the
docker ps --quiet | xargs docker inspect -- Dockerfile by NOT using -P (UPPERCASE) or the --
format '{{ .Id }}: Ports={{ .NetworkSettings.Ports publish-all flag when starting the container. Instead,
}}' use the -p (lowercase) or --publish flag to explicitly
define the ports that you need for a particular
You should then review the list and ensure that all container instance. For example:
the ports mapped are in fact genuinely required by
each container. docker run --interactive --tty --publish 5000 --
publish 5001 --publish 5002 centos /bin/bash

You should use the command below: You should not pass the --net=host option when
docker ps --quiet --all | xargs docker inspect -- starting any container.
format '{{ .Id }}:
NetworkMode={{ .HostConfig.NetworkMode }}'

If this returns NetworkMode=host, it means that the


--net=host option was passed when the container
was started.
You should run the command below: You should run the container with only as much
docker ps --quiet --all | xargs docker inspect -- memory as it requires by using the --memory
format '{{ .Id }}: Memory={{ .HostConfig.Memory argument. For example, you could run a container
}}' using the command below:
docker run -d --memory 256m centos sleep 1000
If this command returns 0, it means that memory
limits are not in place; if it returns a non-zero value, In the example above, the container is started with a
it means that they are in place. memory limit of 256 MB. Verify the memory settings
by using the command below:

docker inspect --format='{{ .Id }}:


Memory={{.HostConfig.Memory}}
KernelMemory={{.HostConfig.KernelMemory}}
Swap={{.HostConfig.MemorySwap}}'
<CONTAINER ID>

You should run the following command. You should manage the CPU runtime between your
docker ps --quiet --all | xargs docker inspect -- containers dependent on their priority within your
format '{{ .Id }}: organization. To do so start the container using the --
CpuShares={{ .HostConfig.CpuShares }}' cpu-shares argument. For example, you could run a
container as below:
If the above command returns 0 or 1024, it means
that CPU shares are not in place. If it returns a docker run -d --cpu-shares 512 centos sleep 1000
non-zero value other than 1024, it means that they
are in place. In the example above, the container is started with
CPU shares of 50% of what other containers use. So
if the other container has CPU shares of 80%, this
container will have CPU shares of 40%. Every new
container will have 1024 shares of CPU by default.
However, this value is shown as 0 if you run the
command mentioned in the audit section. If you set
one container’s CPU shares to 512 it will receive half
of the CPU time compared to the other containers. So
if you take 1024 as 100% you can then derive the
number that you should set for respective CPU
shares. For example, use 512 if you want to set it to
50% and 256 if you want to set it 25%. You can also
view the current CPU shares in the file
/sys/fs/cgroup/cpu/docker/<CONTAINER
ID>/cpu.shares.
You should run the following command on the You should add a --read-only flag at a container's
docker host: runtime to enforce the container's root filesystem
docker ps --quiet --all | xargs docker inspect -- being mounted as read only.
format '{{ .Id }}:
ReadonlyRootfs={{ .HostConfig.ReadonlyRootfs docker run <Run arguments> --read-only
}}' <Container Image Name or ID> <Command>

If the above command returns true, it means the Enabling the --read-only option at a container's
container's root filesystem is mounted read-only. If runtime should be used by administrators to force a
the above command returns false, it means the container's executable processes to only write
container's root filesystem is writeable. container data to explicit storage locations during its
lifetime. Examples of explicit storage locations during
a container's runtime include, but are not limited to:
1. Using the --tmpfs option to mount a temporary file
system for non-persistent data writes.
docker run --interactive --tty --read-only --tmpfs
"/run" --tmpfs "/tmp" centos /bin/bash
2. Enabling Docker rw mounts at a container's
runtime to persist container data directly on the
Docker host filesystem.
docker run --interactive --tty --read-only -v
/opt/app/data:/run/app/data:rw centos /bin/bash
3. Utilizing the Docker shared-storage volume plugin
for Docker data volume to persist container data.
docker volume create -d convoy --opt
o=size=20GB my-named-volume docker run --
interactive --tty --read-only -v
my-named-volume:/run/app/data centos /bin/bash
4. Transmitting container data outside of the Docker
controlled area during the container's runtime for
container data in order to ensure that it is persistent.
Examples include hosted databases, network file
shares and APIs.

You should list all running instances of containers You should bind the container port to a specific host
and their port mappings by executing the command interface on the desired host port. For example,
below:
docker ps --quiet | xargs docker inspect -- docker run --detach --publish 10.2.3.4:49153:80
format '{{ .Id }}: Ports={{ .NetworkSettings.Ports nginx
}}'
In the example above, the container port 80 is bound
Then review the list and ensure that the exposed to the host port on 49153 and would accept incoming
container ports are bound to a specific interface connection only from the 10.2.3.4 external interface.
and not to the wildcard IP address 0.0.0.0. For
example, if the command above returns the results
below, this is non-compliant and the container can
accept connections on any host interface on the
specified port 49153. Ports=map[443/tcp:<nil>
80/tcp:[map[HostPort:49153 HostIp:0.0.0.0]]]
However, if the exposed port is bound to a specific
interface on the host as below, then this is
configured in line with good security practice.
Ports=map[443/tcp:<nil> 80/tcp:
[map[HostIp:10.2.3.4 HostPort:49153]]]
You should use the command below If you wish a container to be automatically restarted,
docker ps --quiet --all | xargs docker inspect -- a sample command is as below:
format '{{ .Id }}:
RestartPolicyName={{ .HostConfig.RestartPolic docker run --detach --restart=on-failure:5 nginx
y.Name }}
MaximumRetryCount={{ .HostConfig.RestartPoli
cy.MaximumRetryCount }}'

If this command returns


RestartPolicyName=always, then the system is not
configured optimally. If the above command returns
RestartPolicyName=no or just
RestartPolicyName=, then restart policies are not
being used and the container would never be
restarted automatically. Whilst this may be a secure
option, it is not the best option from a usability
standpoint. If the above command returns
RestartPolicyName=on-failure, then verify that the
number of restart attempts is set to 5 or less by
looking
You shouldat MaximumRetryCount.
run the following command: You should not start a container with the --pid=host
docker ps --quiet --all | xargs docker inspect -- argument. For example, do not start a container with
format '{{ .Id }}: the command below:
PidMode={{ .HostConfig.PidMode }}'
docker run --interactive --tty --pid=host centos
If the command above returns host, it means that /bin/bash
the host PID namespace is shared with its
containers; any other result means that the system
is configured in line with good security practice.

You should run the following command: You should not start a container with the --ipc=host
docker ps --quiet --all | xargs docker inspect -- argument. For example, do not start a container as
format '{{ .Id }}: below:
IpcMode={{ .HostConfig.IpcMode }}'
docker run --interactive --tty --ipc=host centos
If the command returns host, it means that the host /bin/bash
IPC namespace is shared with the container. Any
other result means that it is not shared, and that
the system is therefore configured in line with good
security practice.
You should use the command below: You should not directly expose host devices to
containers. If you do need to expose host devices to
docker ps --quiet --all | xargs docker inspect -- containers, you should use granular permissions as
format '{{ .Id }}: Devices={{ .HostConfig.Devices appropriate to your organization:
}}' For example, do not start a container using the
command below:
The above command would list out each device docker run --interactive --tty
with below information: --device=/dev/tty0:/dev/tty0:rwm
--device=/dev/temp_sda:/dev/temp_sda:rwm
•CgroupPermissions - For example, rwm centos bash
•PathInContainer - Device path within the container
•PathOnHost - Device path on the host You should only share the host device using
appropriate permissions: docker run --interactive --tty
You should verify that the host device is needed to --device=/dev/tty0:/dev/tty0:rw
be accessed from within the container and that the --device=/dev/temp_sda:/dev/temp_sda:r centos bash
permissions required are correctly set. If the above
command returns [], then the container does not
have access to host devices and is configured in
line with good security practice.

You should run the command below: You should only override the default ulimit settings if
docker ps --quiet --all | xargs docker inspect -- needed in a specific case. For example, to override
format '{{ .Id }}: default ulimit settings start a container as below:
Ulimits={{ .HostConfig.Ulimits }}'
docker run -ti -d --ulimit nofile=1024:1024 centos
This command should return Ulimits=<no value> sleep 1000
for each container instance unless there is a need
in a specific case to override the default settings.
docker ps --quiet --all | xargs docker inspect -- Do not mount volumes in shared mode propagation.
format '{{ .Id }}: Propagation={{range For example, do not start a container as below:
$mnt := .Mounts}} {{json $mnt.Propagation}}
{{end}}' docker run <Run arguments>
--volume=/hostPath:/containerPath:shared
The above command returns the propagation mode <Container Image Name or ID> <Command>
for mounted volumes. The propagation mode
should not be set to shared unless needed. The
above command might throw errors if there are no
mounts. In that case, this recommendation is not
applicable.
You should run the following command: You should not start a container with the --uts=host
docker ps --quiet --all | xargs docker inspect -- argument. For example, do not start a container using
format '{{ .Id }}: the command below:
UTSMode={{ .HostConfig.UTSMode }}'
docker run --rm --interactive --tty --uts=host
If the above command returns host, it means the rhel7.2
host UTS namespace is shared with the container
and this recommendation is non-compliant. If the
above command returns nothing, then the host's
UTS namespace is not shared. This
recommendation is then compliant.
You should run the following command: By default, seccomp profiles are enabled. You do not
docker ps --quiet --all | xargs docker inspect -- need to do anything unless you want to modify and
format '{{ .Id }}: use a modified seccomp profile.
SecurityOpt={{ .HostConfig.SecurityOpt }}'

This should return either <no value> or your


modified seccomp profile. If it returns
[seccomp:unconfined], the container is running
without any seccomp profiles and is therefore not
configured in line with good security practice.

If you have auditing enabled as recommended in You should not use the --privileged option in docker
Section 1, you can use the command below to filter exec commands.
out docker exec commands that use the --
privileged option.

ausearch -k docker | grep exec | grep privileged

If you have auditing enabled as recommended in You should not use the --user=root option in docker
Section 1, you can use the command below to filter exec commands.
out docker exec commands that use the --
user=root option.

ausearch -k docker | grep exec | grep user

You should run the following command: You should not use the --cgroup-parent option within
the docker run command unless strictly required.
docker ps --quiet --all | xargs docker inspect --
format '{{ .Id }}:
CgroupParent={{ .HostConfig.CgroupParent }}'

The above command returns the cgroup where the


containers are running. If it is blank, it means that
containers are running under the default docker
cgroup. Any other return value indicates that the
system is not configured in line with good security
practice.

You should run the following command: You should start your container with the options
docker ps --quiet --all | xargs docker inspect -- below:
format '{{ .Id }}:
SecurityOpt={{ .HostConfig.SecurityOpt }}' docker run --rm -it --security-opt=no-new-
privileges ubuntu bash
This command should return all the security options
currently configured for containers. no-new-
privileges should be one of them. Note that the
SecurityOpt response will be empty (i.e.
SecurityOpt=<no value>) even if "no-new-
privileges": true has been configured in the Docker
daemon.json configuration file.
You should run the command below and ensure You should run the container using the --health-cmd
that all containers are reporting their health status: parameter. For example:

docker ps --quiet | xargs docker inspect -- docker run -d --health-cmd='stat /etc/passwd ||


format '{{ .Id }}: exit 1' nginx
Health={{ .State.Health.Status }}'
You should carry out the following steps: You should use proper version pinning mechanisms
Step 1: Open your image repository and list the (the "latest" tag which is assigned by default is still
image version history for the image you are vulnerable to caching attacks) to avoid extracting
inspecting. cached older versions. Version pinning mechanisms
should be used for base images, packages, and
Step 2: Observe the status when the docker pull entire images. You can customize version pinning
command is triggered. If the status is shown as rules according to your requirements.
Image is up to date, it means that you are getting
the cached version of the image.

Step 3: Match the version of the image you are


running to the latest version reported in your
repository and this will tell you whether you are
running the cached version or the latest copy.

You should run the command below and ensure Use --pids-limit flag with an appropriate value when
that PidsLimit is not set to 0 or -1. A PidsLimit of 0 launching the container. For example:
or -1 means that any number of processes can be
forked concurrently inside the container. docker run -it --pids-limit 100 <Image ID>

docker ps --quiet --all | xargs docker inspect -- In the above example, the number of processes
format '{{ .Id }}: allowed to run at any given time is set to 100. After a
PidsLimit={{ .HostConfig.PidsLimit }}' limit of 100 concurrently running processes is
reached, Docker would restrict any new process
creation.
You should run the command below, and verify that You should follow the Docker documentation and set
containers are on a user-defined network and not up a user-defined network. All the containers should
the default docker0 bridge. be run in this network.

docker network ls --quiet | xargs docker


network inspect --format '{{ .Name }}:
{{ .Options }}'
You should run the command below and ensure You should not share user namespaces between host
that it does not return any value for UsernsMode. If and containers. For example, you should not run the
it returns a value of host, it means that the host command below:
user namespace is shared with its containers.
docker run --rm -it --userns=host ubuntu bash
docker ps --quiet --all | xargs docker inspect --
format '{{ .Id }}:
UsernsMode={{ .HostConfig.UsernsMode }}'

You should run the following command: You should ensure that no containers mount
docker.sock as a volume.
docker ps --quiet --all | xargs docker inspect --
format '{{ .Id }}: Volumes={{ .Mounts }}' | grep
docker.sock

This would return any instances where docker.sock


had been mapped to a container as a volume.
compromise the host and the containers running on it. It is
line with organizational
Default valuesecurity policy. Compliance Status

By default, Docker swarm mode is not


enabled.

By default, the docker-default


AppArmor profile is applied to running
containers. The Docker binary
generates this profile and then loads it
into the kernel.

By default, no SELinux security


options are applied on containers.
By default, the capabilities below are
applied to containers:

AUDIT_WRITE CHOWN
DAC_OVERRIDE FOWNER FSETID
KILL MKNOD NET_BIND_SERVICE
NET_RAW SETFCAP SETGID
SETPCAP SETUID SYS_CHROOT

FALSE

Docker defaults to using a read-write


volume but you can also mount a
directory read-only. By default, no
sensitive host directories are mounted
within containers.
By default, SSH server is not running
inside the container. Only one process
per container is allowed.

By default, mapping a container port


to a privileged port on the host is
allowed.
Note: There might be certain cases
where you want to map privileged
ports, because if you forbid it, then the
corresponding application has to run
outside of a container.

For example: HTTP and HTTPS load


balancers have to bind 80/tcp and
443/tcp respectively. Forbidding to
map privileged ports effectively forbids
from running those in a container, and
mandates using an external load
balancer. In such cases, those
containers instances should be
marked as exceptions for this
recommendation.
By default, all the ports that are listed
in the Dockerfile under the EXPOSE
instruction for an image are opened
when a container is run with the -P or
--publish-all flags.

By default, containers connect to the


Docker bridge when starting and do
not run in the context of the host's
network stack.
By default, all containers on a Docker
host share their resources equally and
no memory limits are enforced.

By default, all containers on a Docker


host share their resources equally. No
CPU shares are enforced.
By default, a container has its root
filesystem writeable, allowing all
container processes to write files
owned by the container's actual
runtime user.

By default, Docker exposes the


container ports on 0.0.0.0, the
wildcard IP address that will match
any possible incoming network
interface on the host machine.
By default, containers are not
configured with restart policies.

By default, all containers have the PID


namespace enabled and the therefore
the host's process namespace is not
shared with its containers.

By default, all containers have their


IPC namespace enabled and host
IPC namespace is not shared with
any container.
By default, host devices are not
exposed to containers. If you do not
provide sharing permissions and
choose to expose a host device to a
container, the host device is be
exposed with read, write and mknod
permissions.

Container instances inherit the default


ulimit settings set at the Docker
daemon level.

By default, the container mounts are


private.

By default, all containers have the


UTS namespace enabled and the
host UTS namespace is not shared
with any containers.
When you run a container, it uses the
default profile unless you override it
with the --security-opt option.

By default, the docker exec command


runs without the --privileged option.

By default, the docker exec command


runs without the --user option.

By default, containers run under


docker cgroup.

By default, new privileges are not


restricted.

By default, health checks are not


carried out at container runtime.
By default, Docker commands extract
the local copy unless version pinning
mechanisms are used or the local
cache is cleared.

The Default value for --pids-limit is 0


which means there is no restriction on
the number of forks. Note that the
PIDs cgroup limit works only for kernel
versions 4.3 and higher.

By default, Docker runs containers


within the default docker0 bridge.

By default, the host user namespace


is shared with containers unless user
namespace support is enabled.

By default, docker.sock is not


mounted inside containers.
This section covers some of the operational security issues associated with Docker deployments. These are best prac
organizations shouldname
Control ref. Control extend their current security best practices and policies to include containers.
Description
6.1 Ensure that image sprawl is avoided (Manual) You should not keep a large number of
6.2 Ensure that container sprawl is avoided container
You shouldimages on the
not keep same
a large host. Use
number of only
(Manual) containers on the same host.
oyments. These are best practices that should be followed where possible. Most of the recommendations in this section simply a
containers.Audit Check Remediation steps (if not compliant)
Step 1 Make a list of all image IDs You should keep only the images that you
that
Stepare
1 - currently instantiated
Find the total numberbyof actually need
You should and establish
periodically a workflow
check to
your container
containers you have on the host: inventory on each host and clean up
st of the recommendations in this section simply act as reminders that
Default value Compliance Status
Images and layered filesystems
remain accessible
By default, Docker on thenot
does host until
restrict
the number of containers you may
This section lists the recommendations that alter and secure the behavior of the Docker Swarm. If you are not using D
Control ref. Control name Description
7.1 Ensure that the minimum number of You should ensure that the minimum number of
manager nodes have been created in required manager nodes is created in a swarm.
a swarm (Manual)

7.2 Ensure that swarm services are By default, Docker swarm services will listen on
bound to a specific host interface all interfaces on the host. This may not be
(Manual) necessary for the operation of the swarm where
the host has multiple network interfaces.

7.3 Ensure that all Docker swarm overlay Ensure that all Docker swarm overlay networks
networks are encrypted (Manual) are encrypted.

7.4 Ensure that Docker's secret You should use Docker's in-built secret
management commands are used for management command for control of secrets.
managing secrets in a swarm cluster
(Manual)

7.5 Ensure that swarm manager is run in You should review whether you wish to run
auto-lock mode (Manual) Docker swarm manager in auto-lock mode.

7.6 Ensure that the swarm manager auto- You should rotate the swarm manager auto-lock
lock key is rotated periodically key periodically.
(Manual)
7.7 Ensure that node certificates are You should rotate swarm node certificates in
rotated as appropriate (Manual) line with your organizational security policy.

7.8 Ensure that CA certificates are You should rotate root CA certificates as
rotated as appropriate (Manual) appropriate.

7.9 Ensure that management plane traffic You should separate management plane traffic
is separated from data plane traffic from data plane traffic.
(Manual)
cker Swarm. If you are not using Docker Swarm then the recommendations in this section do not apply.
Audit Check Remediation steps (if not compliant)
Run docker info and verify the number of managers. If an excessive number of managers is configured, the
docker info --format '{{ .Swarm.Managers }}' excess nodes can be demoted to workers using the
following command:
Alternatively run the below command.
docker node demote <ID>
docker node ls | grep 'Leader'
Where <ID> is the node ID value of the manager to be
demoted.

You should check the network listener on port 2377 Resolving this issues requires re-initialization of the
(the default for docker swarm) and 7946 (container swarm, specifying a specific interface for the --listen-addr
network discovery), and confirm that it is only parameter.
listening on specific interfaces. For example, in this
could be done using the following command:

ss -lp | grep -iE ':2377|:7946'

You should run the command below to ensure that You should create overlay networks the with --opt
each overlay network has been encrypted. encrypted flag.

docker network ls --filter driver=overlay --quiet |


xargs docker network inspect --format
'{{.Name}} {{ .Options }}'

On a swarm manager node, you should run the You should follow the docker secret documentation and
command below and ensure docker secret use it to manage secrets effectively.
management is used in your environment where this
is in line with your IT security policy.

docker secret ls

You should run the command below If you are initializing a swarm, use the command below.

docker info --format 'Swarm Autolock: docker swarm init --autolock


{{ .Swarm.Cluster.Spec.EncryptionConfig.AutoL
ockManagers }}' If you want to set --autolock on an existing swarm
manager node, use the following command.
If the result is true, auto-lock mode is enable. You
could also run the command below. If a key value is docker swarm update --autolock
returned, it means that the swarm was initialized
with the --autolock flag. If the output is no unlock
key is set, it means that swarm was NOT initialized
with the --autolock flag. This should be reviewed in
line with the organization's IT Security policy.

docker swarm unlock-key

Currently, there is no mechanism to find out when You should run the command below to rotate the keys.
the key was last rotated on a swarm manager node.
You should check with the system administrator to docker swarm unlock-key --rotate
see if there is a key rotation process, and how often
the key is rotated. Additionally, to facilitate auditing of this recommendation,
you should maintain key rotation records and ensure that
you establish a pre-defined frequency for key rotation.
Run one of the commands below and ensure that You should run the command to set the desired expiry
the node certificate Expiry Duration is set as time on the node certificate. For example:
appropriate.
docker swarm update --cert-expiry 48h
docker info | grep "Expiry Duration"
docker info --format 'NodeCertExpiry:
{{ .Swarm.Cluster.Spec.CAConfig.NodeCertExpir
You should check the time stamp on the root CA You should run the command below to rotate a certificate.
certificate file. For example:
docker swarm ca --rotate
ls -l /var/lib/docker/swarm/certificates/swarm-
root-ca.crt

The certificate should show a time stamp in line with


the organizational rotation policy.

You should run the command below on each swarm You should initialize the swarm with dedicated interfaces
node and ensure that the management plane for management and data planes respectively. For
address is different from the data plane address. example,

docker node inspect --format '{{ .Status.Addr }}' docker swarm init --advertise-addr=192.168.0.1 --data-
self path-addr=17.1.0.3
Default value Compliance Status
Only a single manager is required to start a given
cluster.

By default, Docker swarm services listen on all


available host interfaces.

By default, data exchanged in overlay networks in


Docker swarm mode is not encrypted.

Not Applicable

By default, the swarm manager does not run in


auto-lock mode.

By default, keys are not rotated automatically.


By default, node certificates are rotated
automatically every 90 days.

By default, root CA certificates are not rotated.

By default, data plane traffic is not separated from


management plane traffic.

You might also like