Slide 1

Slide 1 text

実践コンテナ & Kubernetes セキュリティ /dev/hardening - Hardening Drivers Conferences 2021 OWASP Evening 2021.08 - Container Security / Privacy by Design Kohei Morita / @mrtc0 GMO Pepabo, Inc. / OWASP Fukuoka https://flic.kr/p/a3NYdi #devhardening

Slide 2

Slide 2 text

Kohei Morita / @mrtc0 GMO ペパボ セキュリティ対策室 シニアエンジニア OWASP Fukuoka Chapter Leader セキュリティ・キャンプ 講師 / ステアリングコミッティ https://blog.ssrf.in

Slide 3

Slide 3 text

今日話すこと ● OWASP Docker Security Cheat Sheet を題材にコンテナ、Dokcer への攻撃例と対策について ● コンテナを運用するツールとして注目を集めている Kubernetes への攻撃例と対策について ● CloudNative セキュリティについて

Slide 4

Slide 4 text

Linux コンテナの仕組み コンテナは Linux の仕組みを利用して隔離されたプロセス。様々な隔離技術を使っているが VM ほど分 離レベルは高くない。

Slide 5

Slide 5 text

コンテナの主要技術 詳しくは https://container-security.dev/ を見てください

Slide 6

Slide 6 text

コンテナセキュリティのポインタ ● OWASP Docker Security Cheat Sheet https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html ● OWASP Docker TOP 10 https://github.com/OWASP/Docker-Security ● NIST SP 800-190 Application Container Security Guide https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-190.pdf ● CIS Docker Benchmarks https://www.cisecurity.org/benchmark/docker/ OWASP Evening ということで OWASP Docker Security Cheat Sheet をもとに紹介します。

Slide 7

Slide 7 text

Docker 環境への攻撃ベクトルイメージ 💡 OWASP Docker TOP 10 の Threat Modeling も参考になります

Slide 8

Slide 8 text

OWASP Docker Security Cheat Sheet で見るコンテナセキュリティ RULE #0 - Keep Host and Docker up to date ホストと Docker を最新版にアップデートすること。 コンテナはホストとカーネルを共有しているため、カーネルの脆弱性によってはホスト側にエスケープ(BreakOut)でき る。 Dirty Cow … カーネルの脆弱性。Docker コンテナからホストに Breakout が可能。 Shocker … CAP_DAC_READ_SEARCH が許可されていたため、コンテナからホストのファイルシステムにアクセスできた。 CVE-2019-5736 … 細工されたコンテナを実行することで runc バイナリを上書きし任意のコード実行が可能。 事例

Slide 9

Slide 9 text

OWASP Docker Security Cheat Sheet で見るコンテナセキュリティ RULE #1 - Do not expose the Docker daemon socket (event to the containers) Docker の API を叩くソケット /var/run/docker.sock を誰でも叩ける状態にしないこと。この API を利用してホスト側に Breakout することが可能。rootful Docker の場合は root 権限を取得される。 外部に公開する場合は TLS の設定が必要になるが、CA の管理などが煩雑。そのため、 DOCKER_HOST=ssh://user@host などで SSH での利用がオススメ。また、authz Plugin を使う手もある。 # host の / をマウントしたコンテナを作成 root@3ba2c2752b26:/# curl -L \ --unix-socket /var/run/docker.sock \ -X POST \ -H 'Content-Type: application/json' \ --data-binary '{..., "Image": "ubuntu","Volumes": {"/hostfs/": {}},"HostConfig": {"Binds": ["/:/hostfs"]}}' \ http://v1.24/containers/create ... {"Id":"8e15f2d344fa7bf9588f82a097e7c506429b936e85bc2a60350a018a7277403f","Warnings":[]}

Slide 10

Slide 10 text

non-root ユーザーによる Docker 操作 ● Docker をインストールしたあとに一般ユーザーでも Docker を操作できるように sudo usermod -aG docker $USER するケース ● Docker Daemon が root で動いている場合、コンテナの作成を通じて root を取得できる $ id uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant),4(adm), ... 998(docker) # host の / をコンテナの /hostfs にマウント $ docker run --rm -it -v /:/hostfs alpine:latest head /hostfs/etc/shadow root:!$6$zk2YoWYaQiea6.jg...:18564:0:99999:7::: … # host の /root/.ssh/authorized_keys に書き込み $ docker run --rm -it -v /:/hostfs alpine:latest sh # echo ‘ssh-rsa AAAAB…’ >> /hostfs/.ssh/authorized_keys

