040. Linux 서버 보안 — 신규 리스닝 서비스·비인가 유닛 이상 징후

changseop lee·5일 전

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

선행 학습

1. 개념

013편에서는 /etc/systemd/system/의 서비스를, 014편에서는 리스닝 포트를 점검했습니다. 그런데 systemd에는 이 두 점검을 피해 갈 수 있는 경로가 더 있습니다.

systemd 유닛이 생길 수 있는 곳
 ├─ 시스템 유닛  /etc/systemd/system/, /usr/lib/systemd/system/    ← 013편 점검 대상
 ├─ 임시 유닛    systemd-run 으로 생성 → run-uXXXX.service           (파일 없이 메모리에만, 재부팅 시 소멸)
 └─ 사용자 유닛  ~/.config/systemd/user/*.service                   (systemctl --user)
                 + loginctl enable-linger 사용자 → 로그아웃 후에도 계속 실행

비인가 서비스 판정은 유닛의 위치·생성 방식, 실행 파일, 실행 계정, 리스닝 포트를 하나로 묶어 보는 것이 핵심입니다.

2. 왜 중요한가

  • /etc/systemd/system/만 감시하면 일반 사용자 권한으로 만든 사용자 유닛이나 파일을 남기지 않는 임시 유닛을 놓칩니다.
  • linger가 켜진 계정은 SSH 세션이 없어도 사용자 서비스가 계속 실행되어, 일반 계정 수준의 지속성으로 쓰일 수 있습니다.
  • 서비스가 포트를 열고 있다면 외부 접근 경로까지 생긴 것이므로, 포트 점검과 결합해야 위험도를 정확히 판단할 수 있습니다.

3. 핵심 명령어 / 설정

명령용도
systemctl list-units --type=service --all | grep run-systemd-run 임시 유닛
ls /run/systemd/transient/임시 유닛 정의(메모리 파일시스템)
ls /var/lib/systemd/linger/linger 활성 사용자 목록
sudo -u 사용자 XDG_RUNTIME_DIR=/run/user/UID systemctl --user list-units특정 사용자의 사용자 유닛
find /home -path '*/.config/systemd/user/*' -type f사용자 유닛 파일
systemctl status PIDPID가 속한 유닛(cgroup) 확인

4. 실습 (실습 예시)

# 1) 임시 유닛
systemctl list-units --type=service --all --no-legend | awk '$1 ~ /^run-/'
ls -l /run/systemd/transient/ 2>/dev/null

# 2) linger 사용자와 사용자 유닛 파일
ls /var/lib/systemd/linger/ 2>/dev/null
sudo find /home /root -path '*/.config/systemd/user/*' -type f -printf '%TY-%Tm-%Td %TH:%TM %u %p\n' 2>/dev/null

# 3) 리스닝 포트 → PID → 유닛 역추적
for pid in $(sudo ss -tlpnH | grep -oP 'pid=\K[0-9]+' | sort -u); do
  unit=$(systemctl status $pid 2>/dev/null | head -1 | awk '{print $2}')
  echo "$pid $(cat /proc/$pid/comm) unit=$unit"
done

3번은 포트를 연 프로세스가 어느 유닛 아래에서 실행 중인지를 보여주므로, 서비스 목록에 없는 포트의 출처를 바로 찾을 수 있습니다.

5. 정상 상태

$ ls /var/lib/systemd/linger/
$ sudo find /home -path '*/.config/systemd/user/*' -type f
$
1022 sshd unit=sshd.service
1188 httpd unit=httpd.service

linger 사용자와 사용자 유닛이 없고, 모든 리스닝 프로세스가 승인된 시스템 유닛에 속한 상태가 정상입니다.

6. 이상 상태

$ ls /var/lib/systemd/linger/
devops
$ sudo find /home -path '*/.config/systemd/user/*' -type f -printf '%TY-%Tm-%Td %TH:%TM %u %p\n'
2026-10-01 03:35 devops /home/devops/.config/systemd/user/tracker-sync.service
$ ... (역추적 결과)
9801 python3 unit=user@1002.service
  • devops 계정에 linger + 사용자 유닛 → 로그아웃 후에도 계속 실행
  • 리스닝 프로세스가 user@1002.service(사용자 서비스 관리자) 아래에서 실행 → 시스템 유닛 점검으로는 보이지 않던 포트
  • 데스크톱 기능처럼 보이는 이름(tracker-sync)은 서버 환경에서 의미가 없으므로 위장 가능성

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

linger 설정과 사용자 유닛·임시 유닛 생성 흔적입니다(가상의 예시 로그).

Oct  1 03:35:10 rocky9-web01 sudo[9750]:  devops : TTY=pts/1 ; PWD=/home/devops ; USER=root ; COMMAND=/usr/bin/loginctl enable-linger devops
Oct  1 03:35:31 rocky9-web01 systemd[9760]: Started tracker-sync.service.
Oct  1 03:36:02 rocky9-web01 systemd[1]: Started /usr/bin/python3 -m http.server 8090.
type=EXECVE msg=audit(1759739762.001:3001): argc=6 a0="systemd-run" a1="--unit=run-u77" a2="/usr/bin/python3" a3="-m" a4="http.server" a5="8090"
관찰해석
loginctl enable-linger devops사용자 서비스 상시 실행 허용
systemd[9760] (PID 1이 아닌 systemd)사용자 서비스 관리자가 시작한 유닛
systemd-run ...파일 없는 임시 유닛으로 프로세스 실행
Started /usr/bin/python3 ...임시 유닛은 설명 대신 명령줄이 표시되는 경우가 많음

8. SOC 관제 포인트

  • linger 활성 사용자, 사용자 유닛 파일, run-* 임시 유닛을 정기 점검 항목에 추가합니다.
  • 리스닝 포트는 항상 "어느 유닛에 속하는가"까지 확인합니다.
  • systemd-run, loginctl enable-linger 실행은 운영에서 드물어 탐지 가치가 높습니다.

9. 탐지 규칙

-a always,exit -F arch=b64 -S execve -F path=/usr/bin/systemd-run -k systemd_run
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/loginctl -k loginctl
-w /var/lib/systemd/linger/ -p wa -k linger
<group name="local,hardening_drift,">
  <rule id="100450" level="10">
    <if_group>audit</if_group>
    <field name="audit.key">systemd_run|linger</field>
    <description>임시 유닛 실행 또는 linger 설정 변경</description>
  </rule>
</group>

사용자 유닛 파일 감시는 Wazuh FIM에 /home/*/.config/systemd/user 경로를 추가하는 방식으로 구성합니다(와일드카드 지원 여부는 에이전트 버전 문서로 확인).

