리눅스용 시큐어 OS 모듈 ‘LIDS’ 100% 활용 ②

권한을 분리시키는 POSIX 자격보통 UNIX에 있어서 프로세스는 일반 유저 권한으로 움직이거나 특권(root 권한)으로 움직이는 2종류 밖에 없다. 프로세스에 특권이 필요한 것은 Apache 같은 서비스가 포트 1024번 미만의 이른바 ‘특권 포트’를 프로세스로 사용하는 경우나, ping이나 snort 등과 같은 미가공(raw) 소켓을 이더넷 디바이스에 대해서 오픈해 가공되지 않은 IP 데이터 트래픽을 보는 경우, 혹은 ntpd 등에서 시스템의 시각을 설정하는 경우 등이다.그러나 프로세스에 특권을 모두 주면 새로운 문제가 생긴다. 동작하고 있는 프로세스에 취약점이 있을 경우에, 불법 조작에 의해 프로세스가 가지고 있는 권한을 빼앗길 가능성이 있다. 그 결과 악의가 있는 유저에게 컴퓨터의 모든 사용 특권을 빼앗겨 버리게 된다.이 문제는 UNIX에서 상당히 오래 전부터 지적되었기 때문에, 그 해결방법으로서 ‘자격(POSIX Capability)’에 관한 제안이 POSIX(Portable Operating System Interface for UNIX:IEEE에 의한 UNIX의 표준 애플리케이션 인터페이스 규격)의 드래프트 1003.1 e에 제출되었다.이것은 특권을 더 세분화한 자격 단위로 취급할 수 있도록 하고, 프로세스에 모든 특권을 주는 것이 아니라 최소한의 자격을 주어 필요한 처리를 하자는 것이다. 이에 따라 프로세스에도 취약점이 발견되어 악용되었다고 해도, 그 프로세스가 필요로 하는 최소한의 자격밖에 빼앗기지 않기 때문에 피해의 범위를 좁히는 것이 가능하다.POSIX 자격에 관한 자세한 설명은 이하의 텍스트를 참조하기 바란다.Linux 커널 자격이 POSIX 자격은 Linux 상에서는 ‘Linux 커널 자격’으로서 커널 2.4부터 채용되고 있다. 최신의 커널 2.4.32에서는 29종류의 자격(표 1)이 정의되어 있다.또 커널 2.6.14.4에서는 새롭게 로그 감사에 사용하는 AUDIT 기능 관련의 자격 ‘29 CAP_AUDIT_WRITE’와 ‘30 CAP_AUDIT _CONTROL’의 2개가 추가되어 31종류가 되고 있다.각각의 자격에 관한 자세한 설명은 커널 소스 내에 /usr/src/ linux/include/capability.h 파일에 실려 있다. 또, ‘man capa- bilities’로서 자격에 관한 매뉴얼을 읽을 수도 있다. 대표적인 자격에 관한 설명을 표 2에 제시한다.자격 체크ntpd의 경우를 보자. ntpd는 시스템의 시각을 맞출 때(adjust), sys_adjtimex 시스템 콜을 호출한다. sys_adjtimex 시스템 콜은 /usr/src/linux/kernel/time.c 파일 내에 다음과 같이 정의되고 있다.425행째에 do_adjtimex() 함수를 호출하고 있지만, 이 함수는 같은 파일 내에서 다음과 같이 정의되고 있다.236행째에 capable() 함수에 의한 자격 체크를 실시하고 있는데, ntpd가 CAP_SYS_TIME 자격을 가지고 있지 않으면 퍼미션 체크에서 에러가 나타난다.이 외에도 프로세스가 포트 1023번 이하에서 기동할 때에 참조하는 inet_bind() 시스템 콜 내에서도 다음과 같이 433행째에 CAP_NET_BIND_SERVICE의 자격을 가지고 있는지 체크하여, 가지고 있지 않은 경우에는 퍼미션 에러가 나타나게 되어 있다.LIDS에 의한 자격의 확장LIDS에서는 원래 Linux가 가지고 있는 자격에CAP_PROTECTED: 프로세스를 kill 시그널로부터 보호한다CAP_KILL_PROTECTED: CAP_PROTECTED가 주어진 프로세스를 kill 한다CAP_HIDDEN(LIDS-1 계열만): 프로세스를 숨긴다라고 하는 특수한 자격을 추가하고 있다.▲ CAP_PROTECTEDCAP_PROTECTED가 주어진 프로세스는 kill 시그널로부터 보호받는다. 비록 관리자여도 이 자격이 주어진 프로세스는 제지할 수 없다.통상 시스템에 부정 침입한 크래커나 부정 행위를 하려고 하는 사람은 시스템 감사를 실시하고 있는 서비스를 멈추고 나서 파일 개변 등의 부정 행위를 실시한다. 도둑이 감시 카메라를 가리거나 안보이는 위치에서 나쁜 짓을 하려는 것과 같은 것이다.그러나 시스템의 로그를 취하는 syslogd나 네트워크 상의 패킷 감시를 실시하는 snort, 혹은 시스템 상의 forensic적인 감사 로그 서비스를 CAP_PROTECTED를 이용해 보호하면 불법침입한 사람은 서비스를 멈출 수 없다. 멈추려는 행위 자체도 차례로 로그에 쓰여지게 된다. 시스템을 외부 공격으로부터 지키는 것뿐만 아니라, 시스템 관리자에 대해서도 부정 행위에 대한 억제작용을 한다.▲ CAP_KILL_PROTECTEDCAP_KILL_PROTECTED는 CAP_PROTECTED와 대조적이다. 만일 감사 서비스에 CAP_PROTECTED가 부여돼 보호되었다고 해도, 시스템을 정지할 때는 감사 서비스를 정지하지 않으면 안된다. CAP_KILL_PROTECTED가 주어진 프로그램만이 CAP_PROTECTED로 보호되고 있는 서비스를 kill 할 수 있다.CAP_KILL_PROTECTED와 다음 번에 설명할 ‘스테이트’를 조합해 사용하면 시스템을 안전하게 정지시킬 수 있다.▲ CAP_HIDDEN(LIDS-1 계열만)CAP_HIDDEN를 프로세스에 주면 그 프로세스는 /proc에서 완전히 숨겨진 상태가 되고, ps 커맨드에서도 존재를 확인할 수 없게 된다.CAP_HIDDEN를 감사 서비스에 부여하는 것으로, 외부 및 내부에서는 관리자라고 해도 시스템이 감시를 하고 있는 것조차 깨닫지 못하게 하는 시스템을 만들 수 있다. ATM 등의 감시 카메라가 비밀 카메라가 되는 것이다.CAP_HIDDEN은 다양한 응용을 생각할 수 있는 우수한 자격이지만, 유감스럽게도 LIDS-2 계열에서는 사라졌다. 이것은 LSM(Linux Security Module) 형식으로 되었기 때문이다.자격의 실태자격에는- 시스템 전체를 통해 정의되는 ‘자격 접속 세트(Capability bounding set)’- 프로세스마다 설정되는 ‘프로세스 자격 세트(3종류)’의 2종류가 있어, 이것들로부터 각 프로세스가 가지는 자격이 결정된다. 각 자격 세트는 32비트열로, 각 비트열이 각각 약 30종류의 자격에 대응되고 있다.자격 접속 세트는 시스템 전체에 대해서 적용되는 자격 세트로, 최초로 프로세스를 특권으로 기동했을 때 프로세스가 가지는 자격의 디폴트 값을 결정한다. 이것은 /proc/sys/kernel/ cap-bound에 의해 정의되어, 이 값의 변경을 조정할 수 있다.프로세스 자격 세트는 PID(프로세스 ID)를 요소로 하는 구조체에 의해 정의되고 있어 각각의 PID에 대해서 이하 3종류의 자격 세트를 포함하고 있다.- 실효(effective) 자격 세트: 실제로 판정되는 자격 세트- 계승(inheritable) 자격 세트: 프로세스를 exec() 했을 때에 계승하는 자격 세트- 허가(permitted) 자격 세트: 프로세스가 가지는 것을 허가하는 자격 세트전술한 ntpd의 예라면, 실제로 CAP_SYS_TIME가 있을지 없을지 하는 처리 혹은 CAP_NET_BIND_SERVICE가 있을지 없을지 하는 처리는, 실효 자격 세트에 의해 판정된다.이러한 3종류의 프로세스 자격 세트는 프로세스가 exec() 되었을 때에 ‘자격 접속 세트’와 ‘exec() 전에 프로세스가 가지고 있던 3종류의 프로세스 자격 세트’부터 계산된다. P exec() 전의 프로세스의 자격 세트의 값 P' exec() 후의 프로세스의 자격 세트의 값 cap_bset 자격 접속 세트 F 파일 자격 세트(후술)의 값으로 하면, P'(permitted) = (P(inheritable) & F(inheritable)) |            (F(permitted) & cap_bset) P'(effective) = P'(permitted) & F(effective) P'(inheritable) = P(inheritable) [즉, 변경되지 않는다]가 됩니다.파일 자격 세트는 현재의 Linux에서는 제대로 구현할 수 없기 때문에, 현재 상태로서는 ‘프로그램을 특권으로 동작시켰을 때나, 프로그램에 set-UID 비트가 설정되어 있는 경우에 모든 자격이 ON(32비트열이 모두 1)이 된다’고 한다. 이 때문에 위의 식은 P'(permitted) = (P(inheritable) | cap_bset) P'(effective) = P'(permitted) P'(inheritable) = P(inheritable)가 된다. 현상태의 구현에서는 프로세스가 exec() 되었을 때,- 허가 자격 세트는 계승되어 온 자격 세트와 자격 접속 세트가 논리화 된다- 실효 자격 세트는 허가 자격 세트와 동일해진다- 계승 자격 세트는 변화하지 않는다가 된다.자격의 조정 방법프로세스를 최초로 기동했을 때에 디폴트가 되는 자격 접속 세트의 조정에 대해 설명한다. 32비트열에서 ON으로 하고 싶은 자격을 1, OFF로 하고 싶은 자격을 0으로 늘어놓아 정수값을 echo를 이용하여 /proc/sys/kernel/cap-bound에 쓴다.예를 들어 CAP_CHOWN와 CAP_KILL을 OFF로 하고, 남아있는 모든 것을 ON로 하는 경우에는이 되기 때문에,로 한다.한편, 프로세스 자격 세트의 조정은 libcap에 포함되는 ‘getpcap(자격 보기)’, ‘setpcap(자격 세트)’라는 커맨드를 사용할 필요가 있다.구체적으로는 root 유저에서처럼 프로세스 ID를 지정해 실효(e), 계승(i), 허가(p)를 각각 지정해 자격을 조정한다. 덧붙여 자격을 조정할 때에 프로세스 ID를 지정할 필요가 있다.이 때, 허가 자격 세트에서 한 번 자격을 삭제해 버리면 다시 덧붙일 수 없다. 예를 들어, 허가 자격 세트에서 CAP_CHOWN를 삭제해 버렸을 경우에는 그 프로세스는 두 번 다시 CAP_CHOWN를 가질 수 없게 된다. 그렇기 때문에 실제로 자격 조정은 ‘필요한 자격 이외의 것을 삭제한다’는 방식으로 가겠다.LIDS를 이용했을 경우에 자격의 조정 방법LIDS를 이용하면 프로세스의 자격을 보다 직감적으로 조정할 수 있게 된다.우선, 자격 접속 세트이다. LIDS에서는 LIDS의 설정 파일이 들어가는 /etc/lids 디렉토리 이하에 ‘lids.[스테이트].cap’ 파일을 둔다. 스테이트에 관해서는 다음 번에 설명한다.예로서 통상의 시스템 운용 시에 사용되는 ‘lids.postboot. cap’ 파일을 보자.각각의 자격의 좌측에 ‘+’, ‘-’가 붙어 있다. ‘+’, ‘-’는 그 자격을 자격 접속 세트로 ‘ON’, ‘OFF’ 한다는 의미가 된다. 이와 같이 자격 접속 세트의 설정이 매우 알기 쉬워진다.또, 각 프로세스에게 주는 자격 세트의 조정도 간단하게 되어 있다. LIDS를 이용하면 실효, 계승, 허가의 자격 세트를 특별히 의식하지 않고 실시할 수 있기 때문에, 설정이 보다 간단해진다. 설정은 필요한 자격을 필요한 프로세스에게 주는 방법인 것이다.구체적으로는 ‘lidsconf’ 커맨드를 이용하여라고 지정한다. 실제의 실효 자격 세트는 위와 같이 부여한 자격과 자격 접속 세트의 논리합이 된다.지금까지 LIDS의 특징의 하나인 ‘Linux 커널 자격’에 대해 설명했다. 이것은 프로세스에 특권을 주는 것이 아니라, 특권을 세분화한 필요 최소한의 자격을 주는 것으로, 만일 취약점이 악용되어도 특권을 빼앗기지 않게 하게 하는 것이다.시큐리티 강도와 시스템 동작의 상반지금까지 살펴본 것처럼 LIDS에서는 ACL과 자격을 이용하여 시스템을 보호하고 있다. 이것으로 보호를 철저히 하면 시스템이 무척이나 견고해지는 반면, 설정해야 하는 ACL이나 자격의 수가 많아져 결과적으로 시스템의 쓰기가 나빠지는 문제가 있다. 예를 들어 설명한다.그림 3과 같이 시스템 전체가 READONLY로 보호되고 있다고 가정한다. 프로그램이 기동할 경우 /tmp 디렉터리에 임시 파일을 작성/소거하고, /var/run 디렉터리에 PID 파일을 작성한다고 하자. 첫 회에서 설명한 것처럼, 이 경우에는 ACL을 이용하여 특정 프로그램만 /tmp 디렉터리와 /var/run 디렉터리에 쓸 수 있도록 설정한다.그러나 그 프로그램이 악용되었을 경우에는 /tmp 디렉터리나 /var/run 디렉터리에 기입을 허가해 버리게 되어, 결과적으로 /tmp 디렉터리 아래에 악의가 있는 바이너리가 놓여지는 등, 전체의 시큐러티가 떨어질 가능성이 있다.또, /etc/init.d 이하의 기동 스크립트를 DENY로 하여 프로그램의 불법 기동이나 정지를 방해할 수 있지만, 이것도 항상 DENY로 해 버리면, 시스템을 기동하고 서비스를 시작할 때나 시스템을 종료 할 때, 정상적인 동작이 불가능하다.이와 같이 시스템의 시큐러티 강도를 올리려고 하면, 시스템의 기동이나 정지가 잘 되지 않는 일이 있다. 그러나 기동이나 정지가 잘 되도록 설정을 하면, 결과적으로 시큐러티 강도가 약해질 가능성이 있다.LIDS에서는 이러한 문제에 대한 해답으로 스테이트를 준비하고 있다. 그럼 스테이트에 대해 살펴보기로 하자.스테이트에 관하여이것은 시스템을 BOOT 스테이트, POSTBOOT 스테이트, SHUTDOWN 스테이트로 나누어 각각의 스테이트마다 다른 ACL/자격을 설정할 수 있도록 하자는 것이다. 시스템의 스테이트는 그림 4와 같이 이동한다.BOOT 스테이트시스템이 기동하고 LIDS가 초기화된 상태에서 ‘lidsadm -I’ 커맨드(‘커널 봉인’을 실시하는 커맨드)를 실행하기까지다. 이 BOOT 스테이트에서, 시스템에서 필요로 하는 서비스 등을 기동하거나 필요한 모듈을 로드하거나 한다.POSTBOOT 스테이트커널을 봉인한 후의 스테이트이다. 시스템을 이 스테이트로 한 상태에서 통상 운용이 실행된다. 커널을 봉인하면 LKM (Loadable Kernel Module)에 의한 커널로 모듈의 로드가 불가능하다. 이에 따라, LKM를 악용하는 root 킷의 침입을 막을 수 있다.SHUTDOWN 스테이트‘lidsadm -S -- +SHUTDOWN’ 커맨드를 실행하면, 시스템이 SHUTDOWN 스테이트가 된다. 이름대로 시스템을 이 SHUTDOWN 스테이트로 하고나서 ‘shutdown’ 커맨드에서 실제의 시스템 종료나 재기동을 실시한다.이러한 스테이트마다 다른 ACL/자격을 설정할 수 있다. 방금 전과 같은 예에서는- BOOT 스테이트에서는 시스템 모든 것을 READONLY로 하고, 프로그램이 /tmp나/var/run 디렉터리에 기입이나 삭제를 할 수 있는 ACL를 설정한다- POSTBOOT 스테이트에서는 시스템 전부가 예외 없이 READONLY가 된다- SHUTDOWN 스테이트에서는 시스템 전부를 READONLY로 하고, 프로그램이 /tmp나/var/run 디렉터리에 기입이나 삭제를 할 수 있는 ACL를 설정한다로서 통상 운용은 POSTBOOT 스테이트에서 실시되도록 하면, 만일 통상 운용 중에 프로그램이 악용되었다고 해도 시스템에 영향을 미칠 위험성이 적어진다.이제 실제로 LIDS가 들어간 시스템을 다루고 싶어진 독자도 있을지 모르겠다. LIDS-JP에서는 LIDS를 인스톨 한 VMware 이미지가 www.selinux.gr.jp/LIDS-JP/vmware/에 준비되어 있다. 지금까지 설명한 LIDS의 효과를 체험해 볼 수 있을 것이다.다음 호에는 본 연재의 목적인 Linux가 동작하고 있는 임베디드 기기 상에서 LIDS를 사용하기 위한 BusyBox 문제의 해결 방법을 제안한다.쪹 연재순서리눅스용 시큐어 OS 모듈 ‘LIDS’ 100% 활용1회 임베디드 제품의 시큐리티 위험과 액세스 제어2회 권한을 최소화시키는 리눅스 커널 자격3회 BusyBox를 사용한 임베디드 기기에서 LIDS 활용(주)이랜서(주)이랜서는 한국과 미국, 홍콩, 일본, 중국 등의 글로벌 네트워크를 갖추고 있으며 국내 최고의 PJT와 Talent를 보유하고 있다. 이를 기반으로 기업에 최고의 토털 솔루션을 제공하고, 선진 아웃소싱 문화를 선도하고 있다. 연간 300여 개의 대기업 프로젝트를 진행하고 있으며, 33만 명의 국내 인력과 홍콩, 인도, 일본, 말레이시아 등 국외에 6만 명의 인력을 보유하고 있다.※ ㈜이랜서 및 eLancer는 주식회사 이랜서의 등록 상표입니다.
이 기사를 공유합니다
저작권자 © 테크월드뉴스 무단전재 및 재배포 금지