티스토리 뷰

OS/Linux

[Linux] SELinux 정책설정

림국 2019. 10. 4. 19:12

[Linux] SELinux 정책설정

 

SELinux 테스트 중 정리가 잘되어 있는 글을 발견하여 퍼오게 되었다. selinux 관련하여 검색하면 한국어로 되어있는 페이지가 많이 없었으나 이글을 통해 실제로 이해하는데 도움이 많이 되었다.

 

출처 : http://www.codeforum.net/wiki/doku.php?id=selinux

1. SELinux(Security-Enhanced Linux) 란?

SELinux 란 미 국가 보안국 (U.S. National Security Agency)이 오픈소스커뮤니티에 릴리즈한 Linux의 보안 강화 버전(코드 포함)으로서 리눅스 보안 모듈 구조체(Linux Security Modules(LSM) framework)를 이용하여 리눅스 커널에 의무 접근 제어(Mandatory Access Control - MAC)를 구현하는 것이다. Fedora Core3부터 기본으로 적용되기 시작하였고, 현재 대부분의 최신 리눅스 배포판에서 지원되고있다.

SELinux에 대한 이해를 돕기위해서 DAC, MAC를 잠깐 이야기 해보자.

표준 리눅스 보안은 Discretionary Access Control - DAC 모델을 따른다. DAC 모델에서, 파일과 자원에 대한 결정권은 오직 해당 객체(objects)의 사용자(user id)에게 있고 소유권(ownership)에 따라 이뤄진다. 각 사용자와 그 사용자에 의해 실행된 프로그램은 자기에게 할당된 객체에 대해 전적으로 자유재량권을 갖는다. 이러한 상황에서는, 악의 있는 일반 혹은 루트 사용자(예로, setuid와 setgid)가 실행시킨 결함이 있는 소프트웨어를 통해 주어진 객체로 원하는 어떠한 일을 해도 막아낼 방법이 없으며 보안 정책을 시스템 전체에 걸쳐 시행되도록 할 방법이 없다.

반면에 SELinux하에서 MAC는 모든 주체(subjects - 사용자, 프로그램, 프로세스)와 객체(파일, 디바이스)에 대해서 국부적으로 허가(granular permissions)해 줄 수 있다. 응용프로그램에서 불필요한 부분은 제외하고 오직 필요한 기능에 대해서만 사용 권한을 안전하게 부여하는것이 가능하다.

SELinux는 모든 주체 (사용자, 프로그램, 프로세스) 및 객체 (파일과 장치)에 각각 다른 권한을 부여할 수 있게 해줍니다. 따라서 사용자는 한 응용 프로그램에게 그 프로그램이 제대로 작동하는데 필요한 권한만 안전하게 부여할 수 있다.

 

2 . SELinux 정책이란 무엇인가?

SELinux 정책은 사용자, 프로그램, 프로세스 그리고 이들의 동작 대상인 파일과 디바이스를 포함한 시스템 전체, 즉, 모든 주체와 객체에 대한 접근 허가(access permissions)를 포함한 패키지를 이야기한다. 페도라에서 사용가능한 정책 패키지는 strict , targeted 두가지가 있다.

페도라코어에서 SELinux 정책으로 strict policy 를 적용함으로 인해서 다양한 사용자들이 많은 문제점을 일으킴으로 인해서(일반사용자들이 SELinux를 사용하기 위해서는 수준높은 전문기술이 필요하다) 현재 RHEL4 에서는 보다 완화된 정책패키지 targeted poicy 가 설치시 기본으로 제공된다.

targeted policy는 자주 문제시되는 부분들만 우선적으로 적용시키고, 나머지는 표준 리눅스 보안과 동일하게 운영되도록 적용한 정책이다.

현재, targeted policy 에서는 dhcpd, httpd(apache.te), named, nscd, ntpd, portmap, snmpd, squid 그리고 syslogd 데몬에 대해서 관리한다. 이 데몬들에 대한 정책 파일은 /etc/selinux/targeted/src/policy/domains/program에서 찾을 수 있다.

ReadHat Enterprise Linux 5(CentOS 5)에서는 Policy Module(Customizing SELinux Policy) 형태의 정책 변경 도구를 제공하고 있다.

 

 

