1. 프로세스
1-1. 프로세스란?
프로그램을 실행하면 메모리 같은 주기억장치로 옮겨오면서 CPU 자원을 할당 받아 실행 중인 프로그램을 "프로세스" 라고 한다.
- 프로세스는 실행중인 프로그램의 인스턴스를 의미
- 프로세스는 CPU와 메모리를 사용하는 기본 단위, OS 커널(cgroup) 에서 자원을 관리 함
1-2. 프로세스 정보 확인
/proc/
프로세스 번호에는 상세정보가 담겨 있음
/proc/[PID]/cmdline | 해당 프로세스를 실행할 때 사용된 명령어와 인자를 포함 |
/proc/[PID]/cwd | 프로세스의 현재 작업 디렉터리에 대한 심볼릭 링크 ls -l로 확인하면 해당 프로세스가 현재 작업 중인 디렉터리를 알 수 있음 |
/proc/[PID]/environ | 프로세스의 환경 변수를 나타냄 각 변수는 NULL 문자로 구분 |
/proc/[PID]/exe | 프로세스가 실행 중인 실행 파일에 대한 심볼릭 링크 |
/proc/[PID]/fd | 프로세스가 열어놓은 모든 파일 디스크립터에 대한 심볼릭 링크를 포함하는 디렉터리 이 파일들은 해당 파일 디스크립터가 가리키는 실제 파일이나 소켓 등을 참조 함 |
/proc/[PID]/maps | 프로세스의 메모리 맵을 나타냄 메모리 영역의 시작과 끝 주소, 접근 권한, 매핑된 파일 등을 확인할 수 있음 |
/proc/[PID]/stat | 프로세스의 상태 정보를 포함한 파일 이 파일에는 프로세스의 상태, CPU 사용량, 메모리 사용량, 부모 프로세스 ID, 우선순위 등의 다양한 정보가 담겨 있음 |
/proc/[PID]/status | 프로세스의 상태 정보를 사람이 읽기 쉽게 정리한 파일 PID, PPID(부모 PID), 메모리 사용량, CPU 사용률, 스레드 수 등을 확인할 수 있음 |
2. 도커
2-1. 도커란?
도커는 컨테이너이며 왼쪽과 같은 가상머신(VM)은 하이퍼바이저를 설치하고, 그위에 OS를 가상화하는 하드웨어 레벨의 가상화를 지원하지만, 컨터에너는 운영체제를 제외한 나머지 어플리케이션 실행에 필요한 모든 파일을 패키징한다는 점에서 OS레벨 가상화를 지원
2-2. 도커 설치 - 링크
# 도커 설치
curl -fsSL https://get.docker.com | sh
2-3 도커는 기본적으로 root가 아닌 유저가 관리하지 못함 - 링크
`ubuntu` 계정으로 도커 정보 획득 실패
docker.sock 소켓의 권한 문제로 인한 문제
권한 할당후 정상적으로 정보 획득이 가능한 것을 알 수 있음
2.4 도커 데몬은 Unix Domain Socket인데, Unix Domain Socket 멀까?
Unix Domain은 동일한 시스템 내에서 실행되는 프로세스들 간의 통신을 의미, "Domain"은 로컬 시스템 내의 통신 영역을 의미
TCP 영역을 거치지 않고 Unix Domain Socket으로만 통신을 하는것을 알 수 있음
3. 컨테이너 격리
chroot
chroot를 사용하였지만, sh 명령어가 없다는 에러가 발생
root@MyServer:/tmp# ldd /bin/sh
linux-vdso.so.1 (0x00007ffdfadb2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007464fc200000)
/lib64/ld-linux-x86-64.so.2 (0x00007464fc5ad000)
root@MyServer:/tmp# mkdir -p myroot/{bin,lib64,lib/x86_64-linux-gnu}
root@MyServer:/tmp# cp /usr/bin/sh myroot/bin/
root@MyServer:/tmp# cp /lib/x86_64-linux-gnu/libc.so.6 myroot/lib/x86_64-linux-gnu/
root@MyServer:/tmp# cp /lib64/ld-linux-x86-64.so.2 myroot/lib64
root@MyServer:/tmp# tree myroot
myroot
├── bin
│ └── sh
├── lib
│ └── x86_64-linux-gnu
│ ├── libc.so.6
│ ├── libpcre2-8.so.0
│ └── libselinux.so.1
└── lib64
└── ld-linux-x86-64.so.2
필요한 라이브러리를 추가해서 chroot 명령어 사용 완료
탈옥이 가능한지 확인하고 싶지만, ls 명령어가 없음
root@MyServer:/tmp# ldd /usr/bin/ls
linux-vdso.so.1 (0x00007ffebefb9000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007dcf4c10f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007dcf4be00000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007dcf4c078000)
/lib64/ld-linux-x86-64.so.2 (0x00007dcf4c167000)
root@MyServer:/tmp# cp /usr/bin/ls myroot/bin/
root@MyServer:/tmp# cp /lib/x86_64-linux-gnu/{libselinux.so.1,libc.so.6,libpcre2-8.so.0} myroot/lib/x86_64-linux-gnu/
root@MyServer:/tmp# cp /lib64/ld-linux-x86-64.so.2 myroot/lib64
root@MyServer:/tmp# tree myroot
myroot
├── bin
│ ├── ls
│ └── sh
├── lib
│ └── x86_64-linux-gnu
│ ├── libc.so.6
│ ├── libpcre2-8.so.0
│ └── libselinux.so.1
└── lib64
└── ld-linux-x86-64.so.2
ls 명령어와 필요한 라이브러리를 배치시키고 정상 동작하는 것을 알 수 있음
경로를 패키징하고, 경로에 격리 시킴
ps 명령어 사용해 보기
# copy ps
ldd /usr/bin/ps;
cp /usr/bin/ps /tmp/myroot/bin/;
cp /lib/x86_64-linux-gnu/{libprocps.so.8,libc.so.6,libsystemd.so.0,liblzma.so.5,libgcrypt.so.20,libgpg-error.so.0,libzstd.so.1,libcap.so.2} /tmp/myroot/lib/x86_64-linux-gnu/;
mkdir -p /tmp/myroot/usr/lib/x86_64-linux-gnu;
cp /usr/lib/x86_64-linux-gnu/liblz4.so.1 /tmp/myroot/usr/lib/x86_64-linux-gnu/;
cp /lib64/ld-linux-x86-64.so.2 /tmp/myroot/lib64/;
# copy mount
ldd /usr/bin/mount;
cp /usr/bin/mount /tmp/myroot/bin/;
cp /lib/x86_64-linux-gnu/{libmount.so.1,libc.so.6,libblkid.so.1,libselinux.so.1,libpcre2-8.so.0} /tmp/myroot/lib/x86_64-linux-gnu/;
cp /lib64/ld-linux-x86-64.so.2 /tmp/myroot/lib64/;
# copy mkdir
ldd /usr/bin/mkdir;
cp /usr/bin/mkdir /tmp/myroot/bin/;
cp /lib/x86_64-linux-gnu/{libselinux.so.1,libc.so.6,libpcre2-8.so.0} /tmp/myroot/lib/x86_64-linux-gnu/;
cp /lib64/ld-linux-x86-64.so.2 /tmp/myroot/lib64/;
# tree 확인
tree myroot
myroot
├── bin
│ ├── ls
│ ├── mkdir
│ ├── mount
│ ├── ps
│ └── sh
├── lib
│ └── x86_64-linux-gnu
│ ├── libblkid.so.1
│ ├── libc.so.6
│ ├── libcap.so.2
│ ├── libgcrypt.so.20
│ ├── libgpg-error.so.0
│ ├── liblzma.so.5
│ ├── libmount.so.1
│ ├── libpcre2-8.so.0
│ ├── libprocps.so.8
│ ├── libselinux.so.1
│ ├── libsystemd.so.0
│ └── libzstd.so.1
├── lib64
│ └── ld-linux-x86-64.so.2
├── proc
└── usr
└── lib
└── x86_64-linux-gnu
└── liblz4.so.1
ps 명령어에 필요한 라이브러리를 가져왔지만, ps가 정상 동작 하지 않는다.
/proc 디렉토리 생성후에 proc 타입으로 마운트 시켜주면 ps 명령어가 정상 동작한다.
/proc 디렉토리는 커널이 관리 함
chroot는 탈옥이 가능함
docker나 컨테이너 기술들은 chroot를 사용하지 않음
pivot_root를 이용한 격리
unshare --mount /bin/sh
unshare 된 마운트 네임스페이스
mkdir new_root
mount -t tmpfs none new_root
cp -r myroot/* new_root/
tree new_root/
pivot root
신규 root와 기존 root를 지정하는 명령어
mkdir new_root/put_old
cd new_root
pivot_root . put_old
탈옥 되지 않음을 확인
unshare -m | 마운트네임스페이스 격리 |
unshare -u | uts(unix time sharing) 호스트명, 도메인명 격리 |
unshare -i | ipc(inter-process communication) 격리 |
프로세스 격리
root@MyServer:/tmp# unshare -fp --mount-proc /bin/sh
# echo $$
1
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 00:28 pts/1 00:00:00 /bin/sh
root 2 1 0 00:31 pts/1 00:00:00 ps -ef
# lsns -t pid -p 1
NS TYPE NPROCS PID USER COMMAND
4026532275 pid 2 1 root /bin/sh
호스트에서 격리된 프로세스가 보임
네임스페이스 inode 값이 같은 것을 알수 있음
root@MyServer:/tmp# ps aux | grep 'bin/sh'
root 9042 0.0 0.0 6192 1792 pts/1 S 00:28 0:00 unshare -fp --mount-proc /bin/sh
root 9043 0.0 0.0 2892 1664 pts/1 S+ 00:28 0:00 /bin/sh
root 9068 0.0 0.1 7008 2432 pts/3 S+ 00:32 0:00 grep --color=auto bin/sh
root@MyServer:/tmp# lsns -t pid -p 9043
NS TYPE NPROCS PID USER COMMAND
4026532275 pid 1 9043 root /bin/sh
`kill -9 9043` 을 하게 되면 격리된 프로세스가 사라지는 것을 알 수 있음
User 격리
컨테이너로 실행 된 유저는 host에서 root 유저로 실행 됨
관리가 어려운 이유로.. 가능하지만 사용은 안함
하지만.. 보안에 취약
유저를 격리할 수 있다는 것을 알 수 있음
unshare -U --map-root-user /bin/sh