LabHub

KCSA — 쿠버네티스 보안 어소시에이트 · 쿠버네티스 위협 모델 · 이론

STRIDE 를 쿠버네티스에 대입하기

LabHub 에서 이어서 보기

한 줄 요약

위협 모델링은 "무엇이 무서운가"를 감으로 나열하는 대신 분류 체계로 빠짐없이 훑는 방법입니다.
STRIDE 여섯 항목을 쿠버네티스 오브젝트에 대입하면 점검 항목이 저절로 나옵니다.

왜 이게 필요했나

보안 검토가 사람마다 다른 결론을 내는 이유는 각자 자기가 아는 위협만 보기 때문입니다.
네트워크 담당자는 방화벽을, 개발자는 인젝션을 봅니다. STRIDE 는 "이 여섯 가지를 다 물어봤는가"
라는 체크리스트를 줍니다. 빠뜨림을 구조적으로 줄이는 것이 목적입니다.

어떻게 동작하나

여섯 항목의 쿠버네티스 번역

| STRIDE | 뜻 | 쿠버네티스에서의 모습 | 주 대응 |
| --- | --- | --- | --- |
| Spoofing | 신원 위장 | SA 토큰 탈취, 인증서 위조, --as 사칭 | 강한 인증, 토큰 수명 단축, impersonate 권한 통제 |
| Tampering | 변조 | 이미지 교체, etcd 직접 쓰기, 매니페스트 조작 | 이미지 서명, etcd 접근 통제, GitOps |
| Repudiation | 부인 | 누가 했는지 증명 못 함 | 감사 로그, 개별 신원(공유 계정 금지) |
| Information Disclosure | 정보 노출 | Secret 유출, kubelet 읽기 포트, 로그의 자격증명 | 저장 시 암호화, RBAC, 로그 위생 |
| Denial of Service | 서비스 거부 | 리소스 고갈, apiserver 폭주, 웹훅 장애 | ResourceQuota, LimitRange, PDB, API 우선순위 |
| Elevation of Privilege | 권한 상승 | privileged 파드, hostPath, RBAC 오설정 | PSA, 최소 권한, 어드미션 정책 |

권한 상승 경로 — KCSA 의 핵심

권한 상승은 "관리자 권한을 직접 받는 것"이 아니라 "관리자가 아닌 권한에서 관리자로 가는 경로"
입니다. 대표 경로 넷을 외워 두세요.

1) pods/exec 또는 pods/attach
파드에 들어갈 수 있으면 그 파드의 ServiceAccount 토큰을 읽을 수 있습니다.
그 SA 가 나보다 권한이 높으면 그 권한을 그대로 얻습니다. 디버깅 편의로 준 권한이
"클러스터 안의 모든 SA 중 가장 센 것"으로 가는 사다리가 됩니다.

2) secrets 읽기
Secret 에는 다른 SA 의 토큰, DB 자격증명, 외부 API 키가 들어 있습니다.
네임스페이스에 get secrets 가 있으면 그 네임스페이스의 모든 Secret 을 읽습니다.

3) rolebindings/clusterrolebindings 에 대한 create
스스로에게 더 높은 권한을 부여할 수 있습니다. 쿠버네티스는 이걸 알고 있어서 기본적으로
자기가 갖지 않은 권한은 부여할 수 없게 막습니다(권한 상승 방지). 그 방어를 뚫는 게 다음 항목입니다.

4) escalate, bind, impersonate 동사

그리고 파드 스펙 자체가 상승 경로입니다.

"파드를 만들 수 있다"는 것은 잠재적으로 "그 노드를 소유할 수 있다"에 가깝습니다.
그래서 PSA 나 정책 엔진으로 파드 스펙을 제한하는 것이 RBAC 만큼 중요합니다.

공급망 위협

내가 클러스터를 아무리 잘 잠가도, 내가 자발적으로 받아 실행하는 것에는 소용이 없습니다.

대응은 출처와 무결성입니다 — 신뢰하는 레지스트리만 허용, 다이제스트 고정, 이미지 서명 검증,
SBOM 으로 무엇이 들어 있는지 목록화.

지속성(persistence) 확보 기법

침입에 성공한 공격자는 다시 들어올 길을 만들어 둡니다. 정리해 두면 탐지 항목이 됩니다.

현장에서 만나는 모습

저자의 블로그가 정리한 RBAC 사고 패턴 중 가장 흔한 것 — "모든 ServiceAccount 가 클러스터
리소스를 읽을 수 있는 비정상적인 상태"가 발견되는 경우입니다. 진단은
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin")'
로 cluster-admin 바인딩 주체를 전수 조사하는 것이고, 이건 정확히 지속성 기법 탐지와 같은 쿼리입니다.

공급망 쪽에서는 더 실감 나는 사례가 있습니다. docker build --build-arg NPM_TOKEN=... 로 넣은
토큰이 docker history --no-trunc 에 그대로 나오는 것입니다.
RUN 단계에서 파일을 지워도 이전 레이어에 남습니다. 올바른 방법은
RUN --mount=type=secret,id=npmrc,... 처럼 빌드 시크릿 마운트를 쓰는 것입니다.

그리고 시크릿 유출 대응에서 순서에 대한 저자의 지적이 위협 모델링과 맞닿습니다.
가장 흔한 반응은 Git 히스토리 재작성인데 순서가 틀렸습니다.
공개 저장소에 푸시된 자격증명은 수 초에서 수 분 안에 자동화된 스캐너에 수집되고,
히스토리를 지워도 포크·기존 클론·플랫폼이 보관하는 PR 참조·검색 캐시·CI 아티팩트에 남습니다.
폐기(revocation)가 먼저이고, 히스토리 정리는 재발을 줄이는 위생 작업입니다.
위협 모델링이 대응 순서까지 바꾸는 예입니다.

다음 퀴즈에서 확인할 것

이 모듈은 퀴즈로 마무리합니다. 다음 모듈에서 파드 스펙 기반 권한 상승을 실제로 막는 장치인
PSA 를 다루고, 실습에서 restricted 위반 파드가 거부되는 것을 직접 확인합니다.