kubestronautへの道 ~CKS編 その20 killer coda「Privilege Escalation」~

tech article

今日覚えて帰ること

Privilege Escalation

日本語では権限昇格
Kubernetesにおいては、コンテナにrootユーザーでは入れてしまうことに対して使うことが多い。
SecurityContextというフィールドの下に設定を行うことで、権限昇格を防ぐことができる。

Privilege Escalation Containers

Set Privilege Escalation for Deployment

There is a Deployment named logger which constantly outputs the NoNewPrivs flag.

Let the Pods of that Deployment run with Privilege Escalation disabled.

The logs should show the field change.

deployment によって生成されている pod の権限昇格を無効化せよ、と言っています。

SecurityContextの設定をするだけです。
spec 配下に記述するものと spec.container 配下に記述するものがあるので要注意です。

Podとコンテナにセキュリティコンテキストを設定する
セキュリティコンテキストはPod・コンテナの特権やアクセスコントロールの設定を定義します。 セキュリティコンテキストの設定には以下のものが含まれますが、これらに限定はされません。 任意アクセス制御: user ID (UID) と group ID (GID)に基づいて、ファイルなどのオブジェクトに対する許可を行います...
controlplane $ k edit deployments.apps logger 
deployment.apps/logger edited

修正が必要な箇所の近辺を切り出しています。
また、修正した箇所を赤字にしています。

spec:
  containers:
  - command:
    - sh
    - -c
    - while true; do cat /proc/1/status | grep NoNewPrivs; sleep 1; done
    image: bash:5.0.18-alpine3.14
    imagePullPolicy: IfNotPresent
    name: httpd
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    securityContext:
      allowPrivilegeEscalation: false
  dnsPolicy: ClusterFirst
  restartPolicy: Always

これで完了です。

Privileged Containers

Create a privileged Pod

Create a Pod named prime image nginx:alpine .

The container should run as privileged .

Install iptables (apk add iptables ) inside the Pod.

Test the capabilities using iptables -L .

特権で動く pod を作成し、 iptables をインストールし、 iptables -L で権限の確認をせよ、と言っています。

まずは pod を作成します。
–command オプションで pod 起動時に実行するコマンドを指定することが出来ます。
コマンドを実行してもすぐに破棄されてしまわないように、sleepコマンドを実行するように設定します。

特権の設定はコマンドからはできないので、一旦マニフェストファイルを書き起こして編集し、
k apply コマンドで pod を作成します。

controlplane $ k run prime --image=nginx:alpine -oyaml --dry-run=client --command -- sh -c 'sleep 1d' > pod.yaml

続いて権限昇格を有効にする設定を追記していきます。
追記した箇所は赤字にしています。

controlplane $ vi pod.yaml 


apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: prime
  name: prime
spec:
  containers:
  - command:
    - sh
    - -c
    - sleep 1d
    image: nginx:alpine
    name: prime
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
                  

先ほどの問題とやることは同じです。
修正が完了したら apply します。

controlplane $ k apply -f pod.yaml 
pod/prime created

次に、今立ち上げた pod の中に iptablesコマンド をインストールしていきます。

controlplane $ k exec prime -- apk add iptables
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
(1/4) Installing libmnl (1.0.5-r2)
(2/4) Installing libnftnl (1.2.6-r0)
(3/4) Installing libxtables (1.8.10-r3)
(4/4) Installing iptables (1.8.10-r3)
Executing busybox-1.36.1-r29.trigger
OK: 47 MiB in 70 packages
controlplane $ 

インストールが完了したら、iptables -Lコマンドを実行します。
iptablesコマンドは基本的にroot権限が必要なので、実行できていれば pod にroot権限が付与されていることになります。

controlplane $ k exec prime -- iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
controlplane $ 

これで完了です。

Create a privileged StatefulSet

There is an existing StatefulSet yaml at /application/sts.yaml .

It should run as privileged but it seems like it cannot be applied.

Fix it and create the StatefulSet.

ステートフルセットのマニフェストファイルに問題があって apply できないので修正して apply せよ、と言っています。

一旦 apply してみます。

controlplane $ k apply -f /application/sts.yaml
Error from server (BadRequest): error when creating "/application/sts.yaml": StatefulSet in version "v1" cannot be handled as a StatefulSet: strict decoding error: unknown field "spec.template.spec.securityContext.privileged"

spec.template.spec.securityContext.privileged が不明なフィールドだと言われています。
マニフェストファイルをチェックしてみましょう。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: habanero
spec:
  selector:
    matchLabels:
      app: habanero
  serviceName: habanero
  replicas: 1
  template:
    metadata:
      labels:
        app: habanero
    spec:
      securityContext:
        privileged: true
      containers:
        - name: habanero
          image: nginx:alpine
          command:
            - sh
            - -c
            - apk add iptables && sleep 1d

spec.template.spec.securityContext.privilegedとありますが、正しい位置は
spec.template.spec.securityContext.container.privileged です。
マニフェストファイルを正しく書き換えると以下のようになります。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: habanero
spec:
  selector:
    matchLabels:
      app: habanero
  serviceName: habanero
  replicas: 1
  template:
    metadata:
      labels:
        app: habanero
    spec:
      containers:
        - securityContext:
            privileged: true
          name: habanero
          image: nginx:alpine
          command:
            - sh
            - -c
            - apk add iptables && sleep 1d
          

これを apply すれば完了です。

タイトルとURLをコピーしました