인터넷과 같은 공중망은 위험한 장소다. (심지어 일시적이라고 할지라도) 인터넷에 붙은 컴퓨터를 소유한 어느 누구라도 이런 위험을 이해한다. 공격자들은 시스템 접근 권한을 얻거나 불법적으로 정보에 접근하거나, 스팸을 뿌리기 위해 다른 컴퓨터의 용도를 변경하거나, (분산 서비스 거부 공격의 일부로 SYN 넘침 공격을 사용하려고) 고성능 시스템 공격에 참여하기 위해 보안 취약성을 악용한다.
DDoS 공격은 인터넷에 연결된 (좀비 컴퓨터라 불리는) 여러 시스템이 연합해 목표 시스템의 자원을 고갈시켜, (TCP/IP 3단계 이중 확인을 악용하는 방법으로) 선의의 사용자들이 접속을 못하도록 방해한다. 쿠키와 4단계 이중 확인(SCTP: Stream Control Transmission Protocol)을 사용해 이런 문제점을 해결하는 프로토콜에 대한 설명이 필요하면, 참고자료 절을 읽어보기 바란다.
GNU/리눅스는 아주 안전하지만 또한 아주 변화무쌍하기도 하다. 변경 과정에서 운영체제에 구멍이 나는 바람에 보안 침해 요소가 생길 수 있다. 물론 불법적인 접근을 막아내기 위해 상당한 주의를 기울이고 있지만, 사건이 터지고 난 다음에는 무슨 소용이 있으랴?
이 기사는 SELinux와 기본 아키텍처 이면에 숨겨진 아이디어를 설명한다. SELinux라는 주제를 완벽하게 개괄하려면 책 한 권이 필요하다(참고자료 절 참조). 따라서 이 기사에서는 SELinux가 중요한 이유와 구현 방법에 대한 아이디어를 주도록 기본에 충실하겠다.
대다수 운영체제는 엔티티(사용자 또는 프로그램)가 특정 자원에 접근할 수 있는지를 판단하려고 접근 통제 기법을 사용한다. 유닉스(UNIX®) 기반 시스템은 DAC(Discretionary Access Control)를 사용한다. 이런 방법은 소속 그룹에 기반을 두고 객체 접근을 제약한다. 예를 들어, GNU/리눅스에서 파일에는 소유자, 그룹, 접근 허가 집합이 있다. 접근 허가는 특정 파일에 접근하는 사용자를 정의해 누가 읽고, 쓰고, 실행하는지를 결정한다. 이런 접근 허가는 사용자를 사용자(파일 소유자), 그룹(그룹에 속한 모든 사용자), 다른 사람(그룹에도 속하지 않고 사용자도 아닌 다른 모든 사용자)이라는 세 부류로 나눈다.
이와 같은 어색한 접근 통제 기법이 문제를 일으키는 이유는 보안 침해에 걸린 프로그램이 해당 사용자의 접근 통제 권한을 상속받기 때문이다. 따라서 프로그램은 사용자에게 부여된 접근 권한 수준에서 작업이 가능하므로, 바람직하지 못한 결과를 초래한다. 이런 방식으로 제약을 정의하는 대신에, 최소 권한 원칙을 사용하는 편이 좀 더 안전하다. 프로그램은 작업을 수행하기 위해 필요한 만큼만 권한을 얻으며, 더 이상은 권한을 얻지 않는 방법 말이다. 예를 들어, 소켓 요청에 응답해야 하지만 파일 시스템에 접근할 필요가 없는 프로그램이 있다면, 이 프로그램은 소켓에 귀를 기울이지만 파일 시스템에는 접근 권한이 없어야 한다. 이런 방식을 따르면, 프로그램이 어떤 식으로 보안 침해에 걸리더라도 접근이 명시적으로 최소화된다. 이런 통제 기법을 MAC(Mandatory Access Control)라 부른다.
또 다른 통제 기법으로 RBAC(Role-Based Access Control)가 있다. RBAC에서, 접근 허가는 보안 시스템이 허용한 역할에 기반을 두고 접근 허가를 제공한다. 이런 역할 개념은 한 명 이상의 사용자를 표현하는 그룹이라는 측면에서 전통적인 그룹과 차이를 보인다. 역할은 여러 사용자를 대표하지만, 사용자 집합이 수행할 수 있는 접근 허가 역시 표현한다.
SELinux에서는 MAC와 RBAC를 둘 다 GNU/리눅스 운영체제에 추가했다. 다음 절은 SELinux 구현과 보안 요소를 리눅스 커널에 투명하게 추가한 방법을 설명한다.
초창기 SELinux 시절에는, 패치 집합이 있었음에도 불구하고, 독자적인 보안 프레임워크를 제공했다. 이런 정책이 문제가 된 이유는 GNU/리눅스를 단일 접근 통제 아키텍처로 묶어버렸기 때문이다. 단일 접근 방식을 채택하는 대신, 리눅스 커널은 정책을 강제하지 않도록 일반화된 프레임워크를 상속받았다. 이런 해법이 바로 LSM(Linux Security Module) 프레임워크다. LSM은 적재 가능한 커널 모듈로 구현된 보안용 범용 프레임워크를 제공한다(그림 1 참조).
그림 1. 보안 정책과 강제는 SELinux와 독립적이다.
커널 코드를 수정해 내부 객체에 접근하기 앞서 보안 정책을 구현한 강제 함수라는 훅을 호출하도록 만든다. 이 함수는 미리 정해진 정책을 기반으로 연산을 계속할지 검증한다. 보안 함수는 반드시 보호되어야 하는 기본적인 연산을 다루는 보안 연산 구조체 내부에 저장되어 있다. 예를 들어, security_socket_create 훅(security_ops->socket_create)은 새로운 소켓을 생성하기 앞서 접근 허가를 검사하며 프로토콜 가족, 유형, 프로토콜, 소켓이 커널 내부에서 만들어지는지 사용자 영역에서 만들어지는지를 고려한다. Listing 1은 소켓 생성을 위한 socket.c에서 가져온 코드 예제다(./linux/net/socket.c 참조).
Listing 1. 소켓 생성을 위한 커널 코드
static int __sock_create(int family, int type, int protocol,
struct socket **res, int kern)
{
int err;
struct socket *sock;
/*
* 프로토콜이 범위 내에 있는지 점검한다.
*/
if (family < 0 || family >= NPROTO)
return -EAFNOSUPPORT;
if (type < 0 || type >= SOCK_MAX)
return -EINVAL;
err = security_socket_create(family, type, protocol, kern);
if (err)
return err;
...
|
security_socket_create 함수는 ./linux/include/linux/security.h에 정의되어 있다. 여기서 security_socket_create 함수 호출은 security_ops 구조체에 동적으로 설치된 함수를 간접 호출하는 방식으로 동작한다(Listing 2 참조).
Listing 2. 소켓 생성 점검을 위한 간접 호출
static inline int security_socket_create (int family, int type,
int protocol, int kern)
{
return security_ops->socket_create(family, type, protocol, kern);
}
|
security_ops 구조체에 저장된 함수는 보안 모듈이 설치한다. 이 경우 훅은 SELinux용 적재 가능한 커널 모듈에 정의되어 있다. 각 SELinux 호출은 커널 함수에서 특정 보안 모듈을 위한 동적 호출로 간접 수행을 완료하는 훅 파일 내부에 정의된다(Listing 3에서 /linux/security/selinux/hooks.c를 살펴보라).
Listing 3. SELinux 소켓 생성 점검
static int selinux_socket_create(int family, int type,
int protocol, int kern)
{
int err = 0;
struct task_security_struct *tsec;
if (kern)
goto out;
tsec = current->security;
err = avc_has_perm(tsec->sid, tsec->sid,
socket_type_to_security_class(family, type,
protocol), SOCKET__CREATE, NULL);
out:
return err;
}
|
Listing 3의 핵심은 현재 태스크에 허용된(current->security, 여기서 current는 현재 수행중인 태스크를 나타낸다) 현재 연산을 점검하는 호출이다. AVC(Access Vector Cache)는 (프로세스 성능을 높이기 위해) 직전 SELinux 결정을 담고 있는 캐시다. 호출은 sid(source security identifier), 보안 클래스(요청된 연산의 세부 사항으로 만들어지는), 특정 소켓 호출, 추가 보조 감사 자료를 포함한다. 캐시 내부에서 결정을 찾지 못하면, 보안 서버를 호출해 결정을 내린다(그림 2에 이런 과정이 나타나 있다).
그림 2. 계층적인 리눅스 보안 결정 과정
security-ops 내에 초기화된 콜백 훅은 (register_security()를 통해) 적재 가능한 커널 모듈로 동적으로 정의되지만 그렇지 않다면 보안 모듈을 올리지 않은(./linux/security/dummy.c 참조) 상태에서 더미 스텁 함수를 포함한다. 이런 스텁 함수는 표준 리눅스 DAC 정책을 구현한다. 콜백 훅은 보안을 위한 중재가 필요한 모든 지점에 존재하며, 태스크 관리(생성, 시그널, 대기), 프로그램을 메모리에 올리기(execv), 파일 시스템 관리(슈퍼 블록, 아이노드, 파일훅), IPC(메시지 큐, 공유 메모리, 세마포어 연산), 모듈 훅(모듈 적재와 제거), 네트워크 훅(소켓, 넷링크, 네트워크 디바이스, 기타 프로토콜 인터페이스)을 포함한다. 참고자료 절을 보거나 security.h 파일을 살펴보는 방법으로 훅에 대한 다양한 정보를 얻을 수 있다.
SELinux에서 정책 관리 방법은 이 기사 범위를 넘어가므로, 참고자료 절에서 SELinux 환경 설정에 대한 더 많은 정보를 찾아보기 바란다.
SELinux는 현존하는 가장 포괄적인 보안 프레임워크 중 하나지만 유일한 해법은 아니다. 이 절에서는 사용 가능한 몇 가지 다른 접근 방법을 검토한다.
원래 immunix가 개발했으며 노벨(Novell)이 관리하는 AppArmor는 LSM(Linux Security Module)을 사용해 만든 SELinux 대안 프레임워크다. SELinux와 AppArmor는 동일한 프레임워크를 사용하므로 상호 교환이 가능하다. AppArmor를 처음 개발한 이유는 SELinux가 일반 사용자가 관리하기에는 너무 복잡하게 보였기 때문이다. AppArmor는 프로그램의 전형적인 행동 양식을 프로파일로 바꾸는 학습 모드와 더불어 완벽하게 설정 가능한 MAC 모델을 포함한다.
SELinux와 관련한 쟁점 하나는 SELinux는 확장 속성을 지원하는 파일 시스템을 요구한다는 사실이다. 하지만 AppArmor는 파일 시스템에 중립적이다. SuSE, OpenSuSE, Ubuntu Gutsy Gibbon에서 AppArmor를 찾을 수 있다.
Solaris 10(기존 Trusted Solaris)
Solaris 10 운영체제는 보안 강화 신뢰 확장 구성 요소를 통해 위임 접근 통제 기능을 제공한다. Solaris 10은 MAC은 물론이고 RBAC도 제공한다. Solaris는 모든 객체에 민감도 라벨을 추가하는 방법으로 보안을 달성한다. 이렇게 하면 디바이스, 파일, 네트워크 접근, 심지어 윈도우 관리 서비스에 대한 통제가 가능하다. Solaris 10에서 RBAC를 사용해 얻는 장점은 할당될 수 있는 관리 작업을 세밀하게 분류함으로써 루트 접근 요청을 최소로 줄이는 데 있다.
TrustedBSD는 FreeBSD 운영체제를 위한 궁극적인 목표인 신뢰할 수 있는 운영체제 확장을 개발하려는 프로젝트다. TrustedBSD는 Flask(Flux Advanced Security Kernel) 보안 아키텍처 위에 만든 위임 접근 통제 기능을 포함한다. Flask는 타입 강제, MLS(MultiLevel Security), 플러그인 모듈을 포함한다. TrustedBSD는 또한 애플 다윈 운영체제에서 따온 오픈 소스 BSM(Basic Security Module) 감사 구현 기능을 편입했다(BSM은 원래 썬이 만들었다). BSM은 일반화된 감사 추적 과정을 지원하는 감사 API와 파일 형식이다. TrustedBSD는 또한 SEDarwin(Security Enhanced Darwin)이 사용하는 프레임워크를 구성한다.
운영체제 내부에서 보안을 강화하는 기술로 마지막으로 소개할 내용은 (가상 전용 서버라 부르는) 운영체제 가상화다. 단일 운영체제가 기능을 분리하기 위한 수단으로 격리된 사용자 영역 인스턴스 여러 개를 돌린다. 운영체제 가상화는 또한 격리된 사용자 영역에서 동작하는 응용 프로그램 기능을 제한한다. 예를 들어, 사용자 영역 인스턴스는 (커널 모듈을 올리고 내리는 방식으로) 커널을 변경하거나 파일 시스템을 마운트/언마운트하지 못한다. (proc 파일 시스템을 통한) 커널 매개변수 조정 역시 허용되지 않는다. 다른 사용자 인스턴스 환경을 변경하는 작업도 허용되지 않는다.
운영체제 가상화는 여러 운영체제에서 사용 가능하다. GNU/리눅스는 VServer, Paralles Viruozzo Containers, OpenVZ를 지원한다. 다른 운영체제에서는 containers(Solaris), jails(BSD)를 지원한다. 리눅스 VServer에서는 개별 사용자 영역 인스턴스를 보안 문맥으로 부른다. 각 보안 문맥 내부에서, 전용 서버 인스턴스에 대해 새로운 init을 시작한다. 운영체제 가상화와 다른 가상화 기법은 참고자료 절을 참조하기 바란다.
리눅스 커널 관점에서 MAC와 규칙 기반 접근 통제는 상대적으로 새롭다. LSM 프레임워크 도입 이후에 새로운 보안 모듈이 등장했다. 프레임워크 개선에 덧붙여, 보안 모듈을 층층이 쌓아 리눅스 보안 요구를 최대한 충족하도록 여러 보안 모듈을 공존하게 만들었다. 또한 운영체제 보안 연구 결과 새로운 접근 통제 기법이 계속해서 등장할 것이다. LSM과 SELinux가 현재 제공하는 세부 내역이 궁금하다면 참고자료 절에 실린 기사와 논문을 읽어보기 바란다.
교육
- NSA Web site for SELinux: 여기서 풍부한 SELinux 정보를 얻자. 이 사이트는 SELinux와 관련한 기술 논문과 발표 자료는 물론이고 SELinux를 낳은 연관된 프로젝트에 대한 세부 사항을 설명한다.
- Better Networking with SCTP는 네트워크 보호에 대한 정보를 제공한다. TCP는 두 단계 핸드셰이크과 관련해 알려진 문제점이 있다. 이와 관련해 DoS 공격은 (외부 연결 관점에서 바라보면) 시스템 지원을 소비해 다운되게 만든다. SCTP는 세 단계 핸드셰이크라는 방식으로 이런 문제를 해결한다.
- 위키백과에서 물리적인 접근과 컴퓨터 보안 모드를 포함하는 접근 통제 기법을 멋지게 소개한다. 또한 여기서 DAC(Discretionary Access Control), MAC(Mandatory Access Control), RBAC(Role-Based Access Control)라는 세 가지 접근 통제 기법과 관련한 세부 내역을 찾을 수 있다.
- SELinux는 표준 커널 호출을 보안 호출로 변경하는 기능을 제공하는 리눅스 보안 모듈 프레임워크에 의존한다. LSM 논문은 LSM과 구현 범위에 대한 세부 사항을 설명한다.
- LSM은 원래 Fluke 마이크로커널 운영체제를 위해 개발되었던 Flask 보안 아키텍처를 일부 구현한 기술이다. Flask, Flux, Fluke에 대한 설명은 유타 대학교 웹 페이지를 찾아보기 바란다.
- 리눅스 커널에서 시스템 호출 구현에 대한 정보가 필요하면 리눅스 시스템 호출을 활용한 커널 명령(한국 developerWorks, 2008년 6월)을 읽어보자. 이 기사는 시스템 호출 구현과 함께 커널에 새로운 시스템 호출을 추가하는 방법을 설명한다. 리눅스 커널과 아키텍처에 대한 설명은 리눅스 커널 분석(한국 developerWorks, 2008년 4월)을 살펴보기 바란다.
- NSA 사이트는 입문 내용부터 설정 세부 내역까지 다루는 SELinux 정책 설정에 대한 훌륭한 소개글을 제공한다. 정책 관리는 SELinux의 가장 복잡한 측면 중 하나지만, 다행스럽게 풍부한 문서와 바로 적용 가능한 표준 설정 내용을 구할 수 있다. Tresys Technology는 SELinux 참조 정책에 대한 유용한 페이지를 제공하는데, 상당히 많은 SELinux 정보가 포함되어 있다.
- AppArmor는 LSM에 기반을 둔 또 다른 보안 모듈이다. AppArmor는 openSUSE와 Ubuntu를 포함해 여러 운영체제가 지원한다. 최근 개발자가 떠난 이후에 노벨(Novell)이 주요 개발자로 나섰다.
- architectural overview of Solaris Trusted에서(Solaris 10 운영체제 일부인) Extensions를 읽어보자. 이 논문은 보안 강화를 위한 Solaris 접근 방법에 대한 실질적인 소개 내용을 제공한다. Solaris Trusted Extensions 페이지를 보면 더 자세한 정보가 나온다.
- TrustedBSD는 (Flask 보안 아키텍처와 같은) 특정 설계 구성 요소를 통해 SELinux가 표방하는 목표를 상당수 공유한다. TrustedBSD에서 보안 구현 부분은 보안이 강화된 다윈 운영체제와 공유한다.
- 가상 리눅스(한국 developerWorks, 2007년 2월)는 운영체제 가상화를 포함한 가상화 기법에 대해 설명한다. 이 기사는 다양한 가상화 기법과 역사를 소개한다. 위키백과는 또한 다양한 구현 비교 내역을 포함해 운영체제 가상화에 대한 소개 내용을 제공한다.
- developerWorks 리눅스 영역에서 개발자를 위한 더 많은 자료를 찾아보고, 가장 인기 있는 기사와 튜토리얼을 살펴보자.
- 리눅스 팁과 리눅스 튜토리얼을 developerWorks에서 읽어보자.
- developerWorks 기술 행사와 웹 캐스트를 놓치지 말자.
제품 및 기술 얻기
- SEK for Linux 주문: DB2®, Lotus®, Rational®, Tivoli®, WebSphere®를 비롯해 리눅스용 최신 평가판 소프트웨어를 담은 두 장짜리 DVD를 구하자.
- IBM 시험판 소프트웨어: developerWorks에서 직접 내려받아 다음번 리눅스 프로젝트 개발에 활용하자.
토론
- 블로그, 포럼, 포드캐스트와 새로운 developerWorks 스페이스를 통해 developerWorks 공동체에 참여하자.
