Tuning Your SELinux Policy with Audit2allow(Audit2allow 로 SELinux 정책 튜닝하기)
2005년 8월호의 내용입니다.


Fedora 코어3엔 6개월동안 기본적으로 Security Enhanced Linux (SELinux) 를 탑재하고 있다.
SELinux는 사용자와 그룹, root가 가지는 일반적인 접근보다 휠씬 낫은 분리된 특권을 가지고 있다.
기본적인 SELinux의 설정은 몇몇 사용자에게는 쉬게 보이겠지만, 다른 사용자들은 sendmail.cf 파일이 더 쉽게 보여질것이다.(sendmail.cf 파일을 설정하는 것이 더 쉬워 보일것이다.)
여기서는 audit2allow 툴을 이용해 필요한 정책을 단계적으로 설정하는 것을 보여줄것이다.

SELinux란?

SELinux는 프로세스의 접근제어명령(Mandatory Access Controls) 억제하고, 기록하고, 탐지에 필요한 고리(hook)를 제공하는 커널 패치(2.6.0-test 시리즈에서 kernel.org의 메인커널로 흡수된)이다.
허가와 거부하는 것을 컨트롤 하는 룰은 정책으로 구성된다. 이 정책은 SELinux 프레임워크 아래 관리되는 일들을 명시한 룰들을 포함하고 있다.

전통적인(지금까지 사용되어진) 퍼미션 모델은 사용자, 그룹, unix 파일 허가로 구성되고, 이 모델은 사용자와 그룹이 파일을 읽고, 쓰고, 실행하는 것을 제어할수 있다.
하지만 SELinux는 사용자와 역활,타입으로 더 많은(다양한) 퍼미션을 제공하고 있다.

예를 들어, 전통적인 퍼미션 모델에서 특정포트(1024 포트 밑으로)를 listen 하기 위해서는 해당 프로세스에게 root 권한을 주어야 한다.
이 프로세스가 권한을 가지게 되면, root로써 모든 권한을 행할수 있게 된다.
하지만 SELinux 모델에서는 특정 포트를 특정 서버에게만 권한을 주어 접근하게 할수 있으며, 그외는 허용하지 않는다.

그럼 어떤 리눅스가 SELinux를 지원하는가?
아래 나열된 배포판을 SELinux를 지원하고 있다.

- Fedora Core 2
- Fedora Core 3
- Red Hat Enterprise Linux 4
- CentOS 4
- Debian unstable (kernel support)
- Hardened Gentoo project
- SUSE 9.x (kernel support)
- Ubuntu

그외 추가로 다른 배포판에서도 SELinux 를 지원할 수도 있다. 그외 배포판은 시스템 문서를 참조해 보자.

왜 SELinux 인가?

SELinux 사용하면 리눅스 서버의 보안을 높일수 있다.
프로세스의 제한적인(?) 콘드롤을 지정할수 있기에 취약점이 있는 소프트웨어를 많은 공격(exploit)으로 부터 막을수 있다.

예를 들어, 일반적인 데몬이 실행되고 있다면 하면.. 특정 tcp 포트를 listen하게 되고, 파일의 입력을 저장하기 위해 프로세스에게 요청하면 config 파일을 읽고 난뒤 입력되는 것의 구문을 조사하고, 소켓에게 그 결과를 반환할것이다.

전형적인 권한(퍼미션) 모델에서는 데몬은 tcp를 열기 위해 root 권한을 가지게 되고, listen 상태로 대기하게 된다. (물론 소켓생성후 root 권한을 없어지는 경우도 있지만)
일반적으로 데몬은 실행한 유저의 권한을 가지고 실행을 하게 된다.
그래서 그 사용자가 소유한 디렉토리가 있다면 어떤 파일이든 읽거나 쓸수 있게 된다. 그 유저의 권한으로 실행되는 parsing process(?) 까지도.

데몬 실행시 root 권한으로 실행을 되게 되면 root가 할수 있는 어떤 것이라도 프로세스는 할수 있다는 것이다.
이때 읽거나 쓰는데 문제가 발생한다면 사용자가 읽을수 있는 파일을 인터넷에 노출시키거나, 다른 프로세스의 파일을 덮었는 일도 있을수 있을것이다.
또는 parsing process(?)에 문제가 발생한다면, 프로세스는 특정 프로세스의 사용자 권한(원격접근이 가능한 권한을 가진)으로 실행이 되거나, 서버에 위헙이 될수 있는 명령어도 실행할수 있게 된다.

이제는 똑같은 상황을 SELinux 하에서 생각해 보자.
우선 데몬에 다른 사용자가는 허가하지 않고, 특정 tcp 포트를 열도록 정책을 설정할 것이다.
프로세스(데몬)는 절대로 root로 실행하지 않고, 허가된 타입의 특정 파일만을 읽고 쓸수 있게 될것이다.
또한 parsing process 는 특정 타입의 파일을 읽고, 쓸수만 있으며, 어떤 shell 명령어도 실행할수 없게 된다.
서버와 parser(?)는 /tmp 디렉토리(이와 비슷한 디렉토리도)밑의 파일은 읽고, 쓸수가 없게 된다.  

