소프트웨어 샌드박싱의 기초(2025)
요약
본 글은 소프트웨어 샌드박싱의 기초 지식을 다루며, 프로세스 단위 구획화와 액터 모델을 통해 권한 제한의 중요성을 강조합니다. 특히 전통적인 파일 권한 관리 방식과 달리, 애플리케이션 내부에서 자발적으로 권한을 낮추는 '재량적 권한 축소' 개념에 초점을 맞춥니다.
핵심 포인트
- 샌드박싱은 시스템 정책 보완이며, 프로세스 구획화가 핵심입니다.
- 애플리케이션의 권한 제한은 파일 권한보다 복잡하며 재량적 권한 축소가 중요합니다.
- FreeBSD Capsicum이나 Linux Seccomp 같은 확장 인터페이스가 이 간극을 메웁니다.
- 최소 권한 원칙에 따라 프로그램은 권한을 증가시키지 않고 줄여야 합니다.
프로그램 스스로 관리자 권한 없이 권한을 줄이는 샌드박싱 은 시스템 관리자의 보안 정책을 대체하지 않고 보완함
실제 애플리케이션은 프로세스 단위로 구획화 하고 서로 다른 권한을 부여해야 하며, 액터 모델과 메시지 전달로 구획 간 통신을 설계할 수 있음
UNIX 소켓으로 전달하는 파일 디스크립터를 케이퍼빌리티(capability)로 활용 하면 제한된 프로세스에 필요한 자원만 넘길 수 있지만, ioctl
과 블로킹 I/O에는 별도 주의가 필요함
FreeBSD의 Capsicum 은 cap_enter()
로 암묵적 권한을 차단하는 단순한 모델을 제공하지만, Linux에서는 Seccomp와 Landlock 을 조합하면서 ABI 차이와 파일시스템 의존성을 처리해야 함
기존 코드를 전부 다시 작성하지 않아도 libc 함수 가로채기와 자원 접근 중개 로 샌드박싱을 적용할 수 있으며, 신뢰하는 코드의 취약점과 처음부터 신뢰하지 않는 플러그인은 서로 다른 위협 모델로 다뤄야 함
샌드박싱의 범위와 세 가지 조건
Emilua의 샌드박싱 구현 경험 을 바탕으로, 여러 곳에 흩어진 Linux와 FreeBSD 샌드박싱 구현의 기초 지식을 정리함
일부 Lua 예제에는 당시 미출시 버전인 Emilua 0.11 이 필요하며, 개발 브랜치의 최신 커밋으로 실행할 수 있음
Julien Tinnes와 Chris Evans의 2009년 정의 는 샌드박싱을 세 조건으로 정리함
프로그램으로 프로세스 권한을 제한할 수 있어야 함
시스템의 관리자 권한 없이 가능해야 함
프로그램이 자발적으로 권한을 낮추는 재량적 권한 축소(discretionary privilege dropping) 여야 함
CNSS의 2022년 용어집 은 샌드박스를 허가받은 자원 외에는 접근하지 못하게 하는 제한된 실행 환경으로 정의함
샌드박싱의 필수 특성에는 합의가 없으며, 이런 넓은 정의는 앞의 세 조건을 요구하지 않음
여기서 다루는 범위는 재량적 권한 축소이며, 시스템 관리 정책과 함께 적용 해야 함
관리자용 격리와 프로그램의 권한 축소는 다름
UNIX 파일 권한 은 관리자가 서비스를 격리하는 도구이지, 애플리케이션 내부의 모든 보안 정책을 표현하는 수단은 아님
외부 프로그램이 파일 권한을 자유롭게 바꾸게 하면 관리자의 정책 자체가 무력화됨
Twitter 피드의 공개 대상이나 Identi.ca 메시지 수신 정책처럼, 애플리케이션이 구성하는 세계의 권한은 파일 권한과 잘 맞지 않음
Firefox가 실행하는 DRM 플러그인 에는 Firefox가 접근할 수 있는 모든 파일, 일반적으로 사용자 홈 디렉터리 전체에 대한 접근권이 필요하지 않음
setuidgid
같은 전통적 도구는 관리자용 인터페이스이며, 이런 프로그램 내부 권한 축소에 적합하지 않음
FreeBSD의 Capsicum , Linux의 Seccomp 같은 확장 인터페이스가 이 간극을 메움
root 없이 권한을 줄여야 하는 이유
suid 도우미로 chroot를 구성 하는 방식은 잠시 시스템 전체의 관리자 권한으로 올라간다는 문제가 있음
모든 프로그램이 suid 실행 파일을 설치하도록 허용할 수는 없음
최소 권한 원칙에 따르면 권한은 증가시키지 않고 줄여야 함
Linux 사용자 네임스페이스 는 내부 프로세스에 해당 네임스페이스의 관리자 권한을 주면서, 원래 관리자만 접근하던 커널 경로를 일반 사용자에게 노출함
이 전제를 고려하지 않고 작성된 커널 코드가 존재하며, 과거에도 보안 문제가 발생함
Andy Lutomirski 는 CLONE_NEWUSER
로 네트워크 네임스페이스의 CAP_NET_ADMIN
을 얻어 일반 사용자가 iptables를 설정할 수 있는 상황을 큰 위험으로 평가함
사용자 네임스페이스는 Docker 같은 신뢰하는 컨테이너 도구에 제한 해서 사용하는 편이 적절하며, 범용 소프트웨어 샌드박싱 인터페이스로는 부적합하다고 평가함
Emilua는 초기 수년간 Linux 네임스페이스에 집중했지만 이후 다른 방법으로 전환함
현재도 네임스페이스를 지원하되 컨테이너 도구 제작용 으로 두며, 애플리케이션 샌드박싱에는 다른 메커니즘을 사용함
실용적인 격리 경계는 프로세스임
주류 운영체제에서 권한 경계는 프로세스 이며, 커널은 자격 정보를 확인해 암묵적 권한(ambient authority)으로 새 자원을 얻을 수 있는지 판단함
Linux는 자격 정보를 스레드별로 관리하지만, 이를 애플리케이션의 안전한 격리 경계로 삼기는 어려움
Adam Langley의 스레드 격리 구상 은 이론적으로 가능하더라도 구현 비용이 매우 큼
신뢰하지 않는 스레드마다 신뢰하는 도우미 스레드를 두고, 소켓 쌍으로 시스템 호출 요청을 받아 검증함
모든 메모리가 적대적일 수 있으므로 도우미는 CPU 레지스터만 신뢰해야 하며, 스택을 사용하는 C 대신 신중하게 작성한 어셈블리가 필요함
mmap
, mprotect
등을 통한 위험한 메모리 변경도 차단해야 함
프로그램을 프로세스로 나눈 뒤에는 구획별 권한 부여와 구획 간 통신 을 해결해야 함
Capsicum 연구의 출발점처럼, 구획화된 애플리케이션 개발은 서로 다른 프로세스가 메시지를 주고받는 분산 애플리케이션 개발 임
액터 모델과 케이퍼빌리티 기반 보안
액터 모델 은 분산 시스템의 대표적 설계 방식이며, Erlang은 이를 고가용성과 내결함성에 활용함
액터는 자체 상태를 관리하고 다른 액터를 생성할 수 있음
다른 액터에 메시지를 보내고, 메시지 안에 다른 액터의 주소를 넣을 수 있음
구현에 필요한 조건은 생성/송신/수신 인터페이스뿐 아니라 메모리와 실행의 분리 까지 포함함
생성 함수는 새 액터의 주소를 반환하고, 주소는 메시지 전송과 메시지 데이터에 사용할 수 있어야 함
수신 함수는 호출한 액터의 큐에서 메시지를 읽으며, 현재 액터의 주소도 얻을 수 있어야 함
액터끼리 메모리를 공유하지 않고, 같은 액터가 여러 스레드에서 동시에 실행되지 않아야 함
스레드 사이를 이동하는 실행은 가능하며, 이 직렬 실행 특성은 Boost.Asio의 strand 와 같음
Emilua의 핵심 인터페이스는 spawn_vm(module)
, actor.send(msg)
와 inbox.receive()
임
숫자, 문자열, 테이블뿐 아니라 응답을 받을 다른 액터나 자신의 inbox
도 메시지에 넣을 수 있음
spawn_vm
에 subprocess = {}
를 지정하면 여러 구현 중 별도 프로세스 기반 액터를 선택함
샌드박싱에서는 프로세스 하나를 액터 하나 로 두고 UNIX 도메인 소켓으로 메시지를 주고받음
생성 시 상속한 소켓이 액터 주소 역할을 하며, UNIX 소켓의 파일 디스크립터 전달 로 다른 액터의 주소도 전달할 수 있음
수신함의 파일 디스크립터는 다른 액터에게 전달하지 않는 다중 생산자/단일 소비자 채널 구조임
파일 디스크립터로 전달할 수 있는 자원은 폭넓음
파일, 디렉터리, 파이프, 소켓 을 전달할 수 있음
/dev/random
이나 GPU 통신용 장치 노드, 공유 메모리인 memfd도 대상임
pidfd/procdesc 같은 프로세스 핸들, eventfd 같은 동기화 객체, eBPF 프로그램도 포함됨
케이퍼빌리티 기반 보안 은 자원 참조와 접근권을 함께 다루며, 잘못된 액터에 디스크립터가 유출되지 않는 구조를 분석하는 데 활용할 수 있음
Pony 는 액터 모델과 케이퍼빌리티 기반 보안을 결합한 프로그래밍 언어임
일반적인 액터 주소는 위조할 수 있지만, 여기서는 위조 불가능한 토큰 대신 사용할 채널 로 이 문제를 해결함
특정 액터가 자원에 실질적으로 접근할 수 있는지, 어떤 샌드박스도 파일과 소켓에 동시에 접근하지 못하도록 구성할 수 있는지 검토할 수 있음
주소 전달은 트리뿐 아니라 임의로 변하는 연결 구조 를 지원함
액터 모델에는 수십 년간 축적된 연구와 학습 자료가 있어 분산 애플리케이션 설계에 활용할 수 있음
파일 디스크립터를 케이퍼빌리티로 사용할 때의 조건
케이퍼빌리티는 단순한 자원 참조가 아니라 해당 자원에 작업을 수행할 권한 까지 포함함
UNIX는 보통 파일 디스크립터를 생성할 때 권한을 검사하고, 이미 열린 디스크립터를 사용할 때는 다시 검사하지 않음
일반 사용자는 /root
나 /etc/shadow
를 직접 열 수 없음
하지만 root가 연 /etc/shadow
의 디스크립터를 상속받은 뒤 일반 사용자로 실행한 grep
은 내용을 읽을 수 있음
suid 실행 파일의 디스크립터 상속 도 이 관례를 유지해야 하는 이유임
일반 사용자는 자신이 가진 디스크립터를 su
같은 특권 프로그램의 표준 입출력으로 넘길 수 있음
단순 write
의 효과가 호출자의 높은 권한 때문에 더 강해진다면 이 상속 자체가 보안 문제가 됨
Linux의 새 마운트 API 도 호출자 자격 정보에 의존하는 작업을 write
로 처리하던 초기 설계를 거부하고, 별도 fsconfig
호출을 사용하는 형태로 받아들여짐
시스템에서 suid를 금지하더라도 커널은 이 호환성 제약을 유지함
ioctl
은 중요한 예외 이며, 신뢰하지 않는 프로세스에서 받은 디스크립터에 실행하면 위험함
Emilua가 사용하는 Boost.Asio의 부적절한 FIONBIO
사용은 수정됐으며, 관련 변경에는 Boost 1.86 이상 이 필요함
Linux의 isatty()
도 내부적으로 ioctl
을 사용하므로 비표준 작업을 주의해야 함
FreeBSD Capsicum의 단순한 권한 모델
Capsicum 은 FreeBSD 9.0부터 포함됐으며, 파일 디스크립터를 케이퍼빌리티로 활용하도록 지원함
cap_enter()
한 번으로 프로세스의 암묵적 권한을 차단함
이후 자원 접근은 열린 디스크립터를 통해 수행해야 하며, 새 자원은 다른 프로세스가 전달해야 함
이름으로 파일을 여는 open
이나 외부 소켓 엔드포인트에 연결하는 작업은 실패함
Emilua는 서브프로세스 초기화 코드에서 C.cap_enter()
를 실행할 수 있음
복잡한 라이브러리 초기화나 시스템 자원 획득보다 먼저 권한을 줄일 수 있음
2010년 Capsicum 연구 의 Chromium 구현 비교에서 필요한 코드량은 큰 차이를 보임
Windows ACL/SID는 22,350줄 , Linux Seccomp와 사용자 공간 시스템 호출 래퍼는 11,301줄 이었음
Linux chroot
는 605줄, Mac OS X Seatbelt는 560줄, Linux SELinux는 200줄, FreeBSD Capsicum은 100줄이었음
이 비교에서 chroot
, Seatbelt, SELinux 방식은 샌드박스 제한이 충분하지 않다고 평가됐으며, 이후 설계의 기준은 Capsicum 모델임
cap_rights_limit
은 디스크립터별 권한을 더 줄임
세마포어 대기는 허용하되 신호 올리기는 금지하는 식의 구분이 가능함
예제는 20개 작업자에게 송신권만 있는 소켓을 전달해, 한 작업자가 공유 채널의 송신을 종료하지 못하게 함
openat()
는 케이퍼빌리티 모드에서도 사용 가능 하며, 상대 경로는 주어진 디렉터리 디스크립터 아래에서만 해석됨
비블로킹 I/O도 보안 경계의 일부임
샌드박스에서 받은 디스크립터를 부주의하게 사용하면 스레드가 멈춰 서비스 거부 공격 으로 이어질 수 있으며, UNIX 비블로킹 I/O의 문제 는 오래전부터 알려져 있음
close()
도 블로킹될 수 있음
소켓과 비소켓은 다르게 처리해야 함
수신한 디스크립터는 fstat
으로 소켓 여부를 확인 한 뒤 다르게 처리해야 함
소켓에는 recv()
의 MSG_DONTWAIT
를 사용해야 하며, 당시 Boost.Asio는 이를 올바르게 처리하지 못함
비소켓에는 준비 상태 알림보다 완료 알림을 사용하는 프로액터 방식이 필요하며, Linux의 io_uring과 FreeBSD의 POSIX AIO가 예시임
FreeBSD에서는 aio_read2()
와 AIO_OP2_FOFFSET
으로 오프셋 없이 읽을 수 있음
다른 방식은 ENOTCAPABLE
로 실패할 가능성이 있고, 이 부분도 당시 Boost.Asio에 문제가 남아 있음
Linux의 io_uring은 보안 우려로 널리 비활성화 돼 있으므로, 관련 보안 경험 을 고려하면 샌드박스가 보낸 비소켓 I/O를 거부하는 선택도 가능함
자원을 누가 생성했는지도 구분해야 함
신뢰하는 프로세스가 생성해 샌드박스에 전달한 경우에는 선택지가 더 많음
그러나 O_NONBLOCK
상태는 디스크립터 복사본 사이에 공유 되므로, 샌드박스에 전달한 순간부터 문제가 될 수 있음
Capsicum에서는 F_SETFL
을 금지해 일부 완화할 수 있지만 FreeBSD에만 해당함
기존 코드의 피해 범위를 줄이는 샌드박싱
외부 운영체제 도구가 프로그램이나 사용자 단위로 격리하더라도, 프로그램 내부 취약점이 악용되면 그 프로그램이 가진 모든 데이터와 자격 증명 이 노출될 수 있음
데이터를 독립적으로 나눌 수 있다면 여러 사용자로 프로그램 인스턴스를 실행하는 기존 보안 수단을 활용할 수 있음
고정된 사용자에게 데이터를 배정하기 어렵거나 관계와 정책이 동적이면 맞춤형 샌드박스 가 필요할 수 있음
사람과 가상 세계 사이의 경계인 셸 에는 샌드박싱을 적용해야 함
데스크톱과 모바일의 그래픽 셸, 서버의 텍스트 셸, 웹의 셸인 브라우저가 해당함
Firefox와 Chrome처럼 자금이 풍부한 프로젝트만 내장 샌드박싱을 제공해서는 안 됨
메신저의 미디어 파싱은 전용 샌드박스에서 수행 해야 함
Telegram의 미디어 파서 취약점 하나가 전체 대화 기록 접근으로 이어질 수 있음
대화에는 자녀의 하교 시간, 금융정보를 공유하는 상대, 집을 비우는 여행 일정 같은 민감한 정보가 들어 있을 수 있음
현실적인 출발점은 전체 코드를 다시 작성하지 않는 것 임
Capsicum에서 수정하지 않은 코드를 샌드박스 안에서 실행하는 방식을 비인지 샌드박싱(oblivious sandboxing)이라고 부름
이 방식만으로 재량적 권한 축소 문제를 해결하는 경우는 드물지만, 두 접근을 함께 적용할 수 있음
libc 가로채기로 기존 프로그램의 접근을 중개함
Super Capsicumizer 9000 은 LD_PRELOAD
로 동적 라이브러리를 주입해 암묵적 권한을 사용하는 함수를 가로챔
fakeroot도 수십 년간 사용한 기법임
소규모 실험으로 복잡한 오래된 라이브러리 위의 프로그램을 실행했으며, gedit의 /etc
열기를 거부하는 사례가 있음
대부분의 프로그램이 직접 시스템 호출을 하지 않고 libc를 거친다 는 점을 활용함
동적 링크에서는 대체 함수가 먼저 로드되도록 함
정적 링크에서는 libc의 약한 심볼을 대체 정의로 덮어쓸 수 있는 경우가 많음
Emilua는 Linux와 FreeBSD의 동적/정적 실행 파일에 이 방식을 사용했으며, 당시 getaddrinfo
만 약한 심볼 속성이 없는 문제를 겪음
관련 문제는 glibc 와 FreeBSD 에 등록돼 있음
대체할 함수는 libcasper와 libpreopen 을 참고할 수 있음
FreeBSD libcasper의 cap_getaddrinfo
등은 추가 인자를 요구하고 원래 함수를 직접 가로채지 않으므로 호출 이름과 인자를 조정해야 함
libpreopen은 Super Capsicumizer 9000이 사용하는 라이브러리임
복잡한 프로그램도 적은 수의 함수만 대체하면 되는 경우가 많으며, Chromium 렌더러 는 fontconfig로 글꼴을 찾고 해당 파일을 여는 정도의 권한만 필요함
Emilua 0.11의 libc_service
는 이런 세부 처리를 추상화하고 UNIX 소켓으로 프로세스 간 요청을 중개함
예제는 /dev/null
의 open
결과를 다른 디스크립터로 바꿔 파이프의 문자열을 읽게 함
source_tree_cache
를 미리 채우면 Lua 코드를 읽기 위한 파일시스템 접근도 피할 수 있음
해당 예제는 간결함을 위해 실제 권한 축소 설정을 생략함
중개 방식은 동적 보안 정책 을 구현할 수 있음
Telegram tdlib 클라이언트라면 pluto.web.telegram.org
의 이름 조회만 허용하고, 그 결과로 얻은 IP에만 연결하도록 제한할 수 있음
샌드박스 쪽 Lua 코드에서 호출 결과를 보정해, /tmp/.X11-unix/X0
연결을 다른 디스플레이 서버의 소켓으로 바꿀 수 있음
LD_PRELOAD
로 기존 xterm
을 실행하고 dup2
로 소켓을 교체해 Xephyr로 연결하는 예제가 있음
kcmp
를 정책에 활용 하면 파일 디스크립터마다 다른 하위 정책을 적용하는 접근도 가능함
Linux의 openat()
를 중개하면서 RESOLVE_BENEATH
에 해당하는 제약 을 추가하면 FreeBSD 케이퍼빌리티 모드처럼 디렉터리 아래로 경로 해석을 제한할 수 있음
중개를 우회하지 못하도록 실제 시스템 호출을 차단하는 조치도 반드시 필요함
네이티브 플러그인은 로드 시점부터 위협 모델을 구분해야 함
신뢰하는 코드가 취약점으로 장악되는 경우 에는 위험한 입력을 처리하기 직전에 권한을 줄일 수 있음
예를 들어 ffmpeg 개발자는 신뢰하되 복잡한 코드에 취약점이 있을 수 있다고 가정하면, 라이브러리를 먼저 불러오고 외부 데이터 처리 전에 샌드박스를 설정할 수 있음
처음부터 신뢰하지 않는 라이브러리 는 로드 자체가 위험함
tdlib를 전혀 신뢰하지 않는다면 FreeBSD jail이나 Linux 네임스페이스 같은 격리 환경에서 먼저 빌드해야 함
이후에도 권한을 줄인 상태에서 플러그인을 불러와야 함
암묵적 권한을 차단하면 일반 dlopen()
은 파일시스템에 접근할 수 없어 실패하므로 디스크립터 기반 로딩 이 필요함
FreeBSD는 fdlopen
을 제공함
Linux는 /proc/self/fd/
경로를 사용할 수 있지만, glibc가 경로로 플러그인 중복을 판별하므로 경로 재사용을 막기 위해 해당 디스크립터를 닫지 않아야 함
이 Linux 방식은 완전한 해결책은 아님
Emilua의 native_modules_cache
는 네이티브 플러그인 캐시를 미리 채우는 기능임
아직 로드하지 않은 동적 라이브러리에 의존하면 추가 로딩 문제가 남음
Linux에서는 /proc/self/fd/
접근에도 필요한 Landlock을 활용할 수 있음
FreeBSD에서는 rtld_set_var
와 LIBRARY_PATH_FDS
를 사용하고, Emilua는 ld_library_directories
로 관련 디렉터리 디스크립터를 전달함
위협 모델 자체가 타당한지 검토 해야 함
tdlib가 처리하는 Telegram 서버의 데이터는 이미 Telegram이 가진 것이지만, 샌드박싱으로 로컬 시스템의 다른 데이터에 대한 무제한 접근은 막을 수 있음
Linux initramfs는 신뢰하는 사용자가 만든 입력이므로, 공격자가 이미 이미지를 바꿀 수 있다면 압축 해제 라이브러리의 취약점 없이도 피해를 줄 수 있음
반면 라이브러리에 백도어가 있다면 문제가 달라지며, 때로는 더 좋아 보이는 코드보다 신뢰할 수 있는 사람이 작성한 감사 가능한 코드 가 중요함
Seccomp로 권한을 줄일 때의 복잡성
Seccomp는 BPF 기반 시스템 호출 필터 이며, 재량적 권한 축소보다 운영체제 보안 강화에 더 적합하다고 평가함
반환 동작은 SECCOMP_RET_KILL_PROCESS
, SECCOMP_RET_KILL_THREAD
, SECCOMP_RET_TRAP
, SECCOMP_RET_ERRNO
, SECCOMP_RET_USER_NOTIF
, SECCOMP_RET_TRACE
, SECCOMP_RET_LOG
, SECCOMP_RET_ALLOW
임
open
, bind
처럼 이름을 사용하는 호출을 거부해 암묵적 권한을 차단하면 앞서 설명한 구획화 모델을 적용할 수 있음
차단 목록 은 새 커널에 추가되는 시스템 호출을 미리 알 수 없다는 문제가 있음
Linux의 다중 아키텍처와 ABI 차이 는 필터 우회 위험을 더함
허용 목록 으로 바꿔도 아키텍처별 구현 차이는 남음
암묵적 권한을 한 번에 끄는 라이브러리로 복잡성을 감출 수는 있지만, 해당 구현은 진행되지 않음
Linux 사용자 공간은 파일시스템과 /proc/self
에 크게 의존 함
open
을 가로채더라도 중첩 샌드박스에서는 기존 코드의 /proc/self
접근이 실패할 수 있음
open
을 허용하고 Landlock으로 파일시스템 접근을 제한하는 편이 나을 수 있음
그러나 /proc/self/fd/
를 다른 모드로 다시 열 수 있다면 디스크립터를 엄밀한 케이퍼빌리티로 모델링하기 어려움
Landlock 개발자들은 Capsicum과 호환되는 케이퍼빌리티 제공을 장기 목표로 두고 있지만 아직 해결된 상태는 아님
Linux에서 현실적으로 사용할 조합은 Seccomp + Landlock 이며, 네임스페이스 기반 접근은 이보다 더 복잡하다고 평가함
Kafel로 정책을 재사용하는 방법과 한계
Kafel 은 시스템 호출 필터 정책을 작성하는 언어와 라이브러리이며, 정책을 Seccomp용 BPF로 컴파일함
예제 정책은 Docker 기본 프로필 의 영향을 받았으며, systemd의 필터 집합과 OpenBSD pledge
의 권한 선언에서 분류 방식을 가져옴
비특권 사용자를 대상으로 하므로 root가 필요한 호출은 제외해 BPF 크기와 오버헤드를 줄임
mincore
, cachestat
처럼 드물게 쓰이고 데스크톱 애플리케이션의 지문 수집에 악용될 수 있는 호출도 제외함
실행 기반과 호환성 정책 을 별도 그룹으로 나눔
CRuntime
: 메모리 할당, 스레딩, 종료, libc 유지에 필요한 호출을 허용하며, 프로그램 이미지가 이미 메모리에 올라온 뒤를 전제로 함
CompatX86
, CompatDB32
, CompatSystemd
, CompatWine
: x86 ABI, remap_file_pages
, 마운트 ID 조회, modify_ldt
같은 호환성 요구를 분리함
Credentials
, CredentialsExtra
, CredentialsMutation
: 자격 정보 조회, 다른 프로세스도 조회할 수 있는 capget
, 자격 정보 변경을 구분함
I/O와 파일 관련 정책 도 역할별로 분리함
Aio
, IoUring
, IoEvent
: 전통적 비동기 I/O, io_uring, 이벤트 루프 호출을 구분함
BasicIo
: 읽기/쓰기 계열과 함께, libc가 파일/소켓/TTY 처리 중 사용할 수 있다는 현실적 이유로 ioctl
을 포함함
FileDescriptors
, FileIo
: 디스크립터 관리와 이미 열린 파일, 전달받은 파일, memfd의 I/O를 구분함
Filesystem
, FilesystemAttr
: 경로 기반 파일시스템 접근과 파일 속성 변경을 나누며, 더 세밀한 경로 권한은 Landlock이 적합함
Sync
: 파일과 메모리를 저장장치에 동기화함
네트워크와 메모리/IPC 정책 은 필요한 기능만 조합하도록 나뉨
NetworkIo
, NetworkServer
: 연결과 송수신, 서버의 수신 대기 작업을 분리함
NetworkSocketTcp
, NetworkSocketUdp
, NetworkSocketUnix
: 소켓 종류와 도메인을 조건으로 제한함
Ipc
: SysV IPC, POSIX 메시지 큐, 파이프, memfd 등을 다룸
Memlock
, Pkey
: 메모리 잠금과 메모리 보호 키를 다룸
프로세스와 운영 제어 정책 도 별도로 구성함
Process
: 프로세스 생성/실행, 관계, 네임스페이스 관련 작업을 다룸
다른 실행 파일을 샌드박싱할 때는 대체로 이 집합이 필요하며, Linux의 Seccomp와 cgroup에 실행 시점 정책 전환 기능이 없다는 제약이 있음
Resources
, ResourcesMutation
: 자원 설정 조회와 변경을 구분함
Sandbox
: Landlock과 Seccomp를 통한 추가 제한을 허용함
Signal
, Clock
, Timer
: 신호 처리, 시간 조회, 시간 기반 작업을 구분함
Debug
: kcmp
, ptrace
, 프로세스 메모리 접근 등을 분리함
디버깅 호출은 이미 다른 권한 장치로 제한되더라도 용도가 좁고 과거 CVE에 등장했으며, 협력 프로세스 간 IPC에는 memfd/봉인/mmap 같은 대안이 있음
예제 정책은 약 1년간 사용 했지만, 그대로 완전하게 작동하는 정책 집합은 아님
Kafel의 시스템 호출 데이터베이스가 부족해 일부 이름을 번호로 바꾸는 전처리가 필요함
clock_gettime64
처럼 빠진 호출이 있으며, 더 나은 데이터베이스를 사용하는 Docker 수준의 범위를 처리하지 못함
다중 아키텍처 지원 부족 도 주요 제약임
추가로 필요한 기능은 정책 버전 관리와 더 나은 정책 조합 연산자 임
해당 개선 작업은 고객 수요와 개발 시간 문제로 진행되지 않음
후속으로 남은 주제
추가 글을 작성한다면 액터 모델, 케이퍼빌리티 기반 보안, 접근 제어 정책 을 더 깊이 다룰 가능성이 있음
구현과 운영 측면에서는 그래픽 앱의 컨테이너 실행 데모, Linux의 우회 구현, Windows/macOS, Emilua의 컨테이너 런타임 기능, GUI 애플리케이션 샌드박싱이 후보임
보안 세부 주제로는 PR_SET_DUMPABLE
과 /proc/sys/kernel/yama/ptrace_scope
, 공격 표면과 안전한 파서, FreeBSD libnv, 권한 회수와 프록시, 샌드박싱 패턴, Emilua가 활용하는 C/UNIX 기법이 남아 있음
댓글과 토론
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기