Slide 11

Slide 11 text

OWASP Docker Security Cheat Sheet で見るコンテナセキュリティ RULE #2 - Set a user Breakout された場合の影響を小さくするためにコンテナ内のユーザーを非特権にする。 ● docker run 時に -u オプションで指定する ● Dockerfile で USER 命令で指定する ● userns-remap を使う ○ User Namespace を使って UID を re-map するのでコンテナ内では root として動かすことができる ~$ docker run --rm -it alpine:latest sleep 10 ~$ ps aux | grep sleep root 3225 0.6 0.0 1568 4 pts/0 Ss+ 06:39 0:00 sleep 10 ~$ docker run --rm -it -u 000 alpine:latest sleep 10 ~$ ps aux | grep sleep vagrant 3372 1.0 0.0 1568 4 pts/0 Ss+ 06:40 0:00 sleep 10

Slide 12

Slide 12 text

OWASP Docker Security Cheat Sheet で見るコンテナセキュリティ RULE #3 - Limit capabilities (Grant only specific capabilities, needed by a container) --privileged を使うとすべての Capability が追加されるため、必要に応じて --cap-drop で落とすか、--cap-add で追加 するのが望ましい。 また、特定の Capability の追加は Breakout の原因となるため注意。 ubuntu@docker:~$ docker run --cap-add syslog --rm -it ubuntu:20.04 root@1577bebb133d:/# dmesg | head [ 0.000000] Linux version 5.4.0-47-generic (buildd@lcy01-amd64-014) (gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)) #51-Ubuntu SMP Fri Sep 4 19:50:52 UTC 2020 (Ubuntu 5.4.0-47.51-generic 5.4.55) [ 0.000000] Command line: earlyprintk=serial console=ttyS0 root=/dev/vda1 rw panic=1 no_timer_check [ 0.000000] KERNEL supported cpus: [ 0.000000] Intel GenuineIntel [ 0.000000] AMD AuthenticAMD ... root@1577bebb133d:/# dmesg -C root@1577bebb133d:/# dmesg

Slide 13

Slide 13 text

Privileged Container ● 特権コンテナは強力な権限を持っているほか、Seccomp なども適用されないため、ホストとの分離 が弱い ● 攻撃例 ○ keyctl(2) で鍵を取得 ○ カーネルモジュールのロード ○ その他 cgroup release_agent や uevent_helper, core_pattern, binfmt_misc などの call_usermodehelper_exec を呼び出す機能で Breakout https://asciinema.org/a/361484 https://asciinema.org/a/361483

Slide 14

Slide 14 text

OWASP Docker Security Cheat Sheet で見るコンテナセキュリティ RULE #4 - Add –no-new-privileges flag setuid / setgid バイナリによる権限昇格を防ぐために no-new-privileges オプションを使う。 No New Privileges は子プロセスが新しい特権を取得できないようにする Linux の機能。 # Dockerfile FROM ubuntu:18.04 RUN cp /bin/bash /bin/bash2 && chmod 4755 /bin/bash2 RUN useradd -ms /bin/bash newuser USER newuser CMD ["/bin/bash"] $ docker run -it --rm test:latest newuser@985fc45b58c1:/$ id uid=1000(newuser) gid=1000(newuser) groups=1000(newuser) newuser@985fc45b58c1:/$ /bin/bash2 -p bash2-4.4# id uid=1000(newuser) gid=1000(newuser) euid=0(root) groups=1000(newuser) $ docker run -it --security-opt=no-new-privileges:true --rm test:latest newuser@d96857132041:/$ id uid=1000(newuser) gid=1000(newuser) groups=1000(newuser) newuser@d96857132041:/$ /bin/bash2 -p newuser@d96857132041:/$ id uid=1000(newuser) gid=1000(newuser) groups=1000(newuser)

Slide 15

Slide 15 text

