手把手搭建 k8s docker 漏洞环境
2022-4-1 09:24:0 Author: mp.weixin.qq.com(查看原文) 阅读量:10 收藏

文章作者:sunian    
文章来源:FreeBuf.COM
原文地址:
https://www.freebuf.com/vuls/321244.html

此环境为复现 docker 以及 k8s 容器逃逸的集成漏洞环境。
涉及以下漏洞:
1、docker privileged 特权模式
2、参数SYS_ADMIN导致cgroup逃逸
3、proc挂载
4、docker remote api 未授权
5、挂载sock文件
6、脏牛内核逃逸(此条划掉,没符合漏洞版本的linux,而且在实战中这个漏洞也很少遇到,大家直接靶场lampiao复现一下这个洞就可以)
7、1day runc
8、k8s鉴权配置不当
9、k8s日志挂载
10、k8s账户权限配置不当

使用huawei欧拉服务器V2.0 SP5
https://euleros2019.obs.cn-north-1.myhuaweicloud.com/ict/site-euleros/euleros/repo/yum/2.5/os/x86_64/iso/EulerOS-V2.0SP5-x86_64-dvd.iso
准备两台服务器(虚拟机)
master主服务器 192.168.88.180 k8s-master
node节点服务器 192.168.88.181 k8s-node
集群服务器至少2h2g30G
注意事项:
1、查看hostname如果是localhost,请使用以下命令进行修改
hostnamectl set-hostname test101
2、两台服务器的/etc/hosts文件中需添加如下配置
master主机IP 主机名
node节点IP 主机名
3、保持两台机器时间同步
利用date命令查看,不一致使用命令进行同步
ntpdate ntp1.aliyun.com

若更新源没问题,则进行第三步:安装,若有问题则看第四步:遇到的问题及解决方案。

1、安装依赖

yum install go
yum install git
yum -y install gcc automake autoconf libtool make

把container-selinux-2.107-3.el7.noarch.rpm、runc.sh、privileged.sh放到两台机器上
http://ftp.riken.jp/Linux/cern/centos/7/extras/x86_64/Packages/container-selinux-2.107-3.el7.noarch.rpm

#runc.sh
#!/bin/bash
#sunian
echo "查找原有libseccomp进行删除"
results=`yum list installed|grep libseccomp`
if test ! -z "$results";then
yum -y remove $results
echo "删除完毕"
else
echo "已删除,进行下一步"
fi
`mkdir -p /home/runc`
`cd /home/runc`
`wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libseccomp-2.3.1-4.el7.x86_64.rpm`
rpm -ivh libseccomp-2.3.1-4.el7.x86_64.rpm
`wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libseccomp-devel-2.3.1-4.el7.x86_64.rpm`
rpm -ivh libseccomp-devel-2.3.1-4.el7.x86_64.rpm
`mkdir -p $HOME/go/src/github.com`
`go get github.com/opencontainers/runc`
cd $HOME/go/src/github.com/opencontainers/runc
git checkout v1.0.0-rc5
echo -e "\033[31m `git status` \033[0m"
make
make install
echo -e "\033[31m `runc -v` \033[0m"

注释:查找原有libseccomp进行删除,从官网下载所需libseccomp和libseccomp-devel进行rpm安装,利用go从github下载带有漏洞版本的runc v1.0.0-rc5并编译。

#privileged.sh
#!/bin/bash
#sunian
echo "查找原有docker进行删除"
results=`yum list installed|grep docker`
if test ! -z "$results";then
yum -y remove $results
echo "删除完毕"
else
echo "已删除,进行下一步"
fi
#开始安装存在漏洞版本docker
echo "创建并安装docker的依赖"
echo "安装在/home/privileged目录下"
mkdir -p /home/privileged
mv /root/container-selinux-2.107-3.el7.noarch.rpm /home/privileged
cd /home/privileged
rpm --force --nodeps -ivh container-selinux-2.107-3.el7.noarch.rpm
`wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-18.06.0.ce-3.el7.x86_64.rpm`
rpm -ivh docker-ce-18.06.0.ce-3.el7.x86_64.rpm
`service docker start`
echo `docker version`
echo -e "\033[31m `docker images` \033[0m"

注释:删除原有的docker,安装docker的依赖 即container-selinux,安装存在漏洞版本的docker,执行docker images并输出,查看是否安装成功。

2、配置k8s及安装

(1)系统设置:

安装nfs以及wget
yum install -y nfs-utils
yum install -y wget
关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
关闭selinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
关闭swap分区
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
将桥接的IPv4 IPv6流量传递到iptables的链(直接shell脚本):

# 如果有配置,则修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g" /etc/sysctl.conf
# 可能没有,追加
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
# 执行命令以应用
sysctl -p

(2)配置k8s源

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

(3)安装k8s

yum remove -y kubelet kubeadm kubectl
yum install -y kubelet-1.18.2 kubeadm-1.18.2 kubectl-1.18.2

