027. Linux 서버 보안 — systemd 서비스 보안 옵션과 systemd-analyze security

changseop lee·6일 전

시스템 보안 · 취약점 › A. Linux 서버 보안 설정 · 27/50편 (전체 027/450)
학습 단계: 2단계 · 설정 및 점검
실습 표기: 이 글의 명령어·출력·로그는 로컬 VMware 테스트 VM(Rocky Linux 9 / Ubuntu 22.04) 기준의 「실습 예시」이며, IP·계정·호스트명은 가상의 값입니다.

선행 학습

1. 개념

systemd는 서비스를 실행할 때 프로세스가 볼 수 있는 파일시스템, 얻을 수 있는 권한, 쓸 수 있는 시스템 콜을 제한하는 옵션을 제공합니다. 서비스가 장악되더라도 할 수 있는 일이 줄어드는 피해 범위 제한(blast radius 축소) 장치입니다.

[Service] 옵션                 효과
NoNewPrivileges=yes     → setuid 바이너리로 권한 상승 불가
ProtectSystem=strict    → /usr, /etc 등 전체를 읽기 전용으로
ProtectHome=yes         → /home, /root 접근 차단
PrivateTmp=yes          → 서비스 전용 /tmp (다른 프로세스와 분리)
ReadWritePaths=/var/www/uploads → 쓰기 허용 경로만 명시
CapabilityBoundingSet=CAP_NET_BIND_SERVICE → 필요한 capability만

systemd-analyze security 서비스는 이런 옵션 적용 정도를 0.0(안전)~10.0(위험) 노출 점수로 보여줍니다.

2. 왜 중요한가

  • 웹 서버가 명령 주입으로 장악돼도 ProtectSystem=strict면 /etc/cron.d에 파일을 쓸 수 없고, NoNewPrivileges면 SUID를 통한 상승이 막힙니다.
  • 반대로 공격자나 실수로 override 파일이 추가되면 원본 유닛은 그대로인데 보안 옵션이 해제될 수 있습니다.
  • 점수는 절대 기준이 아니라 개선 방향을 찾는 도구입니다. 서비스 기능을 깨지 않는 선에서 옵션을 추가해야 합니다.

3. 핵심 명령어 / 설정

명령용도
systemd-analyze security전체 서비스 노출 점수 목록
systemd-analyze security httpd.service옵션별 상세 평가
systemctl cat httpd원본 유닛 + drop-in 전체 내용
systemd-delta --type=extended,overridden기본 유닛을 덮어쓴 설정 목록
sudo systemctl edit httpd/etc/systemd/system/httpd.service.d/override.conf 생성

4. 실습 (실습 예시)

# 1) 노출 점수 확인
systemd-analyze security --no-pager | head -15
systemd-analyze security httpd.service --no-pager | tail -3

# 2) 보안 옵션 drop-in 적용 (테스트 VM)
sudo mkdir -p /etc/systemd/system/httpd.service.d
sudo tee /etc/systemd/system/httpd.service.d/10-hardening.conf <<'EOF'
[Service]
NoNewPrivileges=yes
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=full
EOF
sudo systemctl daemon-reload && sudo systemctl restart httpd
systemd-analyze security httpd.service --no-pager | tail -1

# 3) override 현황 점검
systemd-delta --type=extended --no-pager

ProtectSystem=full은 /usr, /boot, /etc를 읽기 전용으로 만들고, strict는 거의 전체를 읽기 전용으로 만듭니다. 웹 애플리케이션이 쓰는 경로는 ReadWritePaths=로 명시해야 합니다.

5. 정상 상태

$ systemd-analyze security httpd.service --no-pager | tail -1
→ Overall exposure level for httpd.service: 6.2 MEDIUM
$ systemd-delta --type=extended --no-pager
[EXTENDED]   /usr/lib/systemd/system/httpd.service → /etc/systemd/system/httpd.service.d/10-hardening.conf

옵션 적용 후 점수가 내려가고, override가 변경관리된 하드닝 파일만 존재하는 상태가 정상입니다. (점수는 systemd 버전·서비스에 따라 다릅니다.)

6. 이상 상태

