พลาดเบอร์ไหนถึงจะโดน hack ผ่าน kubelet

rdamrong

Damrongsak Reetanon

Posted on February 5, 2021

พลาดเบอร์ไหนถึงจะโดน hack ผ่าน kubelet

มีข่าวหนึ่งเมื่อวันที่ 3 กุมภาพันธ์ 2564 เกี่ยวกับ Kubernetes จาก Unit42 ของ PaloAlto Network เนื้อหาก็ประมาณว่า มี malware ชื่อว่า Hildegard มุ่งโจมตี Kubernetes โดยเฉพาะ พออ่านลงไปในรายละเอียดของเนื้อหา จุดเริ่มต้นของการโจมตีในกรณีนี้ เกิดจากข้อผิดพลาดในการกำหนดค่า Configuration ของ kubelet เปิดให้เข้าถึงได้โดยไม่ต้องระบุตัวตน จากนั้นก็เรียกคำสั่งให้ทำงานใน container ผ่านทาง kubelet API และในเนื้อหายังบอกอีกว่า ถ้าติดตั้ง Kubernetes แบบมาตรฐานจะเปิดให้เข้าถึงได้โดยไม่ต้องระบุตัวตนเป็นค่าปกติ

Standard Kubernetes deployments come with anonymous access to kubelet by default.

"งานเข้าล่ะ" คำแรกที่อยู่ในหัวตอนที่อ่านข่าวนี้ เริ่มตั้งถามหลายข้อในหัว แล้วค่อย ๆ ไล่หาคำตอบจนคิดว่า น่าจะสบายใจแล้ว

  • จะรู้ได้ไงว่า kubelet เปิด anonymous access อยู่
  • จะเรียกใช้งานคำสั่งให้ทำงานใน container ผ่านทาง kubelet API ได้อย่างไร

จะรู้ได้ไงว่า kubelet เปิด anonymous access อยู่

ไปเจอใน github Liz Rice VP Open Source Engineering at @aquasecurity เขียนไว้

วิธีการการทดสอบ

curl -sk https://<node_ip>:10250/pods/
Enter fullscreen mode Exit fullscreen mode
  • ถ้าได้ status code เป็น 401 และมีข้อความตอนกลับมาว่า Unauthorized แสดงว่า ค่า --anonymous-auth ใน kubelet configuration เป็น false อยู่
  • ถ้าได้ status code เป็น 403 และมีข้อความตอนกลับมาว่า Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) แสดงว่า ค่า --anonymous-auth ใน kubelet configuration เป็น true และ --authorization-mode เป็น Webhook
  • ถ้าได้ข้อมูลของ Pod แสดงว่า ค่า --anonymous-auth ใน kubelet configuration เป็น true และ --authorization-mode เป็น AlwaysAllow

จะเรียกใช้งานคำสั่งให้ทำงานใน container ผ่านทาง kubelet API ได้อย่างไร

วิธีการการทดสอบ

curl -ks -X POST https://<node_ip>:10250/run/<namespace>/<pod>/<container> -d "cmd=<command>"
Enter fullscreen mode Exit fullscreen mode

ระบบที่ใช้ในการทดสอบ

  • Kubernetes version 1.15.2 และ 1.20.2 (ล่าสุด ณ.วันที่ 6 กุมภาพันธ์ 2564)
  • ติดตั้ง Kubernetes ด้วย kubeadm
  • node จำนวน 2 nodes มี ip เป็น 192.168.254.74, 192.168.254.75
root@cp0:~# kubectl get nodes -o wide
NAME      STATUS   ROLES    AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
cp0       Ready    master   14h   v1.15.2   192.168.254.71   <none>        Ubuntu 20.04.1 LTS   5.4.0-51-generic   containerd://1.3.3-0ubuntu2.2
node0-0   Ready    <none>   14h   v1.15.2   192.168.254.74   <none>        Ubuntu 20.04.1 LTS   5.4.0-51-generic   containerd://1.3.3-0ubuntu2.2
node0-1   Ready    <none>   14h   v1.15.2   192.168.254.75   <none>        Ubuntu 20.04.1 LTS   5.4.0-51-generic   containerd://1.3.3-0ubuntu2.2
Enter fullscreen mode Exit fullscreen mode