OWASP Docker Security Cheat Sheet で見るコンテナセキュリティ RULE #5 - Disable inter-container communication (--icc=false) デフォルトで Docker コンテナはすべてのコンテナと通信ができる。コンテナ間の通信を制限するには Docker Daemon のオプションに icc=false を設定する。コンテナ間の通信を許可する場合は --link オプションで指定する。 RULE #6 - Use Linux Security Module (seccomp, AppArmor, or SELinux) LSM を使って保護する。Debian / Ubuntu などでは AppArmor, CentOS / RHEL などでは SELinux が使われる。 どれもデフォルトのプロファイルが適用されており、カーネルの脆弱性や Breakout を防ぐ / 緩和するために機能してい るため、無効にするべきではない。 RULE #7 - Limit resources (memory, CPU, file descriptors, processes, restarts) DoS 対策のためにメモリや CPU の使用量などを cgroup や ulimit で制限する。

Slide 16

Slide 16 text

コンテナから読み書きできてはいけないファイル ● /proc や /sys 配下などにはカーネルとやり取りするインターフェイスが存在するため、Read Only としてマウントしたり LSM でアクセスを制御している / # echo 1 > /proc/sysrq-trigger sh: can't create /proc/sysrq-trigger: Read-only file system / # cat /proc/kcore cat: can't open '/proc/kcore': Permission denied

Slide 17

Slide 17 text

OWASP Docker Security Cheat Sheet で見るコンテナセキュリティ RULE #8 - Set filesystem and volumes to read-only コンテナのファイルシステムを read-only にすることで、そもそも改ざんされないようにする。 一時ファイルなどについては tmpfs をマウントする。 RULE #9 - Use static analysis tools コンテナイメージに含まれるパッケージの脆弱性スキャンを行う。Docker などのコンテナランタイム自体の設定ファイル も inspec などを利用して設定ミスを検出する。 RULE #11 - Lint the Dockerfile at build time にあるように、ベースイメージの pinning 等もチェックする。

Slide 18

Slide 18 text

コンテナイメージへのクレデンシャルの混入 ● イメージビルド時にプライベートリポジトリなど認証が必要な操作を行う場合、イメージレイヤに クレデンシャルが残ってしまうため docker history やイメージのエクスポートで漏洩する可能性 がある ● Docker では buildkit を使うことで安全にクレデンシャルを扱うことができる FROM ubuntu:20.04 … RUN --mount=type=secret,id=aws,target=/home/user/.aws/credentials,uid=1000 \ aws s3 cp … docker build --secret id=aws,src=$HOME/.aws/credentials …

Slide 19

Slide 19 text

コンテナイメージの改竄 ● レジストリに不正アクセスされてイメージが改竄されるなど、コンテナイメージのエコシステムに はサプライチェーン攻撃のリスクがある ● イメージの整合性を検証する Docker Content Trust を利用する ○ Publisher は秘密鍵でイメージに署名 ○ User が Pull する際は Publisher の公開鍵などを利用し整合性と作成者を検証 ● タグではなく digest を指定することで不正なイメージの意図しないデプロイを防ぐことができる docker run alpine:be9bdc0ef8e96dbc428dc189b31e2e3b05523d96d12ed627c37aa2936653258c ~ $ docker trust inspect --pretty ubuntu:latest Signatures for ubuntu:latest SIGNED TAG DIGEST SIGNERS latest c95a8e48bf88e9849f3e0f723d9f49fa12c5a00cfc6e60d2bc99d87555295e4c (Repo Admin) Administrative keys for ubuntu:latest Repository Key: 8273733f491f362bb36710fd8a99f78c3fbaecd8d09333985c76f1064b80760f Root Key: 1f9bc7ae6335ae41ee03e983c0e31303901be567b4cdb3fc7c7363f0591128ff

Slide 20

Slide 20 text

Kubernetes の概要

Slide 21

Slide 21 text

Kubernetes のセキュリティ ● コンテナ(ランタイム)セキュリティ + Kubernetes のコンポーネントのセキュリティ

Slide 22

Slide 22 text

Kubernetes セキュリティのポインタ ● OWASP Kubernetes Security Cheat Sheet https://cheatsheetseries.owasp.org/cheatsheets/Kubernetes_Security_Cheat_Sheet.html ● CIS Kubernetes Benchmark https://www.cisecurity.org/benchmark/kubernetes/ ● Kubernetes Hardening Guidance - CISA / NSA https://media.defense.gov/2021/Aug/03/2002820425/-1/-1/1/CTR_KUBERNETES%20HAR DENING%20GUIDANCE.PDF