$ systemd-delta --type=extended --no-pager
[EXTENDED]   /usr/lib/systemd/system/httpd.service → /etc/systemd/system/httpd.service.d/10-hardening.conf
[EXTENDED]   /usr/lib/systemd/system/httpd.service → /etc/systemd/system/httpd.service.d/zz-debug.conf
$ systemctl cat httpd | sed -n '/zz-debug/,$p'
# /etc/systemd/system/httpd.service.d/zz-debug.conf
[Service]
NoNewPrivileges=no
ProtectSystem=no
ExecStartPost=/bin/sh -c '/var/tmp/.font-unix/fc &'
  • 이름이 나중에 읽히는 zz- drop-in이 하드닝 옵션을 덮어써 해제
  • ExecStartPost로 서비스 시작 때마다 의심 파일 실행 → 정상 서비스에 기생하는 지속성

7. 로그 분석 (분석 방법)

override 파일 생성 → daemon-reload → 서비스 재시작 순서로 흔적이 남습니다(가상의 예시 로그).

type=PATH msg=audit(1759731800.100:2201): item=1 name="/etc/systemd/system/httpd.service.d/zz-debug.conf" nametype=CREATE key="systemd_units"
Oct  1 03:10:05 rocky9-web01 systemd[1]: Reloading.
Oct  1 03:10:08 rocky9-web01 systemd[1]: Stopping The Apache HTTP Server...
Oct  1 03:10:09 rocky9-web01 systemd[1]: Started The Apache HTTP Server.
type=SYSCALL msg=audit(1759731809.410:2210): syscall=59 success=yes ppid=1 pid=8722 uid=0 comm="sh" exe="/usr/bin/bash" key="exec_tmp"
순서의미
drop-in 생성설정 변경(누가: 같은 이벤트의 SYSCALL auid)
Reloading.systemd가 변경을 읽음
httpd 재시작변경 적용
ppid=1의 sh 실행systemd가 ExecStartPost를 실행

운영 중 서비스 재시작 자체는 흔하므로, 재시작 직전의 유닛 파일 변경이 있었는지가 판단 기준입니다.

8. SOC 관제 포인트

  • /etc/systemd/system/*.service.d/ 생성·변경을 유닛 파일과 같은 수준으로 감시합니다.
  • 보안 옵션을 no로 바꾸는 drop-in, ExecStart*에 셸을 넣는 drop-in은 높은 우선순위입니다.
  • 주요 서비스의 노출 점수를 기준선에 넣어 점수 상승을 변화 지표로 사용합니다.

9. 탐지 규칙

<rule id="100330" level="11">
  <if_sid>550,554</if_sid>
  <field name="file">^/etc/systemd/system/\S+\.service\.d/</field>
  <description>systemd 서비스 drop-in 생성/변경: $(file)</description>
</rule>

report_changes를 켜 두면 Alert에 변경된 줄(예: ExecStartPost=...)이 함께 표시되어 분석 시간이 크게 줄어듭니다(021편 설정 참고).

10. 대응 방법

  1. 초기 확인 — systemctl cat과 systemd-delta로 drop-in 전체 내용과 생성 시각을 확인합니다.
  2. 범위 확인 — 같은 drop-in·실행 파일이 다른 서버·다른 서비스에 있는지 확인합니다.
  3. 증거 확보 — drop-in 사본, 실행된 파일 사본, journal·audit 로그를 보존합니다.
  4. 차단/조치 — 비인가 drop-in 삭제 → daemon-reload → 서비스 재시작, 실행된 프로세스 종료를 진행합니다.
  5. 재발 방지 — 하드닝 drop-in을 표준화하고 drop-in 디렉터리 FIM·노출 점수 기준선을 운영합니다.

11. 핵심 정리

구분핵심 내용
목적서비스 장악 시 피해 범위 축소(샌드박스)
핵심 옵션NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp
점검 도구systemd-analyze security, systemd-delta, systemctl cat
위험 패턴zz-*.conf로 옵션 해제 + ExecStartPost 셸
면접 포인트"원본 유닛이 정상이어도 drop-in이 덮어쓸 수 있다"

12. 다음 편 예고

다음 편 028. Linux 서버 보안 — journald 보존·저장 설정 점검 에서는 로그 수집의 출발점인 journald 보존·저장 설정을 점검합니다.


이전 편: 026. Linux 서버 보안 — cron·at 접근 제어 점검
📚 시리즈 전체 보기: 시스템 보안 · 취약점

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글