sudo systemctl daemon-reload
sudo systemctl enable docker
sudo systemctl restart docker
systemctl enable kubelet && systemctl start kubelet
(到此两台机器都有runc、docker、k8s工具(kubeadm kubectl kubelet))

(4)接下来开始初始化服务器master节点(node服务器无需操作)

# 只在 master 节点执行
# export 命令只在当前 shell 会话中有效,开启新的 shell 窗口后,如果要继续安装过程,请重新执行此处的 export 命令
export MASTER_IP=192.168.88.180
# 替换 apiserver.demo 为 您想要的 dnsName
export APISERVER_NAME=apiserver.demo
# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 创建,事先并不存在于您的物理网络中
export POD_SUBNET=172.18.0.1/16
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts

创建init_master.sh

#!/bin/bash
# 脚本出错时终止执行
set -e

if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then
echo -e "\033[31;1m请确保您已经设置了环境变量 POD_SUBNET 和 APISERVER_NAME \033[0m"
echo 当前POD_SUBNET=$POD_SUBNET
echo 当前APISERVER_NAME=$APISERVER_NAME
exit 1
fi

# 查看完整配置选项 https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
rm -f ./kubeadm-config.yaml
cat <<EOF > ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.2
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
serviceSubnet: "10.96.0.0/16"
podSubnet: "${POD_SUBNET}"
dnsDomain: "cluster.local"
EOF

# kubeadm init
# 根据您服务器网速的情况,您需要等候 3 - 10 分钟
kubeadm init --config=kubeadm-config.yaml --upload-certs

# 配置 kubectl
rm -rf /root/.kube/
mkdir /root/.kube/
cp -i /etc/kubernetes/admin.conf /root/.kube/config

# 安装 calico 网络插件
# 参考文档 https://docs.projectcalico.org/v3.13/getting-started/kubernetes/self-managed-onprem/onpremises
echo "安装calico-3.13.1"
rm -f calico-3.13.1.yaml
wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml
kubectl apply -f calico-3.13.1.yaml

加权限执行进行初始化,预检有点慢,等一等
之后执行如下命令,直到所有的容器组处于 Running 状态
watch kubectl get pod -n kube-system -o wide

节点初始化状态为ready
kubectl get nodes -o wide

至此主机服务器安装完成

(5)配置node节点

在master服务器上获取join命令
kubeadm token create --print-join-command

node节点服务器执行该命令

# 只在 node 节点执行
# 192.168.88.180 为 master 节点的内网 IP
export MASTER_IP=192.168.88.180
# 替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME
export APISERVER_NAME=apiserver.demo
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
执行master服务器获取的join命令

最后master服务器执行命令
kubectl get nodes -o wide

查看node节点服务器直到ready,至此安装完成

1、若无更新源或源有问题(如 无想要的包),可使用以下更新源

Makefile
在/etc/yum.repos.d/目录下,创建文件EulerOS.repo

[base]
name=EulerOS-2.0SP5 base
baseurl=http://repo.huaweicloud.com/euler/2.5/os/x86_64/
enabled=1
gpgcheck=1
gpgkey=http://repo.huaweicloud.com/euler/2.5/os/RPM-GPG-KEY-EulerOS

执行yum clean all清除原有yum缓存。
执行yum makecache生成新的缓存。
yum update更新

2、go版本的问题,1.16以下的go版本不支持io/fs,但是该报错不影响后续运行

3、若使用centos,期间可能出现的问题:

网络问题,主要是go下载runc时请求github网络问题,解决方案:临时环境变量,使用aliyun go源
export GOPROXY=https://mirrors.aliyun.com/goproxy/

4、如果docker未启动

service docker start

5、10250端口占用

[ERROR Port-10250]: Port 10250 is in use
解决方法:
kubeadm reset

6、修改docker为cgroups或systemd驱动

cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF

systemctl daemon-reload && systemctl restart docker

7、rpm安装docker缺少依赖

报错如下
libcgroup is needed by docker-ce-18.06.0.ce-3.el7.x86_64
libltdl.so.7()(64bit) is needed by docker-ce-18.06.0.ce-3.el7.x86_64

解决方案:
http://mirror.centos.org/centos/7/os/x86_64/Packages/ 安装以下依赖
libcgroup-0.41-21.el7.x86_64.rpm
libtool-ltdl-2.4.2-22.el7_3.x86_64.rpm

8、nodeRegistration.name: Invalid value

hostname或dnsname不能用下划线,只能用'-'或'.'。

侵权请私聊公众号删文



文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMjE3ODU3MQ==&mid=2650535987&idx=2&sn=31ac8214c1660ce4f92b2582d7905e1f&chksm=83ba9dd7b4cd14c188a7789eedefdb5ac1ffb71d5ecd7f517a4a6811a3d1bcce800c1bc6d82c#rd
如有侵权请联系:admin#unsafe.sh