1-2. 컨테이너 격리(pivot_root)

Gyullbb·2022년 3월 18일
2

K8S

목록 보기
2/13

1) 개요

앞서 chroot로 생성한 격리공간에는 다음과 같은 단점이 있었다.

  1. 탈옥이 가능하다.
  2. 완전한 격리가 불가능하다. (Host의 filesystems, network 등에 접근 가능)
  3. root 권한 사용 가능하다.
  4. host의 자원을 무제한으로 사용할 수 있다.

이러한 단점의 일부를 극복할 수 있는 pivot_root를 통한 격리에 대해 알아보겠다.


2) pivot_root를 이용한 프로세스 격리

pivrot_root란 root 파일시스템의 마운트 포인트를 변경함으로써 특정 디렉토리를 새로운 루트 디렉토리로 만드는 명령어이다.

앞서 chroot로 만든 격리공간은 root 파일시스템이 동일하였기 때문에 탈옥이 가능했던 한편, pivrot_root를 이용하면 root 파일시스템의 마운트 포인트 자체가 변경되기 때문에 탈옥 자체가 불가능하다.

image

위 그림과 같이 새로운 root 파일 시스템을 지정하고, 기존 root 파일시스템 마운트 포인트를 새로운 root 파일시스템 하위 폴더로 옮겨주는 작업을 진행해보자.


2-1) 격리 공간 생성

man pivot-root로 매뉴얼을 보면 다음과 같이 새로운 root 경로와 기존 root 경로를 제공함으로써 격리공간을 생성하게 된다.

PIVOT_ROOT(8)                           System Administration                          PIVOT_ROOT(8)

NAME
       pivot_root - change the root filesystem

SYNOPSIS
       pivot_root new_root put_old

앞 실습과 마찬가지로 격리 시킬 새로운 경로를 만든 후 nginx 이미지로 환경을 구성해주자.

# mkdir jail
# docker export $(docker create nginx:latest) | tar -C jail -xvf -

2-2) 탈옥 코드 작성 및 탈옥 확인

chroot 테스트 때 작성한 탈옥 코드를 똑같이 복사하여 실행시켜보자.

# 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);
}

[격리 공간 하위로 탈옥 코드 복사]

# apt install gcc
# gcc -o jail/escape_chroot escape_chroot.c
# ls ./jail
bin   dev   docker-entrypoint.sh  etc   lib    media  opt   root  sbin  sys  usr
boot  docker-entrypoint.d  escape_chroot  home  lib64  mnt    proc  run   srv   tmp  var

[탈옥 실행]

# chroot jail /bin/sh
# ./escape_chroot

앞 실습에서 실행했던 것과 마찬가지로 탈옥코드를 통해 격리공간을 빠져나올 수 있다.

2-3) pivot_root를 활용한 탈옥 방지

이제 pivot_root 를 활용하여 root 파일시스템 위치를 아예 바꿈으로써 탈옥이 불가능하도록 한다.

우선 새로운 root 파일시스템이 될 새로운 폴더를 생성해준 후 tmpfs 파일시스템을 새로운 폴더에 마운트시켜준다.

# mkdir new_jail
# mount -n -t tmpfs -o size=800M none ./new_jail/
# df -h /new_jail
Filesystem      Size  Used Avail Use% Mounted on
none            800M     0  800M   0% /new_jail
# mount | grep new_jail
none on /new_jail type tmpfs (rw,relatime,size=819200k)

새로운 폴더(new_jail)에 기존 jail 내부 파일들을 복사한다. 그 후 pivot_root 시 기존의 root filesystem을 mount 할 mount point로 /new_jail 하위에 old_jail/ 폴더를 생성한다.

# cp -r jail/* ./new_jail/
# mkdir ./new_jail/old_jail
# tree -L 1 ./new_jail/
./new_jail/
├── bin
...
├── escape_chroot
...
├── old_jail
...
└── var

pivot_root로 root 파일시스템의 마운트 포인트를 기존 root에서 /new_jail/old_jail로 변경할 때 호스트에 영향을 주지 않기 위해서 호스트와 newjail의 마운트 네임스페이스를 분리해야 한다.

linux의 명령어 중 네임스페이스(격리공간)을 생성하는 명령어는 unshare이다. 이 명령어를 사용하여 호스트에서부터 마운트 네임스페이스를 격리해주자.

root@ubuntu-focal:/# cd ./new_jail/
root@ubuntu-focal:/new_jail# unshare -m

마운트 네임스페이스 격리란?

프로세스와 그 자식 프로세스가 서로 다른 파일시스템 마운트 지점을 제공함으로써 자식 프로세스에서 파일 시스템을 마운트/언마운트 해도 부모 프로세스에 영향을 미치지 않는 상태를 의미한다.

마운트 네임스페이스 격리를 했으면 pivot_root명령어로 root 파일시스템의 마운트 포인트를 old_jail로 변경한다.

root@ubuntu-focal:/new_jail# pivot_root . old_jail
root@ubuntu-focal:/new_jail# cd /
root@ubuntu-focal:/# ls
bin   docker-entrypoint.d   etc   lib64  old_jail  root  srv  usr
boot  docker-entrypoint.sh  home  media  opt       run   sys  var
dev   escape_chroot         lib   mnt    proc      sbin  tmp

탈옥 코드 명령어를 실행해도 빠져나갈 수 없는 것을 확인할 수 있다.

# ./escape_chroot
# ls
bin   docker-entrypoint.d   etc   lib64  old_jail  root  srv  usr
boot  docker-entrypoint.sh  home  media  opt       run   sys  var
dev   escape_chroot         lib   mnt    proc      sbin  tmp

3) 네임스페이를 통한 격리

pivot_root 는 chroot로 만든 격리공간의 단점인 탈옥을 해결하였다. 그러나 나머지 단점들은 아직 해결이 안되었는데, 이는 네임스페이스라는 개념으로 해결할 수 있다.

  1. 탈옥이 가능하다. -> pivot_root로 해결!
  2. 완전한 격리가 불가능하다. (Host의 filesystems, network 등에 접근 가능)
  3. root 권한 사용 가능하다.
  4. host의 자원을 무제한으로 사용할 수 있다.

다음 글에서는 네임스페이스 개념과 그 종류에 대해 알아보겠다.

reference

0개의 댓글