ls 또는 ps 의 Z 옵션

[root@ProjectS ~]#ls -Z
drwxr-xr-x root root user_u:object_r:user_home_t 8_install_DokuWiki
drwxr-xr-x root root user_u:object_r:user_home_t 8_install_textcube
drwxr-xr-x root root system_u:object_r:user_home_t 8_install_trac
drwxr-xr-x root root system_u:object_r:file_t 9_Tbackup
drwxr-xr-x root root system_u:object_r:user_home_t 9_Tmount
-rw------- root root system_u:object_r:user_home_t anaconda-ks.cfg
-rw------- root root user_u:object_r:user_home_t dead.letter
-rw-r--r-- root root root:object_r:user_home_t install.log
-rw-r--r-- root root root:object_r:user_home_t install.log.syslog
-rw------- root root user_u:object_r:user_home_t mbox
[root@ProjectS ~]#

[root@ProjectS ~]#ps -Z
LABEL PID TTY TIME CMD
user_u:system_r:unconfined_t 13761 pts/0 00:00:00 su
user_u:system_r:unconfined_t 13762 pts/0 00:00:00 bash
user_u:system_r:unconfined_t 13875 pts/0 00:00:00 ps
[root@ProjectS ~]#


 

sestatus

setenforce

setsebool

setsebool 사용법

 


[root@ProjectS ~]#
setsebool --help
Usage: setsebool [ -P ] boolean value | bool1=val1 bool2=val2...
[root@ProjectS ~]#


 

FTP 데몬에 대한 사용가 계정 HOME directory 접근 허용 

현상 : ftp client로 login시 인증 성공 후 해당 계정 home 디렉토리로 자동 이동 중 change directory error 발생 
참조 URL : http://kldp.org/node/54059

페도라 코어 4 까실때 SELinux 설정하셨나요? 그렇다면 디폴트로 사용자의 home 디렉토리에 쓰기를 막아놨을겁니다. SELinux 설정에서 FTP 부분을 변경하시면 될것 같습니다. 변경방법은 콘솔상에서 하는방법과 x윈도우에서 변경하는 방법이 있습니다.

콘솔상에서 변경하시려면


[root@ProjectS ~]#
setsebool -P ftp_home_dir 1
[root@ProjectS ~]#
service vsftpd restart

와 같이 home 디렉토리의 읽고쓰기를 1(True)로 변경하시고 vsftpd를 재시작 하시면 됩니다.

x윈도우 상에서는 데스크탑 → 시스템 설정 → 보안 수준에 가셔서 SELinux 텝에 들어가시면 정책 수정중에 FTP 라고 있습니다.

그곳의 삼각형을 클릭하시면 아래로 3개의 정책이 더 나오는데 Ftp의 사용자 홈디렉토리 읽고/쓰기 허가 를 클릭 하시면 됩니다.

또는 FTP에 관하여 SELinux 정책을 아예 적용하지 않는 옵션을 설정하셔도 됩니다. 콘솔 상에서는


[root@ProjectS ~]#
setsebool -P ftpd_disable_trans 1

혹은 정책 수정중에 Disable SELinux protection for ftpd daemon 을 클릭 하시면 됩니다.

p.s. SELinux 설정에 보시면 다른 서비스들도 기본으로 많이 막혀 있습니다.

chcon


