$30 off During Our Annual Pro Sale. View Details »

実践コンテナ & Kubernetes セキュリティ

mrtc0
August 12, 2021

実践コンテナ & Kubernetes セキュリティ

/dev/hardening - Hardening Drivers Conferences 2021
OWASP Evening 2021.08 - Container Security / Privacy by Design

mrtc0

August 12, 2021
Tweet

More Decks by mrtc0

Other Decks in Technology

Transcript

  1. 実践コンテナ & 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  6. コンテナセキュリティのポインタ
    ● 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 をもとに紹介します。

    View Slide

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

    View Slide

  8. 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 バイナリを上書きし任意のコード実行が可能。
    事例

    View Slide

  9. 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":[]}

    View Slide

  10. 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

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

  14. 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)

    View Slide

  15. 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 で制限する。

    View Slide

  16. コンテナから読み書きできてはいけないファイル
    ● /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

    View Slide

  17. 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 等もチェックする。

    View Slide

  18. コンテナイメージへのクレデンシャルの混入
    ● イメージビルド時にプライベートリポジトリなど認証が必要な操作を行う場合、イメージレイヤに
    クレデンシャルが残ってしまうため 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 …

    View Slide

  19. コンテナイメージの改竄
    ● レジストリに不正アクセスされてイメージが改竄されるなど、コンテナイメージのエコシステムに
    はサプライチェーン攻撃のリスクがある
    ● イメージの整合性を検証する 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

    View Slide

  20. Kubernetes の概要

    View Slide

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

    View Slide

  22. 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

    View Slide

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

    View Slide

  24. 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 を拒否できる

    View Slide

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

    View Slide

  26. 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"

    View Slide

  27. 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 は権限がほとんどないため、実質何もできな

    View Slide

  28. 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

    View Slide

  29. 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..."

    View Slide

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

    View Slide

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

    View Slide

  32. 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]

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide