리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.
리눅스 시스템 기초 2 / 50 · Part 1. Linux 기본 구조
실습 환경: Rocky Linux 9 (10.0.0.200) · 비교: Ubuntu 22.04
이전 글: 1. Linux 기본 구조 이해
1편에서 Linux를 User → Application → Shell → System Call → Kernel → Hardware 계층으로 나눠 봤다. 이번 글은 그중 가장 아래에서 모든 것을 통제하는 Kernel 을 자세히 본다.
보안관제 입장에서 커널이 중요한 이유는 두 가지다.
ps, ls 같은 일반 명령어로 보이지 않을 수 있다. 커널이 남기는 흔적(모듈 목록, tainted 상태, 커널 로그)을 확인할 줄 알아야 한다.이번 글에서 답할 질문은 다음과 같다.
/proc, /sys, sysctl, dmesg)커널(Kernel)은 운영체제의 핵심으로, 하드웨어 자원(CPU, 메모리, 디스크, 네트워크)을 프로세스들에게 나눠주고 통제하는 프로그램 이다. 부팅 시 가장 먼저 메모리에 올라가서 시스템이 꺼질 때까지 동작한다.
Linux 커널은 모놀리식(Monolithic) 커널 이다. 프로세스 관리, 메모리 관리, 파일 시스템, 네트워크 스택, 드라이버가 모두 하나의 커널 공간 안에서 동작한다. 대신 모든 기능을 처음부터 넣지 않고, 필요할 때 커널 모듈(LKM, Loadable Kernel Module) 로 붙였다 뗄 수 있다.
| 구분 | 설명 | 예시 |
|---|---|---|
| 커널 본체 (vmlinuz) | 부팅 시 로드되는 핵심 코드 | 스케줄러, 메모리 관리 |
| 커널 모듈 (.ko) | 실행 중 추가·제거 가능한 기능 | 파일 시스템(xfs, ext4), NIC 드라이버, 방화벽 모듈 |
모듈 파일은 /lib/modules/$(uname -r)/ 아래에 있다.