ทดสอบหลังจากติดตั้งทันที

#[at control plane]
root@cp0:~#  curl -sk https://192.168.254.74:10250/pods/
Unauthorized
Enter fullscreen mode Exit fullscreen mode

ผลการทดสอบพบว่า ไม่สามารถเข้าถึง kubelet โดยไม่ต้องระบุตัวตนได้

ตรวจสอบ kubelet configuration ในส่วนของ Authentication และ Authorization

#[at node0-0]
root@node0-0:~# cat /var/lib/kubelet/config.yaml |grep -A 12 authentication
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 5m0s
    cacheUnauthorizedTTL: 30s
Enter fullscreen mode Exit fullscreen mode

พบว่ามีการกำหนดค่าในส่วนของ Authentication และ Authorization ไว้

ทดสอบตั้งค่า Authentication เป็น false และ Authorization เป็น AlwaysAllow

#[at node0-0]
root@node0-0:~# cat /var/lib/kubelet/config.yaml |grep -A 4 authentication
authentication:
  anonymous:
    enabled: true
authorization:
  mode: AlwaysAllow

root@node0-0:~# systemctl restart kubelet

#[at control plane]
root@cp0:~# curl -sk https://192.168.254.74:10250/pods/ | jq |head -n 15
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {},
  "items": [
    {
      "metadata": {
        "name": "weave-net-27v7f",
        "generateName": "weave-net-",
        "namespace": "kube-system",
        "selfLink": "/api/v1/namespaces/kube-system/pods/weave-net-27v7f",
        "uid": "93ac4298-5eb7-497f-b914-9c4183230050",
        "resourceVersion": "72856",
        "creationTimestamp": "2021-02-05T07:35:15Z",
        "labels": {

Enter fullscreen mode Exit fullscreen mode

พบว่า สามารถแสดงรายการของ Pod ใน node นั้นได้

เรียกคำสั่ง hostname ที่ Container testcon ใน Pod testpd ผ่านทาง kubelet API

root@cp0:~#  curl -ks -X POST https://192.168.254.74:10250/run/default/testpod/testcon -d "cmd=hostname"
testpod
Enter fullscreen mode Exit fullscreen mode

ทดสอบลบ kubelet configuration ในส่วนของ Authentication และ Authorization ออกทั้งหมด

#[at node0-0]
root@node0-0:~# cat /var/lib/kubelet/config.yaml | grep authentication
root@node0-0:~# systemctl restart kubelet

#[at control plane]
root@cp0:~# curl -sk https://192.168.254.74:10250/pods/
Unauthorized
Enter fullscreen mode Exit fullscreen mode

พบว่า ไม่สามารถเข้าถึง kubelet โดยไม่ต้องระบุตัวตนได้

สรุป

  • ในการทดสอบ Kubernetes ทั้ง version 1.15.2 และ 1.20.2 ได้ผลการทดสอบเหมือนกัน
  • ค่าปกติหลังจากติดตั้ง Kubernetes ด้วย kubeadm ไม่สามารถเข้าถึง kubelet โดยไม่ต้องระบุตัวตนได้
  • ต้องกำหนดค่า authentication และ authorization ถึงจะเข้าถึง kubelet โดยไม่ต้องระบุตัวตนได้
authentication:
  anonymous:
    enabled: true
authorization:
  mode: AlwaysAllow
Enter fullscreen mode Exit fullscreen mode
  • Hacker อาจจะมีวิธีการไม่สามารถเข้าถึง kubelet โดยไม่ต้องระบุตัวตนได้ ในรูปแบบอื่น ๆ ได้อีก

test [at] your own risk

มูลค่าความสุข

💖 💪 🙅 🚩
rdamrong
Damrongsak Reetanon

Posted on February 5, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related