10. 대응 방법

  1. 초기 확인 — 비인가 유닛의 종류(시스템·임시·사용자), 실행 파일, 실행 계정, 연 포트를 확인합니다.
  2. 범위 확인 — 같은 계정·같은 유닛 이름이 다른 서버에 있는지, 해당 계정의 최근 로그인 출발지를 확인합니다.
  3. 증거 확보 — 유닛 파일(또는 /run/systemd/transient/ 사본), 프로세스 정보, 연결 목록을 보존합니다.
  4. 차단/조치 — 유닛 중지·삭제, linger 해제(loginctl disable-linger), 계정 조치를 진행합니다.
  5. 재발 방지 — 임시·사용자 유닛과 linger 점검을 기준선과 탐지 룰에 포함합니다.

11. 핵심 정리

경로특징 / 점검 방법
시스템 유닛/etc/systemd/system / 013편 점검
임시 유닛systemd-run, 파일 없음 / list-units | grep run-, /run/systemd/transient
사용자 유닛~/.config/systemd/user / find + systemctl --user
linger로그아웃 후에도 실행 / /var/lib/systemd/linger
면접 포인트"포트 → PID → 유닛 역추적으로 숨은 서비스의 출처를 찾는다"

12. 다음 편 예고

다음 편 041. Linux 서버 보안 — CIS Benchmark 관점의 점검 구조 에서는 4단계로 넘어가 점검을 체계화하는 CIS Benchmark 관점의 점검 구조를 다룹니다.


이전 편: 039. Linux 서버 보안 — 하드닝 해제 징후 — SELinux·방화벽·auditd 중지
📚 시리즈 전체 보기: 시스템 보안 · 취약점

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

0개의 댓글