| 서브시스템 | 하는 일 | 사용자가 보는 형태 |
|---|---|---|
| Process 관리 | 프로세스 생성(fork/exec), CPU 스케줄링, 시그널 전달 | ps, top, kill |
| Memory 관리 | 가상 메모리, 프로세스 간 메모리 격리, 페이지 캐시 | free, /proc/meminfo |
| VFS / 파일 시스템 | 파일 읽기·쓰기, 권한 검사, ext4·xfs 등 차이를 감춤 | ls, stat |
| Network | 소켓, TCP/IP 스택, 패킷 필터링(netfilter) | ss, ip, firewalld |
| Security (LSM) | SELinux·AppArmor 같은 보안 모듈이 접근 제어에 개입 | getenforce, audit.log |
| Device Driver | 하드웨어 제어 | lsblk, lspci, dmesg |
x86 CPU는 실행 권한을 링(Ring)으로 나눈다. Linux는 이 중 두 개를 사용한다.
| 모드 | 누가 실행 | 할 수 있는 일 |
|---|---|---|
| Ring 0 (Kernel Mode) | 커널, 커널 모듈 | 모든 메모리·하드웨어 접근 |
| Ring 3 (User Mode) | 일반 프로그램 (root가 실행한 프로그램 포함) | 자기 메모리만 접근, 나머지는 System Call로 요청 |
여기서 자주 하는 오해가 있다. root 권한과 커널 모드는 다르다. root도 User Mode에서 실행되는 프로그램이다. 다만 root는 커널에 요청할 수 있는 범위가 넓고, 커널 모듈을 로드할 수 있다. 그래서 root를 탈취한 공격자는 커널 모듈을 올려 Ring 0까지 내려갈 수 있다. 이것이 커널 모듈 루트킷의 원리다.
커널은 내부 상태를 파일 형태로 노출한다.
| 경로 / 도구 | 내용 | 예 |
|---|---|---|
/proc | 프로세스 정보, 커널 통계 | /proc/version, /proc/modules |
/proc/sys | 실행 중 변경 가능한 커널 파라미터 | /proc/sys/kernel/randomize_va_space |
/sys | 장치·드라이버·모듈 구조 (sysfs) | /sys/module/ |
sysctl | /proc/sys 값을 읽고 쓰는 도구 | sysctl net.ipv4.ip_forward |
dmesg, journalctl -k | 커널 링 버퍼(커널 메시지) | 드라이버 오류, USB 연결 |
5.14.0-427.13.1.el9_4.x86_64
│ │ │ │ │ └ 아키텍처
│ │ │ │ └ 배포판 태그 (el9 = RHEL 9 계열, _4 = 9.4)
│ │ │ └ 배포판 빌드 번호 (패치가 쌓일수록 증가)
│ └──┴ 업스트림 커널 버전 (major.minor.patch)
위 버전 문자열은 형식을 설명하기 위한 예시다.
RHEL 계열은 업스트림 버전(5.14.0)을 유지한 채 보안 패치를 백포트(backport) 한다. 따라서 "5.14는 오래된 버전이니 취약하다"처럼 숫자만 보고 판단하면 안 되고, 배포판 보안 공지(Errata / USN)와 설치된 패키지 버전을 기준으로 판단 해야 한다. 관제 보고서에 취약점 영향 여부를 적을 때 자주 틀리는 부분이다.
Rocky Linux 9 서버에서 커널 정보를 확인했다.
# 1) 커널 버전과 빌드 정보
uname -r
uname -a
cat /proc/version
# 2) 설치된 커널 패키지 (RHEL 계열)
rpm -q kernel
# Ubuntu: dpkg -l 'linux-image-*' | grep ^ii
# 3) 로드된 커널 모듈
lsmod | head -15
lsmod | wc -l
modinfo xfs | head -8
# 4) 커널 오염(tainted) 상태
cat /proc/sys/kernel/tainted
# 5) 보안 관련 커널 파라미터
sysctl kernel.randomize_va_space
sysctl kernel.kptr_restrict kernel.dmesg_restrict
sysctl net.ipv4.ip_forward
# 6) 커널 메시지
sudo dmesg -T | tail -20
sudo journalctl -k -b --no-pager | tail -20
# 7) 보안 업데이트 확인
sudo dnf updateinfo list --security | grep -i kernel
# Ubuntu: apt list --upgradable 2>/dev/null | grep linux-image
아래 출력은 형식 설명용 예시다. 환경마다 달라지는 값은
x로 표시했다.
① lsmod
Module Size Used by
xfs xxxxxx 2
nf_tables xxxxxx xxx
libcrc32c xxxxx 3 nf_conntrack,nf_tables,xfs
| 컬럼 | 의미 | 확인 포인트 |
|---|---|---|
| Module | 모듈 이름 | 처음 보는 이름이면 modinfo로 경로·서명 확인 |
| Used by | 사용 중인 횟수와 의존 모듈 | 의존 관계가 이상하게 없는 단독 모듈 |
modinfo <모듈>의 filename:이 /lib/modules/$(uname -r)/kernel/ 아래가 아니거나, signer: 정보가 없으면 배포판 공식 모듈이 아닐 가능성이 있다.
② /proc/sys/kernel/tainted
| 값 | 의미 |
|---|---|
0 | 오염되지 않음 (배포판 공식 모듈만 로드) |
| 0이 아닌 값 | 특정 사건이 있었음 — 비트별로 원인이 다르다 |
대표 비트: 1(bit 0, P) 사유 라이선스 모듈, 4096(bit 12, O) 커널 트리 밖(out-of-tree) 모듈, 8192(bit 13, E) 서명 없는 모듈. 값은 비트의 합이므로 예를 들어 12288은 O + E 다. VMware Tools나 GPU 드라이버처럼 정상적인 이유로도 오염될 수 있으므로, 기준값(baseline)을 기록해 두고 변화가 생겼는지를 본다.
③ sysctl
| 파라미터 | 권장값 | 의미 |
|---|---|---|
kernel.randomize_va_space | 2 | ASLR 활성화 (메모리 주소 무작위화) |
kernel.kptr_restrict | 1 이상 | 커널 메모리 주소 노출 제한 |
kernel.dmesg_restrict | 1 | 일반 사용자의 dmesg 열람 제한 |
net.ipv4.ip_forward | 0 (라우터가 아니면) | 패킷 포워딩 비활성화 |
| 위협 | 원리 | 흔적 / 확인 방법 |
|---|---|---|
| 커널 취약점 권한 상승 | 커널 버그를 이용해 일반 사용자 → root | 패치 수준(dnf updateinfo), 비정상 root 쉘 |
| 커널 모듈 루트킷 | root 권한으로 악성 모듈을 올려 프로세스·파일·연결을 숨김 | 모듈 로드 이벤트, tainted 값 변화, 도구 간 결과 불일치 |
| 커널 파라미터 변조 | ip_forward=1로 바꿔 서버를 중계 지점으로 악용 등 | sysctl -a 기준값 비교, /etc/sysctl.d/ 변경 |
| 보안 기능 비활성화 | ASLR 끄기, SELinux 해제 | randomize_va_space=0, getenforce |
루트킷이 ps나 ls 결과를 숨기더라도, 서로 다른 경로의 정보를 비교 하면 불일치가 드러나는 경우가 많다. 예를 들어 ps에는 없는데 /proc/<PID> 디렉터리는 존재하는 PID, ss에는 없는데 외부 장비(방화벽·IDS)에는 보이는 연결 등이다. 관제에서 호스트 로그와 네트워크 로그를 교차 확인 하는 이유가 여기에 있다.
커널 모듈을 올리고 내리는 System Call을 감사 규칙으로 기록할 수 있다.
# /etc/audit/rules.d/kmod.rules
-a always,exit -F arch=b64 -S init_module,finit_module -k kmod_load
-a always,exit -F arch=b64 -S delete_module -k kmod_unload
sudo augenrules --load # 규칙 적용
sudo auditctl -l | grep kmod # 적용 확인
sudo ausearch -k kmod_load -i # 이벤트 조회
| 점검 항목 | 명령어 | 비정상 판단 기준 |
|---|---|---|
| 커널 버전 · 패치 | uname -r, dnf updateinfo list --security | 미적용 보안 패치 존재 |
| 모듈 목록 | lsmod → 기준값과 diff | 기준값에 없는 모듈 |
| 모듈 로드 이벤트 | ausearch -k kmod_load -i | 작업 일정에 없는 로드 |
| tainted | cat /proc/sys/kernel/tainted | 기준값에서 변화 |
| 보안 파라미터 | sysctl -a → 기준값과 diff | ASLR·포워딩 값 변경 |
| 커널 메시지 | journalctl -k -b | 반복 segfault, 알 수 없는 장치 연결 |
[Event] SIEM: auditd kmod_load 이벤트 (업무 외 시간)
↓
[IOC] 로드된 모듈 이름, 파일 경로, 실행 계정(auid)
↓
[분석] modinfo 경로·서명 확인 → tainted 값 변화 → 같은 시간대 sudo·SSH 로그
↓
[Root Cause] 어떤 계정이 root 권한을 얻어 모듈을 올렸는가
↓
[Response] 서버 격리, 메모리·디스크 증적 확보 후 재설치 검토
커널 루트킷이 의심되면 해당 서버에서 실행한 명령어 결과를 그대로 신뢰하기 어렵다. 그래서 서버 자체 결과보다 외부(SIEM에 미리 전송된 로그, 네트워크 장비 로그)를 우선 증거로 삼는다.
/lib/modules/$(uname -r)/에 있고 lsmod로 확인한다./proc, /sys, sysctl, dmesg/journalctl -k로 본다.다음 글 「3. Shell과 Bash 이해」 에서는 커널 바로 위에서 사용자의 명령을 받아 실행하는 Shell을 다룬다. 로그인할 때 어떤 설정 파일이 어떤 순서로 실행되는지, 명령 이력(history)이 어떻게 저장되는지, 그리고 공격자가 이 구조를 어떻게 악용하고 관제에서는 무엇을 확인하는지 정리한다.