- Authors

- Name
- Youngju Kim
- @fjvbn20031
보호: 접근 제어와 샌드박싱
보호(Protection)는 운영체제에서 프로세스와 사용자가 자원에 접근하는 것을 제어하는 메커니즘입니다. 보안(Security)이 외부 위협으로부터 시스템을 방어하는 것이라면, 보호는 내부적으로 접근 권한을 관리하는 것입니다.
1. 보호의 목표
┌────────────────────────────────────────┐
│ 보호의 원칙 │
│ │
│ 최소 권한 원칙 │
│ (Principle of Least Privilege) │
│ │
│ → 프로세스/사용자에게 작업 수행에 │
│ 필요한 최소한의 권한만 부여 │
│ │
│ 예: │
│ - 웹 서버: 웹 파일 읽기만 허용 │
│ - DB 서버: 데이터 디렉토리만 접근 │
│ - 일반 사용자: 커널 영역 접근 불가 │
│ │
│ 권한 분리 (Need-to-Know): │
│ → 각 모듈이 자기 역할에 필요한 │
│ 정보만 접근 가능 │
└────────────────────────────────────────┘
2. 보호 링 (Protection Rings)
하드웨어 수준에서 권한 수준을 계층화하는 구조입니다.
┌─────────────────────────────────────┐
│ 보호 링 (x86) │
│ │
│ ┌─────────────────────────┐ │
│ │ Ring 3: 사용자 애플리케이션│ │
│ │ ┌─────────────────┐ │ │
│ │ │ Ring 2: (미사용) │ │ │
│ │ │ ┌───────────┐ │ │ │
│ │ │ │ Ring 1: │ │ │ │
│ │ │ │ (미사용) │ │ │ │
│ │ │ │ ┌───────┐ │ │ │ │
│ │ │ │ │Ring 0:│ │ │ │ │
│ │ │ │ │ 커널 │ │ │ │ │
│ │ │ │ └───────┘ │ │ │ │
│ │ │ └───────────┘ │ │ │
│ │ └─────────────────┘ │ │
│ └─────────────────────────┘ │
│ │
│ Ring 0: 모든 하드웨어 접근 가능 │
│ Ring 3: 제한된 명령어만 실행 가능 │
│ 시스템 콜로 Ring 전환 │
└─────────────────────────────────────┘
현대 시스템의 권한 구조
┌───────────────────────────────────────┐
│ 하이퍼바이저 모드 (Ring -1, VMX root)│
├───────────────────────────────────────┤
│ 커널 모드 (Ring 0) │
│ - 메모리 관리, 프로세스 관리 │
│ - 장치 드라이버, 파일 시스템 │
├───────────────────────────────────────┤
│ 사용자 모드 (Ring 3) │
│ - 애플리케이션, 라이브러리 │
│ - 시스템 콜을 통해 커널 서비스 요청 │
└───────────────────────────────────────┘
3. 보호 도메인 (Domain of Protection)
프로세스가 접근할 수 있는 자원의 집합을 보호 도메인이라 합니다.
도메인 D1 (사용자 A):
file1.txt → read, write
file2.txt → read
printer → print
도메인 D2 (사용자 B):
file2.txt → read, write
file3.txt → read, write, execute
도메인 D3 (데몬 프로세스):
file1.txt → read
network → send, receive
도메인 전환
프로세스가 한 도메인에서 다른 도메인으로 전환하는 것입니다.
// setuid 프로그램에 의한 도메인 전환 예시
// passwd 명령어: 일반 사용자 → root 권한으로 전환
// 실행 전: uid = 1000 (일반 사용자)
// /usr/bin/passwd 는 setuid root
// 실행 중: euid = 0 (root), ruid = 1000
// → /etc/shadow 파일 수정 가능
// 실행 후: uid = 1000 (원래 사용자로 복귀)
4. 접근 행렬 (Access Matrix)
자원에 대한 접근 권한을 체계적으로 표현하는 모델입니다.
│ file1 │ file2 │ file3 │ printer │ Domain 2│
───────────┼──────────┼──────────┼──────────┼─────────┼─────────┤
Domain 1 │ read │ read │ │ print │ switch │
(사용자 A) │ write │ │ │ │ │
───────────┼──────────┼──────────┼──────────┼─────────┼─────────┤
Domain 2 │ │ read │ read │ │ │
(사용자 B) │ │ write │ write │ │ │
───────────┼──────────┼──────────┼──────────┼─────────┼─────────┤
Domain 3 │ read │ │ │ │ │
(데몬) │ │ │ execute │ │ │
접근 행렬 구현 방법
1. 접근 제어 리스트 (ACL) - 열 기준
file1의 ACL:
┌────────────┬──────────────┐
│ Domain 1 │ read, write │
│ Domain 3 │ read │
└────────────┴──────────────┘
file2의 ACL:
┌────────────┬──────────────┐
│ Domain 1 │ read │
│ Domain 2 │ read, write │
└────────────┴──────────────┘
// POSIX ACL 설정 예시 (Linux)
// 명령어로 ACL 설정
// setfacl -m u:user1:rw file1.txt
// setfacl -m g:developers:r file1.txt
// ACL 확인
// getfacl file1.txt
// # file: file1.txt
// # owner: root
// # group: root
// user::rw-
// user:user1:rw-
// group::r--
// group:developers:r--
// mask::rw-
// other::---
2. 역량 리스트 (Capability List) - 행 기준
Domain 1의 역량:
┌──────────┬──────────────┐
│ file1 │ read, write │ ← 역량 (capability)
│ file2 │ read │ = 객체 + 권한
│ printer │ print │
└──────────┴──────────────┘
Domain 2의 역량:
┌──────────┬──────────────┐
│ file2 │ read, write │
│ file3 │ read, write │
└──────────┴──────────────┘
ACL vs Capability 비교
| 특성 | ACL | Capability |
|---|---|---|
| 관점 | 객체(자원) 중심 | 주체(프로세스) 중심 |
| 권한 확인 | 파일 접근 시 ACL 검색 | 프로세스의 역량 목록 확인 |
| 권한 철회 | 쉬움 (ACL에서 제거) | 어려움 (분산된 역량 추적 필요) |
| 사용 예시 | UNIX 파일 권한, Windows NTFS | Mach, seL4 마이크로커널 |
5. 역할 기반 접근 제어 (RBAC)
사용자에게 직접 권한을 부여하는 대신, 역할(Role)에 권한을 할당하고 사용자를 역할에 배정합니다.
사용자 역할 권한
┌────────┐ ┌──────────┐ ┌──────────────────┐
│ Alice │────→│ 관리자 │────→│ 사용자 관리 │
│ Bob │ │ │ │ 시스템 설정 │
└────────┘ └──────────┘ │ 로그 접근 │
└──────────────────┘
┌────────┐ ┌──────────┐ ┌──────────────────┐
│ Carol │────→│ 개발자 │────→│ 코드 저장소 접근 │
│ Dave │ │ │ │ 빌드 시스템 사용 │
│ Eve │────→│ │ │ 테스트 환경 접근 │
└────────┘ └──────────┘ └──────────────────┘
┌────────┐ ┌──────────┐ ┌──────────────────┐
│ Eve │────→│ 감사자 │────→│ 로그 읽기 │
└────────┘ └──────────┘ │ 보고서 생성 │
└──────────────────┘
(Eve는 개발자 + 감사자 역할을 동시에 가질 수 있음)
RBAC의 장점
- 관리 용이: 사용자 입/퇴사 시 역할만 추가/제거
- 최소 권한: 역할에 필요한 최소 권한만 할당
- 직무 분리: 충돌하는 역할을 동시에 가질 수 없도록 제한 가능
6. 강제 접근 제어 (MAC) - SELinux
DAC vs MAC
DAC (임의적 접근 제어): MAC (강제적 접근 제어):
- 파일 소유자가 권한 결정 - 시스템 정책이 권한 결정
- 사용자가 자유롭게 권한 변경 - 관리자만 정책 변경 가능
- UNIX 기본 파일 권한 - SELinux, AppArmor
DAC 문제:
사용자가 root 권한 획득 시 → 모든 파일 접근 가능
MAC 장점:
root라도 SELinux 정책에 의해 제한됨
SELinux 개념
SELinux 보안 컨텍스트:
user : role : type : level
예시:
system_u:system_r:httpd_t:s0 (Apache 웹 서버)
system_u:object_r:httpd_sys_content_t:s0 (웹 콘텐츠)
정책 규칙:
allow httpd_t httpd_sys_content_t : file { read open getattr };
→ httpd_t 타입의 프로세스는 httpd_sys_content_t 타입의 파일을
읽기, 열기, 속성 확인만 가능
# SELinux 상태 확인
getenforce
# Enforcing, Permissive, Disabled
# 파일의 보안 컨텍스트 확인
ls -Z /var/www/html/
# -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
# 프로세스의 보안 컨텍스트 확인
ps -eZ | head -5
# system_u:system_r:init_t:s0 1 ? 00:00:03 systemd
# system_u:system_r:sshd_t:s0 850 ? 00:00:00 sshd
# 보안 컨텍스트 변경
chcon -t httpd_sys_content_t /var/www/html/newfile.html
7. 샌드박싱 (Sandboxing)
프로그램의 실행 환경을 격리하여 시스템의 나머지 부분에 대한 접근을 제한합니다.
샌드박싱 기법
┌────────────────────────────────────────────┐
│ 샌드박싱 계층 │
│ │
│ 시스템 콜 필터링 (seccomp-bpf): │
│ ┌──────────────────────────────────┐ │
│ │ 프로세스 │ │
│ │ → open(), read() → 허용 │ │
│ │ → execve() → 차단 │ │
│ │ → socket() → 차단 │ │
│ └──────────────────────────────────┘ │
│ │
│ 네임스페이스 격리 (Linux): │
│ ┌──────────────────────────────────┐ │
│ │ PID 네임스페이스: 프로세스 격리 │ │
│ │ NET 네임스페이스: 네트워크 격리 │ │
│ │ MNT 네임스페이스: 파일시스템 격리│ │
│ │ USER 네임스페이스: 사용자 격리 │ │
│ └──────────────────────────────────┘ │
│ │
│ chroot / pivot_root: │
│ ┌──────────────────────────────────┐ │
│ │ 프로세스가 보는 루트 디렉토리 │ │
│ │ 를 제한하여 파일시스템 격리 │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────────┘
seccomp-bpf 예시
#include <seccomp.h>
#include <stdio.h>
#include <unistd.h>
int main() {
// seccomp 필터 초기화 (기본: 모든 시스템 콜 차단)
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
// 허용할 시스템 콜만 추가
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
// 필터 적용
seccomp_load(ctx);
// 이후 read, write, exit만 사용 가능
// 다른 시스템 콜 호출 시 프로세스 종료
printf("Sandboxed process running\n");
seccomp_release(ctx);
return 0;
}
브라우저 샌드박싱
┌──────────────────────────────────────────┐
│ 브라우저 │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 브라우저 │ │ 브라우저 │ │
│ │ 프로세스 │ │ 프로세스 │ ← 높은 권한 │
│ │ (메인) │ │ (GPU) │ │
│ └────┬─────┘ └──────────┘ │
│ │ │
│ ┌────┴─────┬──────────┬──────────┐ │
│ │ 렌더러 │ 렌더러 │ 렌더러 │ │
│ │ (탭 1) │ (탭 2) │ (탭 3) │ │
│ │ 샌드박스│ 샌드박스 │ 샌드박스 │ ← 낮은 권한│
│ │ │ │ │ │
│ │ 파일접근│ 네트워크 │ 시스템콜 │ │
│ │ 제한 │ 제한 │ 제한 │ │
│ └─────────┴──────────┴──────────┘ │
└──────────────────────────────────────────┘
8. 코드 서명 (Code Signing)
실행 파일의 출처와 무결성을 검증하는 메커니즘입니다.
개발자:
1. 코드 작성
2. 해시 생성: hash(코드) = H
3. 서명 생성: sign(H, 개인키) = S
4. 코드 + 서명 S + 인증서 배포
사용자(OS):
1. 코드 다운로드
2. 인증서에서 공개 키 추출
3. 서명 검증: verify(S, 공개키) = H'
4. 코드 해시 계산: hash(코드) = H
5. H == H' ? 실행 허용 : 차단
┌────────────────────────────────────────────┐
│ OS별 코드 서명 정책 │
│ │
│ macOS: │
│ - Gatekeeper: 서명된 앱만 실행 허용 │
│ - 공증(Notarization): Apple 서버 검증 │
│ │
│ Windows: │
│ - Authenticode: 실행 파일 서명 │
│ - SmartScreen: 평판 기반 필터링 │
│ │
│ Linux: │
│ - 커널 모듈 서명 검증 │
│ - Secure Boot: UEFI 부트 체인 검증 │
│ │
│ 모바일 (iOS/Android): │
│ - 앱 스토어 서명 필수 │
│ - iOS: 모든 코드 서명 필수 │
└────────────────────────────────────────────┘
9. 정리
- 보호 원칙: 최소 권한, 권한 분리, 직무 분리
- 보호 링: 하드웨어 수준의 권한 계층 (Ring 0 ~ Ring 3)
- 접근 행렬: ACL(객체 중심)과 역량 리스트(주체 중심)로 구현
- RBAC: 역할 기반 접근 제어로 관리 용이성 확보
- MAC/SELinux: 강제 접근 제어로 root도 정책에 의해 제한
- 샌드박싱: seccomp, 네임스페이스 등으로 프로세스 격리
- 코드 서명: 실행 코드의 출처와 무결성 검증
퀴즈: 보호
Q1. DAC와 MAC의 차이점은 무엇인가요?
A1. DAC(임의적 접근 제어)는 파일 소유자가 자유롭게 권한을 설정하고 변경할 수 있습니다. MAC(강제적 접근 제어)는 시스템 관리자가 정의한 보안 정책에 의해 접근이 결정되며, 개별 사용자나 심지어 root도 정책을 우회할 수 없습니다.
Q2. ACL과 역량 리스트 방식의 장단점을 비교하세요.
A2. ACL은 객체 중심으로 특정 파일에 누가 접근 가능한지 쉽게 파악하고 권한을 철회하기 쉽습니다. 역량 리스트는 주체 중심으로 특정 프로세스가 어떤 자원에 접근 가능한지 빠르게 확인 가능하지만, 특정 자원에 대한 모든 역량을 찾아 철회하기 어렵습니다.
Q3. 샌드박싱이 보안에 어떻게 기여하나요?
A3. 샌드박싱은 프로그램이 접근할 수 있는 시스템 자원을 엄격히 제한합니다. 예를 들어 브라우저의 렌더러 프로세스가 취약점에 의해 공격당하더라도, 샌드박스가 파일 시스템 접근과 시스템 콜을 제한하므로 공격자가 시스템 전체를 장악하기 어렵게 만듭니다.