[root@ProjectS]#
chcon --help
Usage: chcon [OPTION]... CONTEXT FILE...
or: chcon [OPTION]... [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE...
or: chcon [OPTION]... --reference=RFILE FILE...
Change the security context of each FILE to CONTEXT.
-c, --changes like verbose but report only when a change is made
-h, --no-dereference affect symbolic links instead of any referenced file
(available only on systems with lchown system call)
-f, --silent, --quiet suppress most error messages
--reference=RFILE use RFILE's group instead of using a CONTEXT value
-u, --user=USER set user USER in the target security context
-r, --role=ROLE set role ROLE in the target security context
-t, --type=TYPE set type TYPE in the target security context
-l, --range=RANGE set range RANGE in the target security context
-R, --recursive change files and directories recursively
-v, --verbose output a diagnostic for every file processed
--help display this help and exit
--version output version information and exit
[root@ProjectS]#



[root@ProjectS]#
chcon -R -t httpd_sys_content_t box/
[root@ProjectS]#
ls -lZ
drwxr-xr-x apache apache system_u:object_r:httpd_sys_content_t box


semanage

semanage 사용법 

  • Apache의 추가 Listen port 확장


[root@ProjectS conf.d]#
semanage --help
semanage {login|user|port|interface|fcontext|translation} -l [-n]
semanage login -{a|d|m} [-sr] login_name
semanage user -{a|d|m} [-LrRP] selinux_name
semanage port -{a|d|m} [-tr] [ -p protocol ] port | port_range
semanage interface -{a|d|m} [-tr] interface_spec
semanage fcontext -{a|d|m} [-frst] file_spec
semanage translation -{a|d|m} [-T] level
Primary Options:
-a, --add Add a OBJECT record NAME
-d, --delete Delete a OBJECT record NAME
-m, --modify Modify a OBJECT record NAME
-l, --list List the OBJECTS
-h, --help Display this message
-n, --noheading Do not print heading when listing OBJECTS
Object-specific Options (see above):
-f, --ftype File Type of OBJECT
"" (all files)
-- (regular file)
-d (directory)
-c (character device)
-b (block device)
-s (socket)
-l (symbolic link)
-p (named pipe)
-p, --proto Port protocol (tcp or udp)
-P, --prefix Prefix for home directory labeling
-L, --level Default SELinux Level (MLS/MCS Systems only)
-R, --roles SELinux Roles (ex: "sysadm_r staff_r")
-T, --trans SELinux Level Translation (MLS/MCS Systems only)
-s, --seuser SELinux User Name
-t, --type SELinux Type for the object
-r, --range MLS/MCS Security Range (MLS/MCS Systems only)


[root@ProjectS conf.d]#
service httpd restart
httpd 를 정지 중: [ OK ]
httpd (을)를 시작 중: [Sun Dec 30 18:28:12 2007] [warn] PassEnv variable LD_LIBRARY_PATH was undefined
[Sun Dec 30 18:28:12 2007] [warn] PassEnv variable LD_LIBRARY_PATH was undefined
httpd: Could not reliably determine the server's fully qualified domain name,
using 218.158.45.145 for ServerName
(13)Permission denied: make_sock: could not bind to address [::]:8888
(13)Permission denied: make_sock: could not bind to address 0.0.0.0:8888
no listening sockets available, shutting down
Unable to open logs
[실패]


[root@ProjectS conf.d]#semanage port -a -t http_port_t -p tcp 8888
[root@ProjectS conf.d]#semanage port -l
SELinux Port Type Proto Port Number
http_cache_port_t tcp 3128, 8080, 8118
http_cache_port_t udp 3130
http_port_t tcp 8888, 80, 443, 488, 8008, 8009, 8443

audit2allow

  • /var/log/audit/audit.log 및 /var/log/messages, /var/log/dmesg 의 AVC denied 로그를 어떤 타입과 적절한 권한이 필요한지 번역해서 보여준다.


[root@ProjectS ~]#
audit2allow --help
usage: audit2allow [options]
options:
--version show program's version number and exit
-h, --help show this help message and exit
-a, --audit read input from audit log - conflicts with -i
-d, --dmesg read input from dmesg - conflicts with --audit and
--input
-i INPUT, --input=INPUT
read input from <input> - conflicts with -a
-l, --lastreload read input only after the last reload
-r, --requires generate require statements for rules
-m MODULE, --module=MODULE
set the module name - implies --requires
-M MODULE_PACKAGE, --module-package=MODULE_PACKAGE
generate a module package - conflicts with -o and -m
-o OUTPUT, --output=OUTPUT
append output to <filename>, conflicts with -M
-R, --reference generate refpolicy style output
-v, --verbose explain generated output
-e, --explain fully explain generated output
-t TYPE, --type=TYPE only process messages with a type that matches this
regex
--perm-map=PERM_MAP file name of perm map
--interface-info=INTERFACE_INFO
file name of interface information
--debug leave generated modules for -M
[root@ProjectS ~]#

[root@ProjectS ~]#
audit2allow -a
#============= ftpd_t ==============
allow ftpd_t home_root_t:dir search;
#============= httpd_sys_script_t==============
allow httpd_sys_script_tfile_t:dir { search getattr };
allow httpd_sys_script_tfile_t:file { read getattr };
allow httpd_sys_script_tuser_home_t:dir { search getattr };
allow httpd_sys_script_tuser_home_t:file { read getattr };
#============= httpd_t ==============
allow httpd_t port_t:tcp_socket name_bind;
allow httpd_t self:tcp_socket name_bind;
allow httpd_t user_home_t:dir { read search getattr };
allow httpd_t user_home_t:file { read write getattr };
#============= system_mail_t ==============
allow system_mail_t httpd_t:file read;
#============= unconfined_t ==============
allow unconfined_t httpd_sys_script_t:dir relabelto;
allow unconfined_t httpd_sys_script_t:file relabelto;
[root@ProjectS ~]#


  • /var/log/audit/audit.log를 직접 보면 다음과 같다.(빨간색 부분을 주목하자.)

실예 : /home/svn/publicsvn/test2/format의 Open permission denied(-13) 발생에 대한 /var/log/audit/audit.log분석

 

type=AVC msg=audit(1199086710.853:174): avc: denied { search } for pid=4166 comm="trac.cgi" name="/"dev=hdc1 ino=2 scontext=user_u:system_r:httpd_sys_script_t:s0 tcontext=system_u:object_r:file_t:s0tclass=dir 
type=SYSCALL msg=audit(1199086710.853:174): arch=40000003 syscall=196 success=no exit=-13 a0=9a58438 a1=bfd0043c a2=6fcff4 a3=8171 items=0 ppid=4108 pid=4166 auid=500 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) comm="trac.cgi" exe="/usr/bin/python" subj=user_u:system_r:httpd_sys_script_t:s0 key=(null)

  • 대충 해석하면 /usr/bin/python 프로세스에 의한 명령 trac.cgi가 user_u:system_r:httpd_sys_script_t CONTEXT를 가지고 대상인 system_u:object_r:file_t CONTEXT를 갖는 dir ”/” (실예에서 이것은 /home/svn을 지칭하는 것이었다. ^^; 뭘 기준으로 한것인지 모르니 이거 사람잡을만 하다)에 접근하다가 avc의 search 권한 불일치로 거부당하여 값 -13 에러를 리턴하고 실패했다는 내용이다.

  • 따라서 이에대한 해결책으로 /home/svn에 httpd_sys_script_t 의 읽기,쓰기 권한에 부합하는 httpd_sys_script_rw_t 를 부여함으로서 바로 위 에러에 대한 문제 해결이 가능하다.(전체 문제 해결을 위해서는 svn부터 시작하여 /home/svn/publicsvn/test2/format 까지 전 경로에 거처 httpd_sys_script_rw_t를 부여하여야 한다)

  • 다음은 실예에서 문제되었던 것을 해결하기 위한 일련의 과정이다.