이처럼 SELinux를 사용하게 되면 프로그램 에러나 설정문제등으로 인해 위험이 노출되는 것을 줄일수 있다.
SELinux를 사용하더라도 시스템 업데이트나 보안에 대한 좋은 습관등은 갖추고 있어야 한다.
SELinux는 단지 시스템 안정하도록 도와주는 많은 것들중 하나일 뿐음을 잊지 말자.

안전한가?

SELinux는 메인 리눅스 커널로 흡수(포함)되었고, 많은 이들로 부터 검증을 받았다.
소스코드는 GPL로 발표(릴리즈)되었으며, 모든 코드는 검증이 가능하다.
몇몇 사용자들은 NSA가 시스템의 백도어로 SELinux를 사용할수 있다는 의문을 제기하기도 했지만, 백도어는 발견되지 않았다.

파일, 프로세스, 사용자

SELinux는 파일과 프로세스에 "보안 상태(security context)"를 구성하게 된다.
이것은 파일 시스템에서 확장 파일시스템 속성에 의해 쓴여진 파일을 말하는 것이며, 시스템의 파일시스템은 확장속성을 꼭 지원해야 한다.
페도라나 레드햇 배포판에서 ls 명령어는 새로운 옵션인 -- -Z 로 파일의 보안상태를 보여줄것이다.
예를 보자.

# ls -lZ /etc/selinux
-rw-r--r--    root    root   system_u:object_r:selinux_config_t config
drwxr-xr-x  root    root   system_u:object_r:selinux_config_t targeted

이것은 /etc/selinux 밑의 파일과 디렉토리를 출력한 것이다.
보안상태(security context)는 system_u가 사용자(user)이고, object_r은 역활(role)이고, selinux_config_t는 타입(type)을 표시한 것이다.
이처럼 사용자/역활/타입을 체크해 현재 SELinux의 정책과 비교하여 시스템에서 허가할지 거부할지를 결정하게 되는것이다.

역시 ps 명령어 사용시에는 -Z 옵션을 사용하면 해당 프로세스의 보안상태(security context)를 볼수 있다.
예를 들어 squid 웹 프록시 데몬이 특정 포트를 오픈해 놓은 상태라면(다른 사용자는 접근할수 없는 상태) 아래와 같은 결과를 볼수 있다.

# ps axZ | grep squid
user_u:system_r:squid_t          3912 ?        Ss     0:00 squid -D
user_u:system_r:squid_t          3915 ?        S      9:10 (squid) -D
user_u:system_r:squid_t          3916 ?        Ss     0:01 (unlinkd)

위에서도 squid 프로세스의 보안상태(security context)를 볼수 있다.
사용자는 user_u이고, 역활은 system_r이고, 타입은 squid_t이다.

유저는 해당 유저가 무엇을 할수 있는지 역활(role)이 지정되어 있다.
역활(role)에는 해당 유저가 웹서버를 실행하거나 ping 명령어 같은 것을 실행할수 있도록 지정할수 있다.
root로 로그인한 상태에서 id 명령어를 실행하면 아래와 같이 출력하게 된다.

# id
uid=0(root)
gid=0(root)groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
context=root:system_r:unconfined_t

역시 root도 system_r 역활과 unconfined_t 타입이라는 것을 알수 있다.

설정하기

레드햇과 페도라에서 SELinux 설정은(사용할것인지, 어떤 방식으로 실행을 할것인지를) /etc/sysconfig/selinux 파일로 한다.
다른 배포판은 경로가 틀릴것이다.
아래는 페도라3의 /etc/sysconfig/selinux 파일의 내용이다.

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#       enforcing - SELinux security policy is enforced.
#       permissive - SELinux prints warnings instead of enforcing.
#       disabled - SELinux is fully disabled.
SELINUX=enforcing
# SELINUXTYPE= type of policy in use. Possible values are:
#       targeted - Only targeted network daemons are protected.
#       strict - Full SELinux protection.
SELINUXTYPE=targeted

SELINUX 지시자 설정은 비교적 간단하다.
SELinux의 정책을 실행할것인지, 정책을 실행하는 동안 간단히 기록을 할것인지, 아니면 사용하지 않을것인지를 결정한다.
enforcing 을 입력하게 된다면, 정책이 실행될것이다.
다른 단어를 사용할 경우, 정책에서 액션을 지정하지 않았다면 프로세스는 거부를 하게 될것이다.

SELINUXTYPE 은 어떤 정책을 활성화 할것인지를 결정한다.
페도라 코어 3 에서는 두가지 정책을 선택할수 있다.(targeted와 strict)

targeted정책은 몇몇 프로세스에 관한 정책으로, 정책의 범위에서 벗어나 리스트되지 않는 것을 허가하고,
strict 정책은 대부분의 프로세스를 위한 정책으로, 명확히 허가된 것이 아닌라면 거부하게 된다.

