鳩小屋

落書き帳

コンテナセキュリティハンズオン1:Understanding Container

第1弾ではコンテナの仕組みを理解するためにコンテナ側とホストOSからリソースの見え方や権限を簡単に確認します。

テーマ

 

 

 

kurobato.hateblo.jp

補足

  • $:ホストOS #:コンテナ内
  • アタッチとデタッチは多用するため覚えておきましょう。(以後省略します)
$docker run -it -d --rm --name test centos /bin/bash
$uname –r                                                               #カーネル
$ls /                                                                         #ルートファイルシステム
$id                                                                           #ユーザ
$ps -aufx                                                                 #プロセス一覧
$hostname                                                              #ホスト名
$docker container ls                                                #コンテナ一覧
$ip addr                                                                    #ネットワーク一覧
$ls -l /proc/$$/ns/                                                   #ネームスペース一覧
$getpcaps [pid]                                                       #コンテナ[pid]のケーパビリティ
#docker container attach [container]#アタッチ
#uname –r                                                               #カーネル
#ps -aufx                                                                 #コンテナ
#id                                                                           #ユーザ
#hostname                                                              #ホスト名
#ip addr                                                                  #ネットワーク
#pwd                                                                      #カレントディレクト
#ls /                                                                        #ルートファイルシステム
#ls -l /proc/$$/ns/                                                  #ネームスペース一覧
#ctrlを押しながらp,qの順にキー押下してデタッチ
一気にコマンドを実行してもよいですが、コンテナとホストOSを切り替えながら交互に確認すると分かりやすいと思います。
 

カーネルの共有

ホスト上でカーネル名を確認し、コンテナにアタッチしてから、コンテナ内のカーネル名を確認します。

$ uname -r
4.4.0-210-generic
$ docker container attach test
# uname -r
4.4.0-210-generic
#[ctrl+p→q]
$

ホストOSとコンテナで同じカーネル名が出力されています。このことからコンテナがホストOSのカーネルを共有していることが確認できます。
 

ルートファイルシステムの分離

同様にホストOSとコンテナOSのルートファイルシステムを確認します。

$ ls /
bin boot dev etc home lib lib64 local media mnt opt proc root run sbin srv sys tmp usr var
$ docker container attach test
# pwd
/
# ls /
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var

 /直下のディレクトリ構成が異なることがわかります。カーネルは共有しているものの、OSのシステムファイルは異なっていることが分かります。

 

ネームスペースの比較

ホストとコンテナのシェルが属するnamespaceを比較します。

$ ls -l /proc/$$/ns/
lrwxrwxrwx 1 root root 0 Apr 19 04:21 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Apr 19 04:21 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Apr 19 04:21 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Apr 19 04:21 net -> net:[4026532041]
lrwxrwxrwx 1 root root 0 Apr 19 04:21 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 19 04:21 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Apr 19 04:21 uts -> uts:[4026531838]

# ls -l /proc/$$/ns/
lrwxrwxrwx 1 root root 0 Apr 19 04:20 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Apr 19 04:20 ipc -> 'ipc:[4026532290]'
lrwxrwxrwx 1 root root 0 Apr 19 04:20 mnt -> 'mnt:[4026532288]'
lrwxrwxrwx 1 root root 0 Apr 19 04:20 net -> 'net:[4026532293]'
lrwxrwxrwx 1 root root 0 Apr 19 04:20 pid -> 'pid:[4026532291]'
lrwxrwxrwx 1 root root 0 Apr 19 04:20 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Apr 19 04:20 uts -> 'uts:[4026532289]'

 ipc,、mnt、net、pid、utsの名前空間が異なることが分かります。これは、dockerがコンテナを作成する際にデフォルトで利用するネームスペースになります。一方、cgroupやuserの名前空間は利用されていないため、どちらも同じ名前空間に属していることが確認できます。なお、userネームスペースはルートレスコンテナと呼ばれるホストのユーザ権限でコンテナ環境を動作させる方式で採用されています。

 

プロセス一覧の比較

psコマンドでプロセス一覧を比較します。

$ ps -aufx
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2 0.0 0.0 0 0 ? S Apr18 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? I< Apr18 0:00 ¥_ [kworker/0:0H] root 6 0.0 0.0 0 0 ? I< Apr18 0:00 ¥_ [mm_percpu_wq]
root 7 0.0 0.0 0 0 ? S Apr18 0:00 ¥_ [ksoftirqd/0]
root 8 0.0 0.0 0 0 ? I Apr18 0:00 ¥_ [rcu_sched]
root 9 0.0 0.0 0 0 ? I Apr18 0:00 ¥_ [rcu_bh]
root 10 0.0 0.0 0 0 ? S Apr18 0:00 ¥_ [migration/0]
root 11 0.0 0.0 0 0 ? S Apr18 0:00 ¥_ [watchdog/0]
root 12 0.0 0.0 0 0 ? S Apr18 0:00 ¥_ [cpuhp/0]
...
root 4705 0.0 0.7 709092 7148 ? Sl 03:38 0:00 ¥_ containerd-shim –namespa
root 4743 0.0 0.3 12024 3220 pts/0 Ss+ 03:38 0:00 ¥_ /bin/bash

# ps -aufx
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 12024 3220 pts/0 Ss 03:38 0:00 /bin/bash
root 17 0.0 0.3 47544 3336 pts/0 R+ 04:12 0:00 ps -aufx

 ホストOS上から見たコンテナのプロセスははrootユーザで動作していることが分かります。また、コンテナにはホストOSのプロセスが参照できないことが確認できます。

 

uts名前空間、user名前空間

$ hostname
user-VirtualBox

# hostname
1d67c8bfff63
 ipc名前空間が異なるため、ホスト名も異なります。
$ id
uid=0(root) gid=0(root) groups=0(root)
# id
uid=0(root) gid=0(root) groups=0(root)
 一方、user名前空間は共有するため、ユーザID、グループIDは同じになります。
 

 コンテナに付与された特権

ホストでコンテナプロセスに割り当てられたケーパビリティを確認します。

$ ps -aufx
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 4743 0.0 0.3 12024 3220 pts/0 Ss+ 03:38 0:00 ¥_ /bin/bash

$ getpcaps 4743
Capabilities for `4743': = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,ca p_setfcap+eip

$ docker run --privileged -it -d --rm --name test2 centos /bin/bash

$ getpcaps 6609
Capabilities for `6609': = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,35,36,37+e ip
 同じrootユーザではあるものの、特権コンテナでは通常コンテナにないケーパビリティまで付与されていることが確認できます。特に、特権コンテナでは過剰な権限が付与されるため、コンテナブレイクアウトのような脅威にさらされます。
 

後片付け

作業が終わったら不要なコンテナは削除しましょう。

#すべてのコンテナを停止
docker stop `docker ps -a -q`
#すべてのコンテナを削除
docker rm `docker ps -a -q`