[root@ProjectS /]#
cd home
[root@ProjectS home]#ls -lZ
drwxr-xr-x root root system_u:object_r:file_t svn
[root@ProjectS home]#
vi /var/log/audit/audit.log

type=AVC msg=audit(1199086710.853:174): avc: denied { search } for pid=4166 comm="trac.cgi" name="/"dev=hdc1 ino=2 scontext=user_u:system_r:httpd_sys_script_t:s0 tcontext=system_u:object_r:file_t:s0tclass=dir 
type=SYSCALL msg=audit(1199086710.853:174): arch=40000003 syscall=196 success=no exit=-13 a0=9a58438 a1=bfd0043c a2=6fcff4 a3=8171 items=0 ppid=4108 pid=4166 auid=500 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) comm="trac.cgi" exe="/usr/bin/python" subj=user_u:system_r:httpd_sys_script_t:s0 key=(null)


[root@ProjectS home]#
chcon -t httpd_sys_script_rw_t svn
[root@ProjectS home]#ls -lZ
drwxr-xr-x root root system_u:object_r:httpd_sys_script_rw_t svn
[root@ProjectS home]#
vi /var/log/audit/audit.log

type=AVC msg=audit(1199086844.720:178): avc: denied { search } for pid=4184 comm="trac.cgi" name="publicsvn" dev=hdc1 ino=9535489 scontext=user_u:system_r:httpd_sys_script_t:s0tcontext=user_u:object_r:file_t:s0 tclass=dir
type=SYSCALL msg=audit(1199086844.720:178): arch=40000003 syscall=5 success=no exit=-13 a0=85f2618 a1=8000 a2=1b6 a3=8000 items=0 ppid=4119 pid=4184 auid=500 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) comm="trac.cgi" exe="/usr/bin/python" subj=user_u:system_r:httpd_sys_script_t:s0 key=(null)