서비스를 거의 하지 않거나, 기본설정에서 변경이 거의 없는 상태로 서비스 하는 서버라면, strict 정책을 사용하고,
그렇지 않다면 targeted 정책을 사용하는 것이 SELinux의 사용이점을 제대로 사용할수 있다.
예를 들어 targeted 정책을 사용한다면, 정책에서 지정된 프로세스들은 SELinux에 의해 감시를 받고, 그외 프로세스는 허가된다.

setenforce 명령어로 enforcing 에서 permissive 방식으로 변경할수도 있다.
setenforce 0 은 permissive 방식이고, setenforce 1은 enforcing 방식이다.
부팅시 SELinux를 비활성화 하면서 커널 명령라인에 selinux=0 를 입력하면 된다.

정책을 변경하기 위해서는 정책 소스 패키지가 꼭 있어야 한다.
페도라 코어3일 경우엔 selinux-policy-targeted-sources 와 selinux-policy-strict-sources 가 소스패키지이다.
이 패키지를 인스톨하려면 아래와 같이 명령어를 주면 된다.

# yum install selinux-policy-targeted-sources selinux-policy-strict-sources


로그기록

SELinux 로그는 프로세스가 거부 되었을때 기록을 한다.(허거되었을때도 기록이 가능하지만)
기본정책이 거부를 허가로 변경해서도 로그를 기록할수도 있다.
아래는 SELinux의 로그 기록이다.(기본적으로 /var/log/messages에 기록된다.)

kernel: audit(1114070701.193:0): avc:  denied  { read } for  pid=24216 exe=/usr/libexec/mysqld name=mysql dev=cciss/c0d0p6 ino=16408 scontext=user_u:system_r:mysqld_t tcontext=root:object_r:var_lib_t tclass=dir

로그를 분석해 보면..

우선 읽기 요구를 거부하고 있다. (denied {read})
읽기 요구를 하는 프로셋의 ID는 24216이다. (for pid=24216)
프로세스 이름은 /usr/libexec/mysqld 이고, (exe=/usr/libexec/mysql name=mysql)
액션의 타켓은 /dev/cciss/c0d0p6 장치에서 실행되고 있다.)
액션 타켓의 inode는 16408이고, (ino=16408)
프로세스의 SELinux context는 user이고, mysqld 타입이다.(scontext=user_u:system_r:mysqld_t)
읽으려고 하는 파일은 var_lib_t 타입의 루트 소유의 파일이다. (tcontext=root:object_r:var_lib_t)

SELinux의 로그 엔트리의 필드를 살펴보자.

audit(timestamp) : 이 필드는 SELinux의 검사 메세지이며, 타임 스탬프 형식으로 기록한다.
avc : SELinux 벡터 캐시 액세스를 나타나며, 거의 모든 기록은 이 캐시이다.
denied | accepted : 이 필드는 해당 액션이 허가되었는지 거부되었는지를 나타낸다. 종종 허가된 메세지를 볼수도 있다.(정책을 리로드할 경우에)
{ read | write | unlink | … } : 이 필드는 파일을 읽거나, 쓰거나, unlink하거나, 정책을 로딩하거나 등의 액션의 종류을 출력한다.
for pid=<pid> : 접근하는 액션의 프로세스 ID를 나타낸다.
exe=<executable> : 실행되는 프로세스의 경로를 나타낸다.
name=<name> : 액션을 시도하는 타켓의 이름을 나타낸다.
dev=<device> : 타켓 파일이 위치한 디바이스를 나타낸다.
ino=<inode-number> : 액션 타켓의 inode를 나타낸다.
scontext=<security context> : 프로세스의 보안상태(문맥)을 나타낸다. 사용자, 규칙, 타입을 가지고 있다.
tcontext=<target context> : 액션 타켓(파일이나 디렉토리등에 사용되는)의 보안상태(문맥)을 나타낸다.
tclass=<target class> : 타켓 오브젝트(디렉토리, 파일, 디바이스, 노드같은)의 클래스를 나타낸다.

다른 로그를 살펴보자.

kernel: audit(1114800386.039:0): avc:  granted  { load_policy } for
pid=12589 exe=/usr/sbin/load_policy
scontext=root:system_r:unconfined_t
tcontext=system_u:object_r:security_t tclass=security

위 로그는 root에 의해 정책이 리로드 되었음을 알수 있다.(아마 make load 명령어를 사용한듯)
avc가 granted 임을 기억해 두자.

다른 예를 한번 더 보자.

kernel: audit(1114800360.543:0): avc:  denied  { unlink } for
pid=12253 exe=/usr/sbin/named name=example.com dev=hda3 ino=505301
scontext=root:system_r:named_t tcontext=root:object_r:named_zone_t
tclass=file

여기서는 example.com 파일을 named가 unlink 되는 것을 거부했다는 것을 알수 있다.
그것은 /dev/hda3 에 위치하고, inode는 505301 이다.

selinux란 무엇이며, Audit2allow 로 SELinux 정책 설정하기

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다