Blog
Dockerにおけるセキュリティポイント(補足)
はじめに
こんにちは、アドテクスタジオでセキュリティエンジニアをしている岡崎です。
先日、 「11/14 サイバーエージェントとさくらインターネットのインフラ談義」 のLT枠に参加させていただき、以下の資料の発表をさせていただきました。
LT枠では10分ほどしか時間なく、とても緊張し、お話できなかった内容を追加して書かせていただきます。
最近、アドテクスタジオではDockerやk8sなどのコンテナ技術を利用しているプロダクト・システムが数多くあります。
そのなかで、セキュリティエンジニアとしてコンテナ技術を活用するときにどのような点に注意する必要があるのかを、Dockerを試しながら洗い出してみました。
今回のDockerのアーキテクチャからセキュリティポイントとして着目したのは、以下の点になります。
・クライアントとデーモン間
ー セキュアな通信
ー 接続制御
・レジストリ
ー セキュアな通信
ー 接続制御
・イメージ
ー イメージの信頼性
・コンテナ
ー コンテナの信頼性
ー システムコールの制御
参考: http://docs.docker.jp/engine/introduction/understanding-docker.html
・クライアントとデーモン間
と
・レジストリ
の
ー セキュアな通信
ー 接続制御
に関しては、TLS証明書を用いた「SSH公開鍵認証」や「WebサーバのSSL/TLS証明書」と同じ原理になります。
通信の暗号化はもちろんのこと、デーモンやレジストリにアクセスできるユーザを制限してセキュアに使いましょう。
・イメージ
ー イメージの信頼性
に関しては、イメージ上で利用しているミドルウェアなどのパッケージに脆弱性が含まれているバージョンが利用されていないかをチェックすることができます。
Docker Hub(エンタープライズ版)には「Docker Security Scanning」という機能があり、Docker Hubにイメージをアップしておくと、定期的にCVE(Common Vulnerabilities and Exposures:脆弱性情報データベース)の情報を元に脆弱性チェックを行ってくれます。
「Docker Hub」で公開されているイメージの中で、「Official」マークのついているものに関しては、イメージスキャン済のものなので、安心して利用できます。
参考: https://hub.docker.com/explore/
・コンテナ
ー コンテナの信頼性
ー システムコールの制御
に関しては、docker run時のオプションがあり、詳細なセキュリティ設定をすることが可能です。
[コンテナの信頼性]
イメージスキャンに関しては、docker runしていない状態での静的スキャンになりますが、以下で説明します「Docker Bench for Security」に関しては、コンテナに対し以下の項目でセキュリティチェックをしてくれます。
1 2 3 4 5 6 7 |
#実行方法 $ sudo docker run -it --net host --pid host --cap-add audit_control \ -v /var/lib:/var/lib \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/lib/systemd:/usr/lib/systemd \ -v /etc:/etc --label docker-bench-security \ diogomonica/docker-bench-security |
参考: https://github.com/docker/docker-bench-security
*コンテナがあるインスタンス内で実行しないといけないのが難点です
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#チェック項目: [INFO] 1 - Host Configuration ホストに対しての設定確認 [INFO] 2 - Docker Daemon Configuration [INFO] 3 - Docker Daemon Configuration Files デーモンに関しての設定確認 [INFO] 4 - Container Images and Build Files [INFO] 5 - Container Runtime コンテナに対しての設定確認 [INFO] 6 - Docker Security Operations |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
#実行結果 docker run -it --net host --pid host --cap-add audit_control \ > -v /var/lib:/var/lib \ > -v /var/run/docker.sock:/var/run/docker.sock \ > -v /usr/lib/systemd:/usr/lib/systemd \ > -v /etc:/etc --label docker-bench-security \ > diogomonica/docker-bench-security # ------------------------------------------------------------------------------ # Docker Bench for Security v1.0.0 # # Docker, Inc. (c) 2015 # # Checks for dozens of common best-practices around deploying Docker containers in production. # Inspired by the CIS Docker 1.6 Benchmark: # https://benchmarks.cisecurity.org/tools2/docker/CIS_Docker_1.6_Benchmark_v1.0.0.pdf # ------------------------------------------------------------------------------ Initializing Wed Nov 15 03:20:26 GMT 2017 [INFO] 1 - Host Configuration [WARN] 1.1 - Create a separate partition for containers [PASS] 1.2 - Use an updated Linux Kernel [PASS] 1.5 - Remove all non-essential services from the host - Network [PASS] 1.6 - Keep Docker up to date [INFO] 1.7 - Only allow trusted users to control Docker daemon [INFO] * docker:x:993: [WARN] 1.8 - Failed to inspect: auditctl command not found. [WARN] 1.9 - Failed to inspect: auditctl command not found. [WARN] 1.10 - Failed to inspect: auditctl command not found. [INFO] 1.11 - Audit Docker files and directories - docker-registry.service [INFO] * File not found [WARN] 1.12 - Failed to inspect: auditctl command not found. [WARN] 1.13 - Failed to inspect: auditctl command not found. [INFO] 1.14 - Audit Docker files and directories - /etc/sysconfig/docker [INFO] * File not found [INFO] 1.15 - Audit Docker files and directories - /etc/sysconfig/docker-network [INFO] * File not found [INFO] 1.16 - Audit Docker files and directories - /etc/sysconfig/docker-registry [INFO] * File not found [INFO] 1.17 - Audit Docker files and directories - /etc/sysconfig/docker-storage [INFO] * File not found [INFO] 1.18 - Audit Docker files and directories - /etc/default/docker [INFO] * File not found [INFO] 2 - Docker Daemon Configuration [PASS] 2.1 - Do not use lxc execution driver [WARN] 2.2 - Restrict network traffic between containers [PASS] 2.3 - Set the logging level [PASS] 2.4 - Allow Docker to make changes to iptables [PASS] 2.5 - Do not use insecure registries [INFO] 2.6 - Setup a local registry mirror [INFO] * No local registry currently configured [PASS] 2.7 - Do not use the aufs storage driver [PASS] 2.8 - Do not bind Docker to another IP/Port or a Unix socket [INFO] 2.9 - Configure TLS authentication for Docker daemon [INFO] * Docker daemon not listening on TCP [INFO] 2.10 - Set default ulimit as appropriate [INFO] * Default ulimit doesn't appear to be set [INFO] 3 - Docker Daemon Configuration Files [PASS] 3.1 - Verify that docker.service file ownership is set to root:root [PASS] 3.2 - Verify that docker.service file permissions are set to 644 [INFO] 3.3 - Verify that docker-registry.service file ownership is set to root:root [INFO] * File not found [INFO] 3.4 - Verify that docker-registry.service file permissions are set to 644 [INFO] * File not found [INFO] 3.5 - Verify that docker.socket file ownership is set to root:root [INFO] * File not found [INFO] 3.6 - Verify that docker.socket file permissions are set to 644 [INFO] * File not found [INFO] 3.7 - Verify that Docker environment file ownership is set to root:root [INFO] * File not found [INFO] 3.8 - Verify that Docker environment file permissions are set to 644 [INFO] * File not found [INFO] 3.9 - Verify that docker-network environment file ownership is set to root:root [INFO] * File not found [INFO] 3.10 - Verify that docker-network environment file permissions are set to 644 [INFO] * File not found [INFO] 3.11 - Verify that docker-registry environment file ownership is set to root:root [INFO] * File not found [INFO] 3.12 - Verify that docker-registry environment file permissions are set to 644 [INFO] * File not found [INFO] 3.13 - Verify that docker-storage environment file ownership is set to root:root [INFO] * File not found [INFO] 3.14 - Verify that docker-storage environment file permissions are set to 644 [INFO] * File not found [PASS] 3.15 - Verify that /etc/docker directory ownership is set to root:root [PASS] 3.16 - Verify that /etc/docker directory permissions are set to 755 [INFO] 3.17 - Verify that registry certificate file ownership is set to root:root [INFO] * Directory not found [INFO] 3.18 - Verify that registry certificate file permissions are set to 444 [INFO] * Directory not found [INFO] 3.19 - Verify that TLS CA certificate file ownership is set to root:root [INFO] * No TLS CA certificate found [INFO] 3.20 - Verify that TLS CA certificate file permissions are set to 444 [INFO] * No TLS CA certificate found [INFO] 3.21 - Verify that Docker server certificate file ownership is set to root:root [INFO] * No TLS Server certificate found [INFO] 3.22 - Verify that Docker server certificate file permissions are set to 444 [INFO] * No TLS Server certificate found [INFO] 3.23 - Verify that Docker server key file ownership is set to root:root [INFO] * No TLS Key found [INFO] 3.24 - Verify that Docker server key file permissions are set to 400 [INFO] * No TLS Key found [INFO] 3.25 - Verify that Docker socket file ownership is set to root:docker [INFO] * File not found [INFO] 3.26 - Verify that Docker socket file permissions are set to 660 [INFO] * File not found [INFO] 4 - Container Images and Build Files [WARN] 4.1 - Create a user for the container [WARN] * Running as root: eloquent_booth [WARN] * Running as root: serene_babbage [INFO] 5 - Container Runtime [WARN] 5.1 - Verify AppArmor Profile, if applicable [WARN] * No AppArmorProfile Found: eloquent_booth [WARN] * No AppArmorProfile Found: serene_babbage [WARN] 5.2 - Verify SELinux security options, if applicable [WARN] * No SecurityOptions Found: serene_babbage [WARN] 5.3 - Verify that containers are running only a single main process [WARN] * Too many proccesses running: eloquent_booth [WARN] * Too many proccesses running: serene_babbage [WARN] 5.4 - Restrict Linux Kernel Capabilities within containers [WARN] * Capabilities added: CapAdd=[audit_control] to eloquent_booth [PASS] 5.5 - Do not use privileged containers [WARN] 5.6 - Do not mount sensitive host system directories on containers [WARN] * Sensitive directory /etc mounted in: eloquent_booth [WARN] * Sensitive directory /lib mounted in: eloquent_booth [WARN] 5.7 - Do not run ssh within containers [WARN] * Container running sshd: eloquent_booth [WARN] 5.8 - Do not map privileged ports within containers [WARN] * Privileged Port in use: 80 in serene_babbage [WARN] 5.10 - Do not use host network mode on container [WARN] * Container running with networking mode 'host': eloquent_booth [WARN] 5.11 - Limit memory usage for container [WARN] * Container running without memory restrictions: eloquent_booth [WARN] * Container running without memory restrictions: serene_babbage [WARN] 5.12 - Set container CPU priority appropriately [WARN] * Container running without CPU restrictions: eloquent_booth [WARN] * Container running without CPU restrictions: serene_babbage [WARN] 5.13 - Mount container's root filesystem as read only [WARN] * Container running with root FS mounted R/W: eloquent_booth [WARN] * Container running with root FS mounted R/W: serene_babbage [WARN] 5.14 - Bind incoming container traffic to a specific host interface [WARN] * Port being bound to wildcard IP: 0.0.0.0 in serene_babbage [PASS] 5.15 - Do not set the 'on-failure' container restart policy to always [WARN] 5.16 - Do not share the host's process namespace [WARN] * Host PID namespace being shared with: eloquent_booth [PASS] 5.17 - Do not share the host's IPC namespace [PASS] 5.18 - Do not directly expose host devices to containers [INFO] 5.19 - Override default ulimit at runtime only if needed [INFO] * Container no default ulimit override: eloquent_booth [INFO] * Container no default ulimit override: serene_babbage [INFO] 6 - Docker Security Operations [INFO] 6.5 - Use a centralized and remote log collection service [INFO] * Container has no volumes, ensure centralized logging is enabled : serene_babbage [INFO] 6.6 - Avoid image sprawl [INFO] * There are currently: 26 images [WARN] * Only 8 out of 26 are in use [INFO] 6.7 - Avoid container sprawl [INFO] * There are currently a total of 8 containers, with 2 of them currently running |
参考: https://github.com/docker/docker-bench-security
わかりやすいところですと「rootユーザで実行している」と指摘されているのがわかります。
1 2 3 4 |
[INFO] 4 - Container Images and Build Files [WARN] 4.1 - Create a user for the container [WARN] * Running as root: eloquent_booth [WARN] * Running as root: serene_babbage |
この基準は、「Understanding Docker Security and Best Practices」にて定義されているものになるようです。熟読しておきましょう。
参考: https://blog.docker.com/2015/05/understanding-docker-security-and-best-practices/
[システムコールの制御]
docker run時のオプションに「–security-opt」というものがあります。
1 2 3 4 5 6 7 8 9 |
#AppArmorが有効なホスト上 --security-opt=apparmor:$domain #SELINUXが有効なホスト上 --security-opt=label:user:$userID --security-opt=label:role:$role --security-opt=label:type:$type --security-opt=label:level:$level --security-opt=label:disable |
のようなオプションを追加することで、MAC(Mandatory Access Control:強制アクセス制御)を実現できます。
また、「seccomp(secure computing mode)」オプションを利用することで、コンテナ上で利用可能なシステムコールを細かく制御することもできます。
1 |
--security-opt seccomp:$profile |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#利用するには以下の項目が「y」になっていること $ grep SECCOMP /boot/config-$(uname -r) CONFIG_HAVE_ARCH_SECCOMP_FILTER=y CONFIG_SECCOMP_FILTER=y CONFIG_SECCOMP=y #default sampleの実行 #https://github.com/docker/labs/blob/master/security/seccomp/seccomp-profiles/default.json $ docker container run --rm -it --security-opt seccomp=default.json alpine sh / # chmod 777 / -v mode of '/' changed to 0777 (rwxrwxrwx) #chmod禁止パターン sampleの実行 #https://github.com/docker/labs/blob/master/security/seccomp/seccomp-profiles/default-no-chmod.json #以下の3つのシステムコールが削除されていることがわかります。 ーーーーー - { - "name": "chmod", - "action": "SCMP_ACT_ALLOW", - "args": [] - }, - { - "name": "fchmod", - "action": "SCMP_ACT_ALLOW", - "args": [] - }, - { - "name": "fchmodat", - "action": "SCMP_ACT_ALLOW", - "args": [] - }, ーーーーー $ docker container run --rm -it --security-opt seccomp=default-no-chmod.json alpine sh / # chmod 777 / -v chmod: /: Operation not permitted |
参考: https://github.com/docker/labs/tree/master/security/seccomp
https://docs.docker.com/engine/security/seccomp/
おわりに
Dockerのセキュリティ周りはこれからどんどん熱くなってくると思うので、今後いろいろ試し、アドテクスタジオのセキュリティ強化のために活用できる仕組みを考えていこうと思っています。
Author