chroot

c0wb3ll ㅣ 2020. 11. 6. 14:45

chroot

chroot 란?

chroot란 Change Root Directiory의 줄임말로 현재 실행중인 프로세스와 자녀 프로세스의 루트 디렉토리를 변경하는 작업이다.

 

chroot를 이용해 변경된 루트 디렉토리에서는 그 상위에 디렉토리 (ex. 본래 루트 디렉토리)에 파일 및 명령에 접근할 수 없게한다.

 

이렇게 변경된 환경을 chroot jail이라고 부른다.

chroot 동작 원리

시스템에는 최상위 디렉토리를 가리키는 /(root) 디렉토리가 존재한다.

최상위 디렉토리라는 호칭 그대로 모든 디렉터리 및 파일은 이 하위에 존재하게 된다.

시스템에서는 어떤 파일에 접근할 때는 루트(/) 디렉토리를 기준으로 다른 파일에 접근할 수 있다.

예를 들어 일반 사용자에게 가장 친숙한 바탕화면을 경로로 표시하더라도 Desktop이 아닌 /home/username/Desktop 이 경로가 된다.

 

chroot는 이 root 디렉토리를 다른 위치로 지정하여 최상위 디렉토리를 바꾸어주는 명령어이다.

 

이렇게 루트 디렉토리를 변경시켜주면 바뀌는 점이 무엇이 있을까?

 

앞서 말하였듯이 시스템에서는 어떤 파일에 접근할 때 루트 디렉토리를 기준으로 접근한다.

즉 내가 루트 디렉토리를 /home/username/Desktop으로 변경한다면 Desktop 상위 디렉토리에 있는 경로를 표현할 방법이 없으므로 접근할 수 없게 된다.

 

이렇게 된다면 Desktop상위 디렉토리와 격리되어 접근할 수 없게 되고 이러한 환경을 jail(감옥)이라고 부르는 이유이기도 하다.

chroot 사용해 보기

# pwd
/home/ctf/chal

나는 ctf 환경을 구축해보기 위해 chroot를 공부했으므로 해당 폴더를 루트 디렉토리로 변경하려 한다.

# chroot /home/ctf/chal /bin/bash
chroot: failed to run command '/bin/bash': No such file or directory

해당 명령어는 /home/ctf/chal 경로를 루트 디렉토리로 쉘(/bin/bash)을 실행시키라는 의미이다.

그런데 보면 이상한 에러를 뽑아낸다. /bin/bash라는 파일 혹은 디렉토리를 찾을 수 없다고 한다. 이유가 무엇일까?

# pwd
/home/ctf/chal
# ls
enrolment  flag

그 이유는 chroot 명령어의 두번째 인자로 사용되는 명령어들은 기존 루트가 아닌 새롭게 루트 디렉토리가 될 루트를 기준으로 하기 때문이다.

즉 /home/ctf/chal 이라는 루트 디렉토리 밑에는 /bin/bash 라는 파일 및 디렉토리가 존재하지 않기 때문에 작동하지 않는 것이다.

그럼 제대로 chroot 명령어를 사용하기 위해서는 /bin/bash 파일을 /home/ctf/chal/bin/bash 경로에 위치시켜줘야 할 것 같다.

# mkdir ./bin
# cp /bin/bash ./bin/bash
# ls
bin  enrolment    flag
# cd bin
# ls
bash

그럼 이제 다시 chroot를 실행시켜보자.

# chroot /home/ctf/chal /bin/bash
chroot: failed to run command '/bin/bash': No such file or directory

하지만 같은 에러를 뿜어내준다. 이러한 에러를 뿜는 이유는 프로그램 파일들이 동적 라이브러리를 사용하기 때문이다.

따라서 ldd 명령어를 이용하여 사용하는 라이브러리 파일 또한 변경될 루트 디렉토리 밑에 넣어주어야 한다.

# ldd /bin/bash
    linux-vdso.so.1 (0x00007ffdc09dc000)
    libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fd2366ac000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd2366a6000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd2364b4000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fd23680c000)
# mkdir ./lib
# mkdir ./lib/x86_64-linux-gnu
# mkdir ./lib64
# cp /lib/x86_64-linux-gnu/libtinfo.so.6 ./lib/x86_64-linux-gnu/             
# cp /lib/x86_64-linux-gnu/libdl.so.2 ./lib/x86_64-linux-gnu/
# cp /lib/x86_64-linux-gnu/libc.so.6 ./lib/x86_64-linux-gnu/
# cp /lib64/ld-linux-x86-64.so.2 ./lib64/

다음과 같이 라이브러리를 전부 이동시켜주었다.

그럼 이제 루트 디렉토리를 변경시켜주자.

# ls
bin  enrolment    flag  lib  lib64
# chroot /home/ctf/chal /bin/bash
bash-5.0# ls
bash: ls: command not found

bash-5.0# 으로 쉘이 변경되었다.

그런데 당연했지만 웃긴 점이 ls 명령어를 이용하려고 하자 ls 명령어가 존재하지 않는다는 것이었다.

ls 또한 라이브러리와 명령어를 변경된 루트 디렉토리 밑에 넣어야만 작동한다.

더 실습하고 싶은 사람들은 위 /bin/bash를 옮길때와 같이 실습해보길 바란다.


이번에 CTF를 준비하면서 포너블 도커 환경을 구축하게 되었는데 쉘을 따면 홈 디렉토리(유저 디렉토리)로 떨어지는 것이 아닌 루트 디렉토리로 떨어지는 점에서 스트레스를 받았다.

 

그래서 루트 디렉토리를 변경시키는 방법을 찾아보다 chroot에 대해 알게되었고 위 실습까지는 성공했으나 도커 환경에 적용시키는 것은 실패하게 되었다...

 

chroot 와 동시에 알게 된 것이 바로 nsjail인데 chroot를 이용해 포너블용 도커 환경을 구축해주는 jail이다.(DownunderCTF Writeup 페이지에 가면 Dockerfile 과 nsjail-pwn.sh파일이 존재해서 알게 됨)

 

이것 또한 결국 적용에는 실패하여 실제 CTF에는 플래그 경로를 표시해주었고 공부하면서 스트레스도 많이 받았지만 오랜만에 하는 삽질이라서 일단 해본 부분까지만 정리를 해본다. (적용에는 실패해 적용시키는 방법을 다루지는 못하지만 다른 분들은 nsjail과 chroot라는게 있다는 것만큼은 알고 시작하길 바라며...)


Reference

https://www.44bits.io/ko/post/change-root-directory-by-using-chroot

https://github.com/google/nsjail

https://github.com/DownUnderCTF/Challenges_2020_public