Slide 23

Slide 23 text

Kubernetes API ● コントロールプレーンにある Kubernetes API を外部に公開するフロントエンド。Kubernetes 利 用者はこの API を介してリソースを操作するため、認証が必須 ● Kubernetes では様々な認証機能があるが OIDC / IAM Provider による認証がオススメ AuthN / AuthZ の流れ ● AuthN … リクエストに含まれる資格情報が正しいか検証する ● AuthZ … 認証されたユーザーが該当リソースへの権限を持っているか検証する ● Admission Controller … リクエスト内容の検証や書き換えなどを行う

Slide 24

Slide 24 text

Kubernetes API Anonymous Request ● 認証情報を含まないリクエストを送信すると Anonymous Request として処理される ● このとき RBAC としては system:anonymous User と system:unauthenticated Group になる ● もしこのロールに権限を付与した場合、外部からクラスタを操作できてしまうことに繋がる ❯ curl -k https://192.168.99.110:8443/api/v1/namespaces/ { "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "namespaces is forbidden: User \"system:anonymous\" cannot list resource …”, "reason": "Forbidden", "details": { "kind": "namespaces" }, "code": 403 } ❯ curl -k https://192.168.99.110:8443/api/v1/namespaces/ { "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401 } kube-apiserver に anonymous-auth=false を設定することで Anonymous Request を拒否できる

Slide 25

Slide 25 text

Kubernetes API https://hackerone.com/reports/455645

Slide 26

Slide 26 text

kubelet ● Node で実行される Pod の管理を行うエージェント。API を通して Pod の一覧やコンテナでコマン ドの実行が可能。 ● kube-apiserver 同様に Anonymous Request の拒否と Authorization Mode を適切に設定するこ とを推奨 $ curl -s -k https://localhost:10250/pods | jq .items[].metadata.name "coredns-558bd4d5db-wn86h" "test" "etcd-minikube" "kube-apiserver-minikube" "kube-controller-manager-minikube" "kube-scheduler-minikube" "storage-provisioner" "kube-proxy-6hkc6"

Slide 27

Slide 27 text

ServiceAccount ● ServiceAccount Token は Pod の /var/run/secrets/kubernetes.io/serviceaccounts/ 配下にマウ ントされる ● Pod が侵害された場合は、その ServiceAccount の権限に応じてリソースの操作が可能になる root@test:/# ls /var/run/secrets/kubernetes.io/serviceaccount/ ca.crt namespace token root@test:/# KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) root@test:/# curl -sSk \ -H "Authorization: Bearer $KUBE_TOKEN" \ https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/default/pods/$HOSTNAME ... "status": "Failure", "message": "pods \"test\" is forbidden: User \"system:serviceaccount:default:default\" …”, "reason": "Forbidden", ... ● 例えば Job を生成するような権限を持った SA Token がマウントされている場合は Privileged コンテナや hostPath マウントするようなコンテナを作り、権限昇格が可能になる ● default SA に権限を付与しない、automountServiceAccountToken を設定して自動でマウントしないなど ✍ デフォルトでマウントされる default SA は権限がほとんどないため、実質何もできな い

Slide 28

Slide 28 text

Secrets ● Secret の manifest は Base64 でエンコードされているだけなので GitOps と相性が悪いため、暗 号化等が必要 既存のツールがたくさんある。それぞれ Pros / Cons あるので、クラスタに合わせて利用するツー ルを選定すると良い。 ● vault-k8s ● external-secrets ● sealed-secrets ● SOPS ● bank-vaults ● kubesec apiVersion: v1 data: password: cEBzc3cwcmQ= kind: Secret metadata: creationTimestamp: null name: password

Slide 29

Slide 29 text