[root@ProjectS home]#
cd svn
[root@ProjectS svn]#ls -lZ
-rwxr-xr-x root root user_u:object_r:file_t publicsvn
[root@ProjectS svn]#chcon -t httpd_sys_script_rw_t publicsvn
[root@ProjectS svn]#ls -lZ
drwxr-xr-x root root user_u:object_r:httpd_sys_script_rw_t publicsvn
[root@ProjectS svn]#
vi /var/log/audit/audit.log

type=AVC msg=audit(1199086912.148:180): avc: denied { search } for pid=4199 comm="trac.cgi" name="test2"dev=hdc1 ino=9535515 scontext=user_u:system_r:httpd_sys_script_t:s0 tcontext=user_u:object_r:file_t:s0tclass=dir
type=SYSCALL msg=audit(1199086912.148:180): arch=40000003 syscall=5 success=no exit=-13 a0=90fb618 a1=8000 a2=1b6 a3=8000 items=0 ppid=4110 pid=4199 auid=500 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) comm="trac.cgi" exe="/usr/bin/python" subj=user_u:system_r:httpd_sys_script_t:s0 key=(null)


[root@ProjectS svn]#
cd publicsvn/
[root@ProjectS publicsvn]#ls -lZ
drwxrwxr-x root root user_u:object_r:file_t test2
[root@ProjectS publicsvn]#chcon -t httpd_sys_script_rw_t test2
[root@ProjectS publicsvn]#cd test2
[root@ProjectS test2]#chcon -t httpd_sys_script_rw_t format
[root@ProjectS test2]#
ls -lZ
-r--rw-r-- root root user_u:object_r:httpd_sys_script_rw_t format


audit2why


[root@ProjectS ~]#
audit2why --help
audit2why: invalid option -- -
usage: audit2why [-p policy] < /var/log/audit/audit.log

semodule


[root@ProjectS audit]#
semodule --help
usage: semodule [options]... MODE [MODES]...
Manage SELinux policy modules.
MODES:
-R, --reload reload policy
-B, --build build and reload policy
-i,--install=MODULE_PKG install a new module
-u,--upgrade=MODULE_PKG upgrade existing module
-b,--base=MODULE_PKG install new base module
-r,--remove=MODULE_NAME remove existing module
-l,--list-modules display list of installed modules
Other options:
-s,--store name of the store to operate on
-n,--noreload do not reload policy after commit
-h,--help print this message and quit
-v,--verbose be verbose


[root@ProjectS audit]#
semodule -l
amavis 1.1.0
ccs 1.0.0
clamav 1.1.0
dcc 1.1.0
evolution 1.1.0
iscsid 1.0.0
mozilla 1.1.0
mplayer 1.1.0
nagios 1.1.0
oddjob 1.0.1
pcscd 1.0.0
pyzor 1.1.0
razor 1.1.0
ricci 1.0.0
smartmon 1.1.0
[root@ProjectS audit]#


Customizing SELinux Policy

웁스! 한고비 뒤 SELinux와 관련된 에러가 또 발생하였다. Trac에서 로깅을 위해 syslogd를 사용하도록 설정하였더니, 웁스 아래 그림과 같은 에러가 발생하였다.

원인은 기본적으로 httpd 데몬에서 수행된 script (httpd_sys_script_t)에서 Socket 생성하는 것이 막혀 있기 때문이었다. ( ^^; 재미있는 것은 php는 스크립트로 취급되지 않는 것 같다. php로 된 Dokuwiki는 smtp를 사용한 메일 발송에 문제가 없었었다.)

 

