Last Updated on 2월 28, 2024 by Jade(정현호)
SELinux
SELinux(Security-Enhanced Linux) 는 관리자가 시스템 액세스 권한을 효과적으로 제어할 수 있게 하는 Linux 시스템용 보안 아키텍처입니다. 이는 원래 미국 국가안보국(United States National Security Agency, NSA)이 LSM(Linux Security Module)을 사용하여 Linux 커널에 대한 일련의 패치로 개발한 것입니다.
SELinux는 2000년에 오픈소스 커뮤니티에 릴리스되어 2003년에 업스트림 Linux 커널로 통합되었습니다.
SELinux는 시스템의 애플리케이션, 프로세스, 파일에 대한 액세스 제어에 관여되며 SELinux 에 액세스할 수 있는 대상을 정하는 룰 세트인 보안 정책을 사용하여 정책에서 허용된 액세스를 실행하는 보안 모듈입니다.
시스템 환경
OS : CentOS 7.9
Nginx : 1.19.6
PHP : 8.0.2
SELinux Audit 로그 내역
PHP 7.4 에서 8.0.2 로 변경 테스트 진행 중 설치 완료 후 phpinfo() 를 확인 과정에서 500 internal server error 가 발생하였습니다. Nginx 와 php-fpm 등의 설정에서는 특이 사항이 없었기에 결국 SELinux 로그 를 확인하게 되었습니다.
SELinux Audit 로그 내역
최근 사용하는 리눅스 시스템에서는 SELinux 를 Enable 한 상태로 사용 중이다 보니 예상되지 않는 곳에서의 에러는 상당수가 SELinux 에 denied 되어서 문제가 발생되는 경우가 많았습니다. 그래서 이번에도 SELinux Audit 를 확인하였고 역시나 SELinux 에서의 차단된 내역을 확인할 수 있었습니다.
참고로 이전에 SELinux 에 의한 문제 발생은 아래 포스팅을 참조하시면 됩니다.
audit.log
먼저 확인해본 로그는 SELinux 로그인 audit.log 였으며 에러가 발생하는 시점에 발생되는 내역은 아래와 같습니다 php-fpm 커맨드에서 avc: denied { execute } 내용이 명확히 확인되고 있으며 dev="tmpfs" 라는 내용과 httpd_tmpfs_t 등의 주요 내용이 확인됩니다.
(가로 사이즈 조절을 위해서 개행 되어 편집 되어있습니다)
[root]# cd /var/log/audit/audit.log <...중략...> type=AVC msg=audit(1612974836.458:658): avc: denied { execute } for pid=9999 comm="php-fpm" path=2F6465762F7A65726F202864656C6574656429 dev="tmpfs" ino=34728 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_tmpfs_t:s0 tclass=file permissive=0 type=SYSCALL msg=audit(1612974836.458:658): arch=c000003e syscall=10 success=no exit=-13 a0=48bc1000 a1=6400000 a2=5 a3=1 items=0 ppid=9993 pid=9999 auid=4294967295 uid=997 gid=994 euid=997 suid=997 fsuid=997 egid=994 sgid=994 fsgid=994 tty=(none) ses=4294967295 comm="php-fpm" exe="/opt/remi/php80/root/usr/sbin/php-fpm" subj=system_u:system_r:httpd_t:s0 key=(null) type=PROCTITLE msg=audit(1612974836.458:658): proctitle=7068702D66706D3A20706F6F6C20777777 type=ANOM_ABEND msg=audit(1612974836.458:659): auid=4294967295 uid=997 gid=994 ses=4294967295 subj=system_u:system_r:httpd_t:s0 pid=9999 comm="php-fpm" reason="memory violation" sig=11 <...중략...>
audit2why
그 다음으로는 에러가 발생한 사유 등을 더 자세하게 확인하기 위하여 audit2why 를 수행하였습니다.
Missing type enforcement (TE) allow rule 메세지로 보았을 때 이번에도 정책 룰이 없기 때문에 발생된 것으로 확인됩니다.
[root]# audit2why < /var/log/audit/audit.log type=AVC msg=audit(1612974836.458:658): avc: denied { execute } for pid=9999 comm="php-fpm" path=2F6465762F7A65726F202864656C6574656429 dev="tmpfs" ino=34728 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_tmpfs_t:s0 tclass=file permissive=0 Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access.
audit2allow
audit2allow -a 명령어를 통해서 해결 가능한 룰이나 명령어 정보를 알아볼 수 있으며 수행하였을 때 명령어는 없었으며 추가가 필요한 정책(권한)의 목록만 확인할 수 있었습니다 명령어로 권한부여가 가능하면 명령어에 대한 정보도 제공됩니다
예시 : #!!!! Fix with $ restorecon -R -v /var/lib/mysql/ibdata1
[root]# audit2allow -a #============= httpd_t ============== allow httpd_t httpd_tmpfs_t:file execute; allow httpd_t postfix_etc_t:file read; allow httpd_t self:capability sys_ptrace;
semodule 를 통한 정책 추가
semodule 를 통해 생성한 정책을 추가할 수 있습니다. 그 전에 위에서 추가해야 할 정책을 포함하여 te 파일의 작성이 필요 합니다(type enforcement (TE))
te 파일 작성
아래는 위의 3개 정책 외 추가적으로 SELinux 에서 차단이 되는 정책을 같이 반영하기 위해서 포함된 내역입니다. nginx-passenger.te 파일을 만들어서 아래 내용을 입력하면 됩니다.
[root]# vi nginx-passenger.te module nginx-passenger 1.0; require { type var_run_t; type user_home_dir_t; type httpd_t; type user_home_t; type httpd_tmp_t; type httpd_tmpfs_t; type passenger_exec_t; type postgresql_port_t; type httpd_log_t; type httpd_sys_content_t; type postfix_etc_t; type var_log_t; type root_t; type etc_runtime_t; type fusefs_t; type default_t; type http_cache_port_t; type unreserved_port_t; type unconfined_t; type admin_home_t; type system_mail_t; type httpd_sys_rw_content_t; class process execmem; class capability { fowner sys_resource fsetid sys_ptrace }; class tcp_socket name_connect; class shm { associate getattr read unix_read unix_write write destroy }; class file { execute setattr read create execute_no_trans write ioctl open append map }; class capability2 block_suspend; class process ptrace; class process setrlimit; class file { ioctl write execute setattr read rename create open execute_no_trans getattr lock}; class lnk_file { read getattr write open }; class dir { write search read create open getattr add_name }; } #============= httpd_t ============== allow httpd_t httpd_tmp_t:file execute; allow httpd_t httpd_tmpfs_t:file execute; allow httpd_t httpd_log_t:file setattr; allow httpd_t passenger_exec_t:dir { search getattr }; allow httpd_t self:capability sys_ptrace; allow httpd_t self:process ptrace; allow httpd_t self:process execmem; allow httpd_t self:capability2 block_suspend; allow httpd_t user_home_t:file { execute execute_no_trans read open write }; allow httpd_t var_run_t:file { read write }; allow httpd_t postfix_etc_t:file { read getattr open }; allow httpd_t root_t:dir write; allow httpd_t root_t:dir add_name; allow httpd_t root_t:file create; allow httpd_t root_t:file { open read write }; allow httpd_t root_t:file lock; allow httpd_t etc_runtime_t:file write; allow httpd_t fusefs_t:file { getattr read open write }; allow httpd_t fusefs_t:dir { read write }; allow httpd_t user_home_t:lnk_file { read write open }; allow httpd_t default_t:lnk_file { read write open }; allow httpd_t default_t:file { read write open }; allow httpd_t http_cache_port_t:tcp_socket name_connect; allow httpd_t unreserved_port_t:tcp_socket name_connect; allow httpd_t admin_home_t:file getattr; allow system_mail_t httpd_sys_rw_content_t:file { read write }; allow httpd_t unconfined_t:shm { unix_read unix_write associate getattr read write destroy }; allow httpd_t self:process setrlimit; allow httpd_t var_log_t:file open; allow httpd_t root_t:file map;
checkmodule
위에서 작성한 te 파일을 통해 checkmodule 를 수행을 합니다 정상적으로 수행된다면 아래와 같이 수행될 것입니다.
[root]# checkmodule -M -m -o nginx-passenger.mod nginx-passenger.te checkmodule: loading policy configuration from httpdtmpexec.te checkmodule: policy configuration loaded checkmodule: writing binary representation (version 19) to httpdtmpexec.mod
package 생성 및 허용 정책 적용
semodule_package 과 semodule 명령어를 이용하여 허용 정책을 추가합니다. 특별한 메세지 없이 종료된다면 정상적으로 수행된 것입니다. 문제가 있다면 에러가 발생되게 됩니다.
[root]# semodule_package -o nginx-passenger.pp -m nginx-passenger.mod [root]# semodule -i nginx-passenger.pp
확인
여기까지 진행 후 다시 한번 phpinfo 를 체크하였고 audit.log 에서 추가적인 차단 내용 없이 페이지 로드가 정상적으로 수행되는 것을 확인하였습니다.
Reference
Reference link
github.com/nginx-passenger.te [Link]
관련된 다른 글
Principal DBA(MySQL, AWS Aurora, Oracle)
핀테크 서비스인 핀다에서 데이터베이스를 운영하고 있어요(at finda.co.kr)
Previous - 당근마켓, 위메프, Oracle Korea ACS / Fedora Kor UserGroup 운영중
Database 외에도 NoSQL , Linux , Python, Cloud, Http/PHP CGI 등에도 관심이 있습니다
purityboy83@gmail.com / admin@hoing.io