서비스 · 프로세스 관리 41 / 50 · Part 5. 보안과 SOC
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (systemd로 부팅한 Docker 격리 컨테이너, 테스트 계정 analyst)

1. 들어가며

Part 5 「보안과 SOC」를 시작한다. Part 1~4에서 프로세스의 구조(exe, cwd, PPID, 세션, cgroup, fd, 소켓)와 서비스·예약 작업의 동작을 배웠다. 이제 이 지식을 관제 판단 에 쓴다.

관제 요원이 서버 한 대를 점검할 때 수백 개의 프로세스를 하나씩 볼 수는 없다. 필요한 것은 "무엇을 먼저 봐야 하는가"를 정하는 기준 이다. 이번 글에서는 지금까지 배운 지표를 판단 기준표로 정리하고, 읽기 전용 점검 스크립트로 사용자 프로세스에 플래그를 붙여 확인 우선순위를 정하는 실습을 한다.

Part 5의 실습은 모두 무해한 테스트 항목(sleep·python 복사본, logger 한 줄)을 대상으로 한다. 목표는 공격 재현이 아니라 탐지·수집·판단 절차 를 익히는 것이다.


2. 핵심 개념

2-1. 판단 기준표

분류지표확인 위치관련 편
실행 파일exe가 (deleted)/proc/PID/exe01·15
exe가 /tmp, /dev/shm, /var/tmp/proc/PID/exe05
이름이 .으로 시작 (숨김)exe 경로—
패키지 소유가 아님rpm -qf / dpkg -S22
실행 주체서비스 계정의 셸·다운로드 도구ps -o user,comm30
예상 밖의 부모 (웹 서버 → 셸)pstree -ps02·03
생존 방식PPID 1 + TTY 없음ps -o ppid,tty08·19
서비스가 아닌 세션 scope 소속/proc/PID/cgroup18
행위허용 목록 밖 포트, 외부 연결ss -tnp16
지속적인 높은 CPUtop, ps --sort07·47

2-2. 판단 원칙

원칙설명
지표는 "확인 필요" 신호하나의 지표만으로 악성이라 판단하지 않는다
조합 으로 우선순위여러 지표가 겹칠수록 우선 확인
정상 맥락 확인서비스 cgroup, 패키지 소유, 변경 관리 기록으로 설명되면 정상
읽기 전용판단 전에는 아무것도 바꾸지 않는다 (증거 보존, 43편)

3. 동작 원리

의심 프로세스 판단 기준 — 하나의 지표가 아니라 조합으로 본다

/proc/[0-9]* 순회 (root 소유 제외 — 사용자 프로세스 우선)
  → exe · cwd · PPID · TTY 읽기
  → 규칙별 플래그: DELETED_EXE / TMP_EXE / HIDDEN_NAME / ORPHAN_NO_TTY
  → 플래그 개수로 확인 순서 결정
  → 상위 항목 상세 확인: cmdline · lstart · cgroup · sessionid

실습 스크립트는 사용자 프로세스만 대상으로 했다. root 프로세스는 수가 많고 정상 데몬이 대부분이라, 실무에서는 패키지 소유 여부 같은 추가 기준(49편)과 함께 본다.


4. 명령어 실습

# 1) (analyst) 점검 대상: 확인이 필요한 형태의 테스트 프로세스와 일반 nohup 작업
cp /usr/bin/sleep /tmp/.cache-helper && setsid /tmp/.cache-helper 600 < /dev/null > /dev/null 2>&1 &
rm -f /tmp/.cache-helper; nohup sleep 700 > /dev/null 2>&1 &

# 2) (root) 판단 기준표를 적용하는 읽기 전용 스크립트 /root/triage.sh
#    - 사용자(비 root) 프로세스의 PID·USER·PPID·TTY·EXE·CWD 출력
#    - DELETED_EXE / TMP_EXE / HIDDEN_NAME / ORPHAN_NO_TTY 플래그
/root/triage.sh

# 3) 플래그가 가장 많은 프로세스 상세 확인
ls -l /proc/$P/exe; tr '\0' ' ' < /proc/$P/cmdline
ps -o pid,ppid,user,lstart,etime,stat,cmd -p $P
cat /proc/$P/cgroup | tail -1; cat /proc/$P/sessionid

5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · analyst@rocky9-lab — 점검 대상 준비: 정상 프로세스와 확인이 필요한 프로세스

실제 실행 결과 — Rocky Linux 9.8 · root@rocky9-lab — 판단 기준표로 한 줄씩 점검

실제 실행 결과 — Rocky Linux 9.8 · root@rocky9-lab — 플래그가 붙은 프로세스 상세 확인

텍스트 원본(실제 출력):

