시스템 보안 · 취약점 › A. Linux 서버 보안 설정 · 17/50편 (전체 017/450)
학습 단계: 2단계 · 설정 및 점검
실습 표기: 이 글의 명령어·출력·로그는 로컬 VMware 테스트 VM(Rocky Linux 9 / Ubuntu 22.04) 기준의 「실습 예시」이며, IP·계정·호스트명은 가상의 값입니다.
SELinux는 파일 권한(DAC)과 별개로 "이 프로세스 타입이 이 객체 타입에 이 동작을 해도 되는가" 를 정책으로 검사하는 강제 접근 통제(MAC)입니다. root라도 정책을 벗어나면 거부됩니다.
httpd 프로세스 (scontext: httpd_t)
│ 요청: /var/www/html/index.html 읽기 (tcontext: httpd_sys_content_t)
↓
① DAC 검사 (rwx 권한) → 통과
② SELinux 정책 검사 → httpd_t → httpd_sys_content_t : read 허용?
├─ 허용 → 동작 수행
└─ 거부 → type=AVC ... denied 로그 (Enforcing이면 실제 차단)
모드는 Enforcing(차단+기록), Permissive(기록만), Disabled(정책 미적용) 세 가지입니다.
httpd가 장악되더라도 SELinux가 httpd_t의 행동 범위(포트 바인딩, 셸 실행, 홈 디렉터리 접근)를 제한해 피해 확산을 막습니다.setenforce 0을 하고 되돌리지 않는 경우가 많습니다. 공격자에게도 SELinux 해제는 흔한 첫 조치입니다.| 명령 | 용도 |
|---|---|
getenforce, sestatus | 현재 모드·정책·설정 파일 모드 |
grep ^SELINUX= /etc/selinux/config | 재부팅 후 적용될 모드 |
ls -Z 경로, ps -eZ | 파일·프로세스 컨텍스트 |
sudo ausearch -m AVC -ts recent | 최근 AVC 거부 |
sudo ausearch -m AVC -ts today | audit2why | 거부 원인 설명(policycoreutils-python-utils) |
semanage port -l | grep http | 타입별 허용 포트 |
restorecon -Rv 경로 | 기본 컨텍스트 복원 |
# 1) 상태 확인 (런타임 vs 설정 파일)
getenforce
sudo sestatus | grep -E 'Current mode|Mode from config|Loaded policy'
# 2) AVC 발생 실습: httpd를 허용되지 않은 포트(9999)에 바인딩 시도
sudo sed -i 's/^Listen 80$/Listen 9999/' /etc/httpd/conf/httpd.conf
sudo systemctl restart httpd # 실패 예상
sudo ausearch -m AVC -ts recent -i | tail -5
sudo ausearch -m AVC -ts recent | audit2why
# 3) 원복
sudo sed -i 's/^Listen 9999$/Listen 80/' /etc/httpd/conf/httpd.conf
sudo systemctl restart httpd
정상 운영에서 포트를 바꿔야 한다면 semanage port -a -t http_port_t -p tcp 9999로 정책에 등록하는 것이 올바른 방법이고, SELinux를 끄는 것은 해결책이 아닙니다.
$ getenforce
Enforcing
$ sudo sestatus | grep -E 'Current mode|Mode from config'
Current mode: enforcing
Mode from config file: enforcing
런타임과 설정 파일 모두 enforcing이고, AVC 거부가 설명 가능한 소수(설정 실수 등)만 있는 상태가 정상입니다.
$ getenforce
Permissive
$ grep ^SELINUX= /etc/selinux/config
SELINUX=disabled
permissive=1로 기록되며 차단되지 않습니다. 이 기간의 AVC 로그는 "막지 못한 정책 위반 목록"이 됩니다.AVC 거부와 모드 변경 로그입니다(가상의 예시 로그).
type=AVC msg=audit(1759719000.101:1601): avc: denied { name_bind } for pid=7501 comm="httpd" src=9999 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0
type=AVC msg=audit(1759719300.220:1622): avc: denied { execute } for pid=7533 comm="httpd" name="bash" dev="dm-0" ino=1310 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:shell_exec_t:s0 tclass=file permissive=0
type=MAC_STATUS msg=audit(1759719400.010:1630): enforcing=0 old_enforcing=1 auid=1002 ses=5 enabled=1 old-enabled=1 lsm=selinux res=1
| 로그 | 해석 |
|---|---|
name_bind ... src=9999 | 허용되지 않은 포트 바인딩 → 설정 문제일 가능성 |
execute ... httpd_t → shell_exec_t | 웹 프로세스가 셸 실행 시도 → 웹셸·명령 주입 의심 (정탐 가능성 높음) |
MAC_STATUS enforcing=0 old_enforcing=1 auid=1002 | 사용자 1002가 Permissive로 전환 |
같은 httpd_t의 AVC라도 동작(name_bind vs execute) 에 따라 의미가 완전히 다릅니다.
MAC_STATUS enforcing=0은 하드닝 해제 징후로 즉시 확인합니다(039편에서 종합).execute, connectto, name_connect 거부는 침해 행위와 연결될 가능성이 높습니다.<group name="local,selinux,">
<rule id="100240" level="12">
<if_group>audit</if_group>
<match>type=MAC_STATUS</match>
<regex>enforcing=0 old_enforcing=1</regex>
<description>SELinux Enforcing 해제(setenforce 0)</description>
</rule>
<rule id="100241" level="10">
<if_group>audit</if_group>
<match>type=AVC</match>
<regex>scontext=\S+:httpd_t:\S+ tcontext=\S+:shell_exec_t</regex>
<description>웹 프로세스의 셸 실행 시도(SELinux 차단)</description>
</rule>
</group>
auid)와 AVC 거부의 프로세스·동작을 확인합니다.sestatus 출력, 관련 웹 로그를 보존합니다.setenforce 1 및 설정 파일 복원, 셸 실행 시도가 있었다면 웹 애플리케이션을 격리 조사합니다.| 구분 | 핵심 내용 |
|---|---|
| 모드 | Enforcing(차단) / Permissive(기록만) / Disabled |
| AVC 3요소 | scontext(누가) · 동작 · tcontext(무엇을) |
| 고위험 AVC | httpd_t → shell_exec_t execute |
| 해제 탐지 | type=MAC_STATUS enforcing=0 old_enforcing=1 |
| 면접 포인트 | "SELinux 끄기는 해결책이 아니라 semanage로 정책 등록" |
다음 편 018. Linux 서버 보안 — AppArmor 프로파일 상태 점검(Ubuntu) 에서는 Ubuntu의 강제 접근 통제인 AppArmor 프로파일 상태 점검을 다룹니다.
이전 편: 016. Linux 서버 보안 — nftables 규칙셋 점검과 차단 로깅
📚 시리즈 전체 보기: 시스템 보안 · 취약점