--- tags: Kubernetes,SecurityContext description: Kubernetes Security Context Issue robots: index, follow --- # misconfig - II: Security Context 相信很多人由容器環境轉到Kubernetes時,最常做的一件事就是上傳好image後,就很直覺的把服務開到叢集中,非常直覺、快速、幫自己挖了坑。 例如: ```yaml= apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: mycontainer name: mycontainer spec: containers: - args: - client image: nginx name: mycontainer resources: {} dnsPolicy: ClusterFirst restartPolicy: Always ``` 前一篇文章我們有提到一些需要補充的東西,就讓我們來看看會發生什麼事。 ## 1.1. 環境資訊 **K8S: v1.20.12** **NAME STATUS ROLES** g1-master1 Ready controlplane,etcd g1-master2 Ready controlplane,etcd g1-master3 Ready controlplane,etcd g1-worker1 Ready worker g1-worker2 Ready worker g1-worker3 Ready worker ## 1.2. Lab操作 1. 建立一個pod,快速的把他對外服務、確認狀態。 ```shell= └[~]> kubectl run mycontainer pod/mycontainer created └[~]> kubectl expose pod mycontainer --type=NodePort --target-port 80 --port 80 service/mycontainer exposed └[~]> kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 74d mycontainer NodePort 10.43.194.42 <none> 80:31065/TCP 1m └[~]> curl 172.24.2.16:31065 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... ... (略) ``` 2. 然後我們就可以幫他安裝套件了,前後不用5分鐘完成。(擦汗 ```shell= └[~]> kubectl exec -it mycontainer -- /bin/bash root@mycontainer:/# apt update Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB] Get:2 http://security.debian.org/debian-security bullseye-security InRelease [44.1 kB] Get:3 http://deb.debian.org/debian bullseye-updates InRelease [39.4 kB] Get:4 http://deb.debian.org/debian bullseye/main amd64 Packages [8183 kB] ... root@mycontainer:/# apt install recon-ng Reading package lists... Done Building dependency tree... Done Reading state information... Done The following additional packages will be installed: javascript-common libgpm2 libjs-jquery libjs-skeleton libjs-sphinxdoc (略) ``` :::info 1. [recon-ng](https://www.kali.org/tools/recon-ng/ "recon-ng"): Recon-ng is a full-featured Web Reconnaissance framework. ::: ![](https://i.imgur.com/nGjw58W.png) 沒有模組可以用,就安裝或enable自己想要的囉。 3. 用一個沒有安裝任何服務的nginx來做範例似乎說不過去,我們用一個可以執行系統指令的網頁服務來看看。 [1. 小網頁程式-github、dockerfile](https://github.com/yansheng133/securitycontext "security context") [2. 已經build好的docker image](https://hub.docker.com/r/yansheng133/securitycontext "") :::danger 1. 上述兩個連結,僅用於本文展示透過網頁執行系統指令所產生的可能問題,不負責任何濫用後產生的任何損失。 ::: **source code** ```go= package main import ( "os/exec" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/ping/:exec", func(c *gin.Context) { exe := c.Params.ByName("exec") out, err := exec.Command(exe).Output() if err != nil { c.JSON(200, gin.H{ "message": err, }) } output := string(out[:]) c.JSON(200, gin.H{ "CLI return message": output, "Warning: ": "This is training sample, DO NOT USE IT FOR BAD!", }) }) r.Run() } ``` 4. 能夠執行指令的web服務:testweb.yaml。 ```yaml= apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: testweb name: testweb spec: replicas: 1 selector: matchLabels: app: testweb strategy: {} template: metadata: creationTimestamp: null labels: app: testweb spec: containers: - image: yansheng133/securitycontext:0.3 name: securitycontext resources: {} status: {} --- apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: testweb name: testweb spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: testweb type: NodePort status: loadBalancer: {} ``` 5. 建立相關的服務。 ```shell= └[~]> kubectl create -f testgo.yaml deployment.apps/testweb created service/testweb created └[~]> kubectl get svc,deploy,pod NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 73d service/mycontainer NodePort 10.43.194.42 <none> 80:31065/TCP 23h service/testweb NodePort 10.43.91.239 <none> 80:30344/TCP 12m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/testweb 1/1 1 1 12m NAME READY STATUS RESTARTS AGE pod/mycontainer 1/1 Running 0 23h pod/testweb-5f8f8bcb9f-pq5sk 1/1 Running 0 12m ``` 6. 傳指令進去,確認回應是什麼,也可用瀏覽器打開,透過網址輸入一樣的內容就可以了。 ```shell= └[~]> curl 172.24.2.15:30344/ping/ls {"CLI return message":"go.mod\ngo.sum\nmain.go\n","Warning: ":"This is training sample, DO NOT USE IT FOR BAD!"}% └[~]> curl 172.24.2.15:30344/ping/whoami {"CLI return message":"root\n","Warning: ":"This is training sample, DO NOT USE IT FOR BAD!"}% └[~]> curl 172.24.2.15:30344/ping/'%20check%20ascii.' {"message":{"Name":" check ascii.","Err":{}}}{"CLI return message":"","Warning: ":"This is training sample, DO NOT USE IT FOR BAD!"}% └[~]> curl 172.24.2.15:30344/ping/id {"CLI return message":"uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)\n","Warning: ":"This is training sample, DO NOT USE IT FOR BAD!"}% ``` 7. 從回應我們可以觀察到以下狀況: :::info 1. 可以列出當前的資料夾。 2. 自己的權限是root。 3. 有些ascii碼會做轉換。 ::: 撇除ASCII碼會做轉換這個網頁程式面的問題,發現可以進行一些基本指令的呼叫,這個問題一樣會發生在登入容器或透過特定的指令、程式反向連結到想要的IP位置。 不過我們可以在服務建立的時候,就把系統權限全部拔掉。 例如拔掉所有的系統權限(capabilities)、拿掉切換到root的權限(allowPrivilegeEscalation)、把權限切換到指定的使用者(runAsUser)等。 ```yaml= apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: dropall name: dropall spec: containers: - args: - /bin/sleep - "3600" image: busybox name: dropall resources: {} securityContext: runAsUser: 2000 capabilities: drop: - all allowPrivilegeEscalation: false dnsPolicy: ClusterFirst restartPolicy: Always status: {} ``` 8. 確認一下id, whoami, ping與系統能夠執行哪些東西。 ```shell= └[~]> kubectl exec -it dropall -- /bin/sh / $ id uid=2000 gid=0(root) / $ whoami whoami: unknown uid 2000 / $ ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8): 56 data bytes ping: permission denied (are you root?) / $ cat /proc/1/status |grep Cap CapInh: 0000000000000000 CapPrm: 0000000000000000 CapEff: 0000000000000000 CapBnd: 0000000000000000 CapAmb: 0000000000000000 ##想確認可以操作哪些東西可以透過capsh --decode=值來做檢查,整排0就是無任何權限。 ``` 經過調整之後,就可以把非必要的權限等都移除,能夠有效的縮小被攻擊面,另外搭配一些network policy能夠更加明確的指定容器與容器間相互存取的方式,建議讀者可以參考先前的calico network policy,強化網路活動可視性,避免惡意人士對整體環境的偵查作業。 ## 1.3. 參考資料 [1. official - security contex](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ "") [2. Open Policy Agent](https://www.openpolicyagent.org/ "OPA") [3. kubesec](https://kubesec.io/ "kubesec")