LabHub
学习 学习路径 课程

KCSA — Kubernetes 安全助理

用攻击者的眼睛打开集群

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

이 실습은 진짜 클러스터에서 돕니다

KCSA 는 위협 모델과 공격 표면입니다. 그것을 배우려면 실제로 훔쳐 봐야 합니다 — 저장소에서 평문을 꺼내고, 권한이 없는데도 시크릿을 읽어 내고, 감사 로그에 그 흔적이 남는 것을 봅니다.

가짜 클러스터에는 저장소도 apiserver 인증 체인도 감사 로그도 없어서, 이 전부가 글로만 남아 있었습니다. base64 는 암호화가 아니다 를 말로 듣는 것과 저장소에서 평문을 꺼내 보는 것은 다릅니다.

CKS 와 겹치지 않게 합니다. CKS 는 막는 실습이고, 여기 KCSA 는 왜 막아야 하는지를 공격으로 보여 줍니다.

처음 뜨는 데 2분쯤 걸립니다.

단계

  1. 시크릿을 만들고 저장소에서 평문으로 꺼내 /root/kcsa/plaintext.txt 에 담으세요.
  2. 저장 데이터 암호화를 켜고, 평문이 사라지는 것을 /root/kcsa/encrypt.txt 에 담으세요.
  3. 옛 시크릿은 다시 써야 암호화되는 것을 /root/kcsa/rewrite.txt 에 담으세요.
  4. app에 PSA enforce=restricted, enforce-version=v1.36을 적용하세요. runner SA에는 app의 pods get·list·create만 부여하고 secrets get은 허용하지 마세요. /root/kcsa/leak.yaml에 namespace app의 leak Pod를 작성하세요. restartPolicy=Never, runner SA, 자동 토큰 마운트 끄기, runAsNonRoot와 UID 65532, RuntimeDefault seccomp, allowPrivilegeEscalation=false, capabilities drop ALL을 사용합니다. 컨테이너 하나는 busybox:1.36으로 command: [sha256sum, /s/password]를 실행하며 db Secret 볼륨 s를 /s에 읽기 전용으로 마운트합니다. 관리자 생성으로 대신하지 말고 --as=system:serviceaccount:app:runner로 생성하세요. Succeeded를 확인한 뒤 /root/kcsa/escalate.txtdirect_secret=no, create_pod=yes, psa=restricted, secret_mount=readable과 실제 로그의 해시 한 줄, PSA가 막는 실행 설정과 막지 않는 데이터 접근 경계를 설명하세요. 합성 비밀 원문은 출력하지 않습니다.
  5. 익명·기본 SA 로 apiserver 를 두드려 인증 경계/root/kcsa/anon.txt 에 담으세요.
  6. **/etc/kubernetes/audit.yaml**에 감사 정책을 쓰세요. 첫 규칙에서 core secrets·configmaps·serviceaccounts/token을 사용자·동사·네임스페이스 제한 없이 Metadata로 보호하세요. 다음은 /healthz, /readyz, /livez와 각 /* 하위 경로만 None, 마지막은 조건 없는 Metadata입니다. omitStagesRequestReceived만 생략할 수 있습니다. 총 3규칙 또는 기본값 앞 RBAC 쓰기 상세 규칙을 더한 4규칙을 사용합니다. 선택적 상세 규칙은 rbac.authorization.k8s.io의 roles·rolebindings·clusterroles·clusterrolebindings에 create·update·patch·delete·deletecollection만 RequestResponse로 기록합니다. /etc/rancher/k3s/config.yaml.d/90-labhub-audit.yaml에서 kube-apiserver-arg+로 감사 인자를 추가해 기존 암호화 설정을 보존하고 k3s를 재시작하세요. 로그는 /var/log/kubernetes/audit.log, blocking 모드, maxsize=5·maxbackup=1·maxage=1로 제한합니다. 준비 완료 후 제공 도우미 python3 /opt/fixtures/audit-evidence.py capture --policy /etc/kubernetes/audit.yaml --log /var/log/kubernetes/audit.log --case /root/kcsa/audit-case.json --events /root/kcsa/audit-evidence.jsonl로 합성 Secret의 생성201·조회200·거절403·삭제200을 수집하세요. 본문 없는 Metadata 이벤트 네 개와 정책 지문을 보존하고 /root/kcsa/audit.txt에 결과를 설명하세요. 도우미는 정책을 고치지 않으며 실제 비밀을 넣지 않습니다.
  7. 지금까지를 4C 와 STRIDE 로 정리해 /root/kcsa/model.txt 에 담으세요.
  8. /root/kcsa/report.mdplaintext_found=yes, encrypted=yes, audit_lines= 세 줄과 설명을 쓰세요.

참고

70분 실습이므로 만료 전에 +시간으로 연장하세요(최대 180분). 세션 종료 시 작업물이 사라집니다.

base64 는 암호화가 아니다

시크릿을 만들고 저장소에서 평문으로 꺼내 /root/kcsa/plaintext.txt 에 담으세요.

sqlite3 로 저장소를 열고 hex(value) 에서 평문을 찾으세요.

저장 데이터 암호화를 켠다

저장 데이터 암호화를 켜고, 평문이 사라지는 것을 /root/kcsa/encrypt.txt 에 담으세요.

EncryptionConfiguration 을 쓰고 apiserver 에 --encryption-provider-config 로 넘깁니다.

옛 시크릿은 다시 써야 바뀐다

옛 시크릿은 다시 써야 암호화되는 것을 /root/kcsa/rewrite.txt 에 담으세요.

kubectl get secret -o json | kubectl replace -f - 로 다시 씁니다.

Restricted 파드도 Secret 볼륨을 읽는다

app에 PSA enforce=restricted, enforce-version=v1.36을 적용하세요. runner SA에는 app의 pods get·list·create만 부여하고 secrets get은 허용하지 마세요. /root/kcsa/leak.yaml에 namespace app의 leak Pod를 작성하세요. restartPolicy=Never, runner SA, 자동 토큰 마운트 끄기, runAsNonRoot와 UID 65532, RuntimeDefault seccomp, allowPrivilegeEscalation=false, capabilities drop ALL을 사용합니다. 컨테이너 하나는 busybox:1.36으로 command: [sha256sum, /s/password]를 실행하며 db Secret 볼륨 s를 /s에 읽기 전용으로 마운트합니다. 관리자 생성으로 대신하지 말고 --as=system:serviceaccount:app:runner로 생성하세요. Succeeded를 확인한 뒤 /root/kcsa/escalate.txtdirect_secret=no, create_pod=yes, psa=restricted, secret_mount=readable과 실제 로그의 해시 한 줄, PSA가 막는 실행 설정과 막지 않는 데이터 접근 경계를 설명하세요. 합성 비밀 원문은 출력하지 않습니다.

요청 주체와 파드의 SA는 다릅니다. runner로 생성하고, PSA 실행 조건과 Secret 참조를 구분하세요.

인증 경계를 두드린다

익명·기본 SA 로 apiserver 를 두드려 인증 경계/root/kcsa/anon.txt 에 담으세요.

익명 요청과 기본 SA 토큰으로 apiserver 를 직접 호출해 보세요.

남기지 않으면 없었던 일이 된다

**/etc/kubernetes/audit.yaml**에 감사 정책을 쓰세요. 첫 규칙에서 core secrets·configmaps·serviceaccounts/token을 사용자·동사·네임스페이스 제한 없이 Metadata로 보호하세요. 다음은 /healthz, /readyz, /livez와 각 /* 하위 경로만 None, 마지막은 조건 없는 Metadata입니다. omitStagesRequestReceived만 생략할 수 있습니다. 총 3규칙 또는 기본값 앞 RBAC 쓰기 상세 규칙을 더한 4규칙을 사용합니다. 선택적 상세 규칙은 rbac.authorization.k8s.io의 roles·rolebindings·clusterroles·clusterrolebindings에 create·update·patch·delete·deletecollection만 RequestResponse로 기록합니다. /etc/rancher/k3s/config.yaml.d/90-labhub-audit.yaml에서 kube-apiserver-arg+로 감사 인자를 추가해 기존 암호화 설정을 보존하고 k3s를 재시작하세요. 로그는 /var/log/kubernetes/audit.log, blocking 모드, maxsize=5·maxbackup=1·maxage=1로 제한합니다. 준비 완료 후 제공 도우미 python3 /opt/fixtures/audit-evidence.py capture --policy /etc/kubernetes/audit.yaml --log /var/log/kubernetes/audit.log --case /root/kcsa/audit-case.json --events /root/kcsa/audit-evidence.jsonl로 합성 Secret의 생성201·조회200·거절403·삭제200을 수집하세요. 본문 없는 Metadata 이벤트 네 개와 정책 지문을 보존하고 /root/kcsa/audit.txt에 결과를 설명하세요. 도우미는 정책을 고치지 않으며 실제 비밀을 넣지 않습니다.

보호 규칙이 먼저 일치해야 합니다. omitStages는 본문 제거가 아닙니다. 정책 작성과 실제 완료 이벤트 수집을 구분하세요.

4C 와 STRIDE 로 정리한다

지금까지를 4C 와 STRIDE 로 정리해 /root/kcsa/model.txt 에 담으세요.

지금까지 본 공격을 4C 계층과 STRIDE 범주에 각각 대응시키세요.

무엇을 배웠나

/root/kcsa/report.mdplaintext_found=yes, encrypted=yes, audit_lines= 세 줄과 설명을 쓰세요.

plaintext_found=yes, encrypted=yes, audit_lines= 세 줄과 설명을 쓰세요.