etcd ● Kubernetes クラスタのデータを保管する KV Store として利用されている。Secret も含まれているのでアクセス 制御と暗号化を行う必要がある ● 多くの場合は TLS クライアント認証が用いられるようになっているが、暗号化はデフォルトで行われない ❯ kubectl create secret generic password --from-literal=flag='p@ssw0rd' secret/password created $ ETCDCTL_API=3 etcdctl \ --endpoints https://127.0.0.1:2379 \ --cacert /var/lib/minikube/certs/etcd/ca.crt \ --key /var/lib/minikube/certs/etcd/healthcheck-client.key \ --cert /var/lib/minikube/certs/etcd/healthcheck-client.crt \ get -w fields /registry/secrets/default/password ... "Value" : "k8s\x00\n\f\n\x02v1\x12\x06Secret\x12\xcc\x01\n\xaf\x01\n\bpassword\x12\x00\x1a\adefault\"\x00*$12610d47-8a48-4b6f-bbe7-2f0f73150f282\x008\x 00B\b\b͈ͥ\x06\x10\x00z\x00\x8a\x01_\n\x0ekubectl-create\x12\x06Update\x1a\x02v1\"\b\b͈ͥ\x06\x10\x002\bFieldsV1:-\n+{\"f:data\":{\".\":{},\"f:flag\":{}},\" f:type\":{}}\x12\x10\n\x04flag\x12\bp@ssw0rd\x1a\x06Opaque\x1a\x00\"\x00" # 平文で保存されている ... # 暗号化するとこうなる "Value" : "k8s:enc:aesgcm:v1:key1:ZZS(՝Uu\x1e\x81\xc0owc\x83j\x8e\x05\x8b\a(\x85\xb2\x0e\x8dd%\xc9!\xeey7\x..."

Slide 30

Slide 30 text

Network デフォルトではすべての Pod が互いに通信することが可能であるため、コンテナに侵入された場合に横 展開される。また、マネージドサービスの場合は Metadata Server にアクセスされ権限昇格に繋がる。 EKS の場合 インスタンス情報の取得 VPC, SecurityGroup 情報の取得 ECR リポジトリからイメージの取得 GKE の場合 Metadata に含まれるクレデンシャルを使って kubelet に なりすまし、Secret などの取得が可能 Network Policy を使い、特定の Pod 同士のみが疎通できるようにする。 Istio などを用いてアプリケーション(Sidecar)同士が認証するなど、サービスメッシュによる通信制御を行う。 対策

Slide 31

Slide 31 text

クラウドネイティブ化によるセキュリティの変化 ● 一方で、従来の守り方では通用しない点も出てきている FIM … コンテナのファイルシステムを Read Only にできない場合、どう検知する? コマンド実行監視 … auditd ではコンテナのID/名前などは拾えない アンチウィルス … 既存の AV はコンテナに対応している? ● 一つのクラスタに複数のロール/アプリケーションが動くようになり、Attack Surfaces が増え、 横展開、権限昇格の脅威が大きくなっている ● コンテナ化によって依存パッケージの減少など、小さくてセキュアな環境が構築できるようにな り、アップデート戦略も比較的容易になった ● Immutable な環境のため、「異常」を検知しやすくなった

Slide 32

Slide 32 text

Falco ● カーネルモジュール / eBPF などを利用してシステムコールや Kubernetes の audit ログを監査するツール 例えば... ● Pod 内で execve が発行されプロセスが Spawn された ● /etc や /usr/bin などの特定のディレクトリやファイルに変更があった ● Pod から不審なサーバーに接続した ● Secret にアクセスがあった などなどを YAML ベースのルールをもとに検知&アラート発砲できる - rule: Launch Privileged Container desc: Detect the initial process started in a privileged container. condition: > container_started and container and container.privileged=true and not falco_privileged_containers and not user_privileged_containers output: Privileged container started ... priority: INFO tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement]

Slide 33

Slide 33 text

OpenPolicyAgent ● IaC と同様に「あるべき状態」を宣言し、ドリフトを検知するようなセキュリティテストや異常検 知がクラウドネイティブ環境でも大きなテーマとして扱われている ● 宣言的なセキュリティポリシーフレームワークである Open Policy Agent は Istio / Envoy や Kubernetes Admission Controller として AuthN / AuthZ ロジックを定義できる

Slide 34

Slide 34 text

CNCF Landscape (Security) https://landscape.cncf.io/

Slide 35

Slide 35 text

これからのクラウドネイティブセキュリティ ● クラウドネイティブなアーキテクチャでは、それぞれの開発工程でセキュリ ティを取り入れる必要があり、セキュリティ設計力が求められる ● 組織の全員がセキュリティ, 信頼性に対して責任を持つ文化作り ● 良いサービス(=安定性, 頻繁なデプロイなど)を提供するために、セキュリ ティに関しても復旧も視野にいれた自動化の仕組みを実現していく