[analyst@rocky9-lab ~]$ cp /usr/bin/sleep /tmp/.cache-helper && setsid /tmp/.cache-helper 600 < /dev/null > /dev/null 2>&1 &
[analyst@rocky9-lab ~]$ sleep 0.3; rm -f /tmp/.cache-helper; nohup sleep 700 > /dev/null 2>&1 &
[analyst@rocky9-lab ~]$ sleep 0.3; pgrep -a -u analyst sleep; pgrep -a -u analyst -f cache-helper
860 sleep 700
858 /tmp/.cache-helper 600
[root@rocky9-lab ~]# cat > /root/triage.sh <<'EOF'
> #!/bin/bash
> # 사용자 프로세스를 점검 기준으로 표시 (읽기 전용)
> printf '%-6s %-8s %-6s %-4s %-28s %-14s %s\n' PID USER PPID TTY EXE CWD FLAGS
> for d in /proc/[0-9]*; do
>   p=${d#/proc/}; u=$(stat -c %U $d 2>/dev/null) || continue
>   [ "$u" = root ] && continue
>   exe=$(readlink $d/exe 2>/dev/null) || continue
>   cwd=$(readlink $d/cwd 2>/dev/null); ppid=$(awk '/^PPid/{print $2}' $d/status)
>   tty=$(ps -o tty= -p $p | tr -d ' '); f=""
>   case "$exe" in *" (deleted)") f="$f DELETED_EXE";; esac
>   case "$exe" in /tmp/*|/dev/shm/*|/var/tmp/*) f="$f TMP_EXE";; esac
>   case "$(basename "${exe% (deleted)}")" in .*) f="$f HIDDEN_NAME";; esac
>   [ "$ppid" = 1 ] && [ "$tty" = "?" ] && f="$f ORPHAN_NO_TTY"
>   printf '%-6s %-8s %-6s %-4s %-28s %-14s %s\n' "$p" "$u" "$ppid" "$tty" "${exe:0:28}" "${cwd:0:14}" "${f:- -}"
> done
> EOF
[root@rocky9-lab ~]# chmod 700 /root/triage.sh; /root/triage.sh
PID    USER     PPID   TTY  EXE                          CWD            FLAGS
31     analyst  1      ?    /usr/bin/python3.9           /opt/labapp     ORPHAN_NO_TTY
35     dbus     1      ?    /usr/bin/dbus-broker-launch  /               ORPHAN_NO_TTY
37     dbus     35     ?    /usr/bin/dbus-broker         /               -
821    analyst  1      ?    /usr/lib/systemd/systemd     /               ORPHAN_NO_TTY
823    analyst  821    ?    /usr/lib/systemd/systemd     /               -
858    analyst  1      ?    /tmp/.cache-helper (deleted) /home/analyst   DELETED_EXE TMP_EXE HIDDEN_NAME ORPHAN_NO_TTY
860    analyst  1      ?    /usr/bin/sleep               /home/analyst   ORPHAN_NO_TTY
[root@rocky9-lab ~]# P=$(for d in /proc/[0-9]*; do readlink $d/exe 2>/dev/null | grep -q deleted && echo ${d#/proc/}; done | head -1); echo "PID=$P"
PID=858
[root@rocky9-lab ~]# ls -l /proc/$P/exe; tr '\0' ' ' < /proc/$P/cmdline; echo
lrwxrwxrwx 1 analyst analyst 0 Sep 24 13:40 /proc/858/exe -> '/tmp/.cache-helper (deleted)'
/tmp/.cache-helper 600
[root@rocky9-lab ~]# ps -o pid,ppid,user,lstart,etime,stat,cmd -p $P
    PID    PPID USER                      STARTED     ELAPSED STAT CMD
    858       1 analyst  Thu Sep 24 13:40:13 2026       00:01 Ss   /tmp/.cache-helper 600
[root@rocky9-lab ~]# cat /proc/$P/cgroup | tail -1; cat /proc/$P/sessionid; echo
0::/docker/5a46f907edb23397a00c52e8214c9c387f1cf283dd50c13b81f6c01a58252f3b/user.slice/user-1000.slice/session-15.scope
15
[root@rocky9-lab ~]# pkill -u analyst -x sleep; pkill -u analyst -f cache-helper; true

6. 결과 해석

관찰의미
PID 858 /tmp/.cache-helper (deleted) — 플래그 4개임시 경로·숨김 이름·삭제된 실행 파일·터미널 없는 고아. 가장 먼저 확인할 대상 이다
PID 860 /usr/bin/sleep — ORPHAN_NO_TTY정상 경로의 프로그램이지만 로그아웃 후에도 남은 작업이다. 소유자에게 용도를 확인한다
PID 31 python3.9 (labapp) — ORPHAN_NO_TTYsystemd 서비스는 원래 PPID 1·TTY 없음이다. cgroup이 labapp.service 라면 정상 — 규칙의 오탐이다
dbus·systemd --user — ORPHAN_NO_TTY시스템·사용자 manager도 같은 모양이다. 이 플래그 하나로는 판단할 수 없다
858 상세: cmdline /tmp/.cache-helper 600, STAT Sssetsid로 새 세션의 리더 가 된 프로세스 (19편)
cgroup .../user-1000.slice/session-15.scope서비스가 아니라 analyst의 로그인 세션 에서 시작되었다
sessionid 15이 번호로 인증 로그·감사 로그의 로그인 기록과 연결할 수 있다 (48·50편)

규칙 기반 점검은 오탐(ORPHAN_NO_TTY의 정상 서비스) 을 반드시 낳는다. 그래서 플래그 개수로 우선순위를 정하고, cgroup·패키지 소유 같은 정상 맥락 으로 걸러 내는 단계가 필요하다.


7. 보안 관점

주제내용
우선순위관제 시간은 한정되어 있다. 지표 조합으로 확인 순서를 정하는 것 자체가 관제 역량이다
정상 맥락systemd 서비스, 패키지 소유 파일, 변경 관리 기록은 정상 판단의 근거가 된다. 반대로 이들로 설명되지 않는 항목이 조사 대상이다
증거 우선플래그가 붙었다고 바로 종료하지 않는다. (deleted) 실행 파일은 프로세스가 살아 있을 때만 복사할 수 있다 (43편)
사람 확인사용자 계정의 프로세스는 기술 판단만으로 끝내지 않고 소유자에게 용도를 확인 하는 절차를 둔다

8. 보안관제 관점

[점검 실행]  /root/triage.sh > triage_$(date +%F_%H%M).txt
     ↓
[우선순위]   플래그 수 내림차순 → 상위 항목부터
     ↓
[정상 맥락]  cat /proc/PID/cgroup   → *.service 면 해당 unit 확인 (패키지·변경 기록)
             rpm -qf / dpkg -S <exe>  → 패키지 소유 여부
     ↓
[설명 불가]  43편 휘발성 증거 수집 → 44편 네트워크 확인 → 담당자·소유자 확인
     ↓
[기록]       판단 근거(지표·맥락·확인 결과)를 티켓에 남김
판단 결과조치
정상 (맥락으로 설명됨)예외 목록에 근거와 함께 등록
확인 필요증거 수집 후 소유자 확인
이상 (설명 불가 + 지표 다수)에스컬레이션, 증거 수집, 격리 판단

9. 실무에서 자주 발생하는 실수

실수결과예방
지표 하나로 악성 판정정상 서비스 중단조합 + 정상 맥락 확인
플래그 붙은 프로세스 즉시 kill증거 소실수집 후 조치
일반 계정으로 점검exe·cwd를 못 읽음root로 실행
이름(comm)만 보고 판단위장 이름에 속음exe 경로 기준
오탐 예외를 근거 없이 등록실제 이상을 가림예외에 근거·만료일 기록

10. 실습 체크리스트

[ ] 판단 기준표의 지표와 확인 위치를 정리했다
[ ] 읽기 전용 점검 스크립트로 사용자 프로세스에 플래그를 붙였다
[ ] 플래그 4개가 겹친 테스트 프로세스를 최우선으로 식별했다
[ ] 정상 서비스(labapp)의 ORPHAN_NO_TTY 오탐을 cgroup 으로 걸러냈다
[ ] cgroup 과 sessionid 로 프로세스의 시작 세션을 확인했다
[ ] 판단 결과별 조치(예외·확인·에스컬레이션)를 구분할 수 있다

11. 핵심 정리

  • 의심 프로세스 판단은 실행 파일·실행 주체·생존 방식·행위 지표의 조합으로 한다.
  • 각 지표는 "확인 필요" 신호이며, 여러 개가 겹칠수록 우선순위가 높다.
  • 서비스 cgroup·패키지 소유·변경 기록 같은 정상 맥락으로 오탐을 걸러 낸다.
  • 판단 전에는 아무것도 바꾸지 않고, 증거 수집 후 조치한다.
  • 판단 근거를 기록해야 예외 관리와 보고가 가능하다.

12. 다음 편 예고

다음 글 「42. 정상 프로세스 기준선(baseline) 만들기」 에서는 "평소 상태"를 파일로 저장해 두고 변화만 찾아내는 방법을 다룬다. 프로세스·대기 포트·활성 unit의 기준선을 만들고, 새 서비스와 포트가 생겼을 때 diff로 찾아낸다.


참고 자료


시리즈 이동

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

0개의 댓글