이 글을 읽기 위해 chroot를 알고 있어야 합니다. chroot는 저의 이전 글에 정리했습니다.
1. chroot 취약점
chroot는 디렉터리를 탐색할 수 있는 취약점이 있습니다.
아래 예제는 chroot로 nginx컨테이너를 생성한 프로세스입니다. nginx 컨테이너가 디렉터리 탐색을 사용해서 최상위 경로로 루트 디렉터리를 변경했습니다.
nginx 컨테이너의 루트 디렉터리가 호스트 루트 디렉터리로 변경되었기 때문에, 호스트에 있는 정보를 탈취할 수 있습니다. 아래 예는 /etc/passwd파일을 탈취했습니다. 실습환경이 vagrant이기 때문에 vagrant user가 보입니다.
아래 코드는 파이썬 탈옥코드입니다. 탈옥코드는 chdir과 chroot를 같이 사용하면 됩니다. chdir은 현재 작업 디렉터리를 변경하고 chroot는 루트 디렉터리를 변경합니다.
import os
if not os.path.exists("chroot-dir"):
os.mkdir("chroot-dir")
os.chroot("chroot-dir")
for i in range(1000):
os.chdir("..")
os.chroot(".")
os.system("/bin/bash")
2. chroot 탈옥이 가능한 이유?
chroot로 루트 디렉터리를 변경하면, 루트 디렉터리와 현재 작업 디렉터리가 상대경로로 변경됩니다. 상대경로는 디렉터리 탐색(예: ../)이 가능하기 때문에 탈옥이 가능합니다.
루트 디렉터리와 작업 디렉터리는 /proc/{process_id}/root, /proc/{process_id}/cwd에 있습니다.
# chroot 프로세스 id 조회
$ echo $$
5394
# host에서 chroot 프로세스 루트 디렉터리(root), 작업 디렉터리(cwd)조회
$ cat /proc/5394/root
$ cat /proc/5394/cwd
3. pivot_root란?
pivot_root는 chroot의 취약점을 보완했습니다. pivot_root를 실행하면 아래 그림처럼 루트 디렉터리가 “/”로 변경됩니다. 루트 디렉터리가 상대경로로 설정되는 chroot와 다른 결과입니다.
pivot_root 원리는 루트 디렉터리가 “/”로 설정되도록 루트 파일 시스템을 변경합니다. man chroot와 man pivot_root의 설명을 보면, chroot는 루트 디렉터를 변경하고 pivot_root는 루트 파일 시스템을 변경한다고 되어 있습니다.
4. pivot_root 실행방법
pivot_root는 현재 루트 파일 시스템을 디렉터리에 백업한 후, 지정한 경로로 루트 파일시스템을 변경합니다. 제 생각은 mount namespace를 사용하면 백업한 루트 파일 시스템은 사용할 일이 없을 것 같습니다.
mkdir .old_root
pivot_root {새로운 루트 파일 시스템 경로} .old_root
5. 실습
실습에서는 pivot_root로 루트 파일 시스템을 변경하고 탈옥이 되는지 테스트합니다. 실습을 하기 위해 docker가 필요합니다.
python이 설치된 debian 리눅스 컨테이너를 실행하고 docker export로 컨테이너 파일을 추출합니다. 추출된 파일은 debian_python.tar압축파일입니다.
docker export $(docker create python:bullseye) -o /root/test/debian_python.tar
ls -l /root/test/debian_python.tar
debian압축파일을 압축해제합니다. 저는 /root/test경로에 압축해제했습니다.
mkdir /root/test
cd /root/test
mkdir -p ./debian_python
tar -xvf ./debian_python.tar -C ./debian_python
mount namespace를 생성하면서 sh쉘을 실행합니다. sh쉘을 생성한 이유는 mount namespace를 사용하여 mount작업을 격리하기 위해서입니다.
unshare --mount sh
mount --bind ./debian_python ./debian_python
sh쉘의 루트 파일 시스템을 백업할 디렉터리를 만듭니다.
mkdir ./debian_python/.oldrootfs
pivot_root를 사용하여 루트 파일 시스템을 debian_python 디렉터리로 변경합니다.
cd ./debian_python
pivot_root . .oldrootfs
루트 파일 시스템을 변경한 후, 수동으로 변경된 루트 디렉터리로 이동해줘야합니다.
cd /
루트 디렉터리 이동 후 ls, python 등 명령어가 잘 실행되는지 확인합니다.
ls
whoami
python
이제 sh쉘이 탈옥이 되는지 확인해봅니다. pivot_root를 사용했기 때문에 당연히 안되야 합니다. 탈옥코드는 chroot테스트와 동일하게 파이썬 스크립트를 사용합니다.
cat > breakout.py
import os
if not os.path.exists("chroot-dir"):
os.mkdir("chroot-dir")
os.chroot("chroot-dir")
for i in range(1000):
os.chdir("..")
os.chroot(".")
os.system("/bin/bash")
탈옥코드를 실행하고 /etc/passwd를 확인하여 탈옥이 실패했는지 확인합니다. debian 컨테이너의 /etc/passwd가 보여야 합니다.
# 탈옥 시도
python3 breakout.py
# debian 컨테이너의 /etc/passwd가 보이면 탈옥 실패
cat /etc/passwd
탈옥이 실패한 이유는 루트 파일 시스템이 변경되어서, 루트 디렉터리가 상대경로가 아닌 “/”로 변경되었기 때문입니다.
# chroot를 실행한 프로세스에서 process id 조회
$ echo $$
7513
# host에서 실행
$ ls -l /proc/7513/root
$ ls -l /proc/7513/cwd
참고자료
- https://thomasvanlaere.com/posts/2020/04/exploring-containers-part-1/
- 이게 돼요? 도커 없이 컨테이너 만들기 / if(kakao)2022 - https://youtu.be/mSD88FuST80?si=Vbl63IkW6Dc8YFJk
- https://book.hacktricks.xyz/linux-hardening/privilege-escalation/escaping-from-limited-bash
이하공백
'전공영역 공부 기록' 카테고리의 다른 글
AWS ALB에 여러 도메인 인증서(ACM)를 적용한 경험 (2) | 2024.09.11 |
---|---|
Pause container는 어떻게 실행될까? (1) | 2024.09.08 |
Istio ServiceEntry설정할 때 IP만 사용하려면? (0) | 2024.09.04 |
AWS security group 체이닝이 불가능한지 확인하는 방법 (0) | 2024.09.04 |
chroot - 컨테이너는 어떻게 파일을 실행할까? (2) | 2024.09.02 |