이것은 socket이라는 시스템의 커널 리소스에 대한 문제이기 때문에 무언가 context type을 변경해준다고 해결될 문제가 아니었다. 즉 정책 변경이 필요하게 된 것이다. 
그동만 별 영양가 없다고 생각했던 audit2allow가 드디어 빛을 발하기 시작했다. 

참고문서 : Chapter 45. Customizing SELinux Policy

SELinux Policy를 커스터마이징 하는데 있어 Red Hat Enterprise Linux 4, 5에 각각 대응하는 CentOS 4, 5의 정책 Customizing 방법이 큰 차이가 있었다. 
CentOS 4는 selinux-policy-targeted-sources 패키지를 설치하여 정책 파일들을 편집한 다음 다시 로드 하는 방식을 사용한다.

그러나 CentOS 5에서는 정책관리를 보다 커널 모듈과 같이 취급하여 Policy Module이라는 것을 사용하였다. 모듈의 install, reload, remove 등에 사용되는 명령이 semodule 이라는 것이다.

다시 위의 에러가 발생한 문제로 돌아가 문제가 발행한 프로그램은 trac.cgi라는 것이다. /var/log/audit/audit.log 의 AVC 로그중 comm=“trac.cgi” 와 관련된 AVC를 뽑고자 한다면 다음과 같이 할 수 있다.


#
grep trac.cgi /var/log/audit/audit.log | audit2allow

그동안 문제되었던 다른것 포함, audit 로그를 분석하여 그것을 allow 정책으로 변환하여 보여준다.


[root@ProjectS policy]#
grep trac.cgi /var/log/audit/audit.log | audit2allow
#============= httpd_sys_script_t==============
allow httpd_sys_script_tdevlog_t:sock_file write;
allow httpd_sys_script_tfile_t:dir { search getattr };
allow httpd_sys_script_tfile_t:file { read getattr };
allow httpd_sys_script_tself:unix_dgram_socket { write create connect };
allow httpd_sys_script_tsyslogd_t:unix_dgram_socket sendto;
allow httpd_sys_script_tuser_home_t:dir { search getattr };
allow httpd_sys_script_tuser_home_t:file { read getattr };
#
============= unconfined_t ==============
allow unconfined_t httpd_sys_script_t:file relabelto;


1차적으로 allow httpd_sys_script_t self:unix_dgram_socket { write create connect }; 이 적용되면 일차적으로 위 소켓 생성시 나는 에러를 해결할 수 있을 것이다. 기타 관련된 다른 allow도 audit 로그 분석을 통해 뽑아졌다.

이를 Policy Module로 컴파일하여 만드는 방법은 다음과 같다.


#
grep trac.cgi /var/log/audit/audit.log | audit2allow -M tracsocket

위 명령을 수행하면 현재 폴더에 tracsocket.pp 와 tracsocket.te 파일 2개가 생성된다. tracsocket.pp는 컴파일된 policy module 파일이다. tracsocket.te는 text로 된 컴파일되기 전의 소스이다.

이것을 SELinux 시스템에 적용하는 방법은


#
semodule -i tracsocket.pp

와 같이 하면 적용된다.

이렇게 한번 인스톨된 모듈의 정책은 리부팅 후에도 유지된다고 하니, install에 사용된 pp를 삭제하면 무슨일이 벌어질까?!, 아마도 커널에 로드된 정책을 포함한 전체 Policy를 별도로 저장한다면 문제가 없겠지만 커널 모듈 파일이 지워지면 커널 모듈 로딩중 에러가 나듯, pp 파일이 삭제되면 SELinux에서 Policy 모듈 로드중 에러가 나지 않을까 생각해 본다.

굳이 시간을 들여 테스트 해보픈 마음은 없다. ^^; 여튼 사용된 pp파일은 되도록 삭제나 install된 위치에서 옮기지 말도록 하자. te 파일도 같이 보관하자. 컴파일된 pp 모듈이 실제 어떤 정책을 갖는지 텍스트인 te 파일을 통해 확인할 수 있으니 말이다. 얼핏 te를 가지고 재 컴파일도 가능하다고 한것 같지만 사용법은 나중에 필요하면 알아봐야 겠다. ㅋㅋ

 

출처 : http://egloos.zum.com/forbis/v/3415796

댓글