리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.
리눅스 시스템 기초 14 / 50 · Part 2. 파일·명령어·권한
실습 환경: Rocky Linux 9 (10.0.0.200) · xfs
이전 글: 13. Linux 파일 종류
🔗 심화 시리즈 — 「파일 · 권한 · 사용자 관리」
이 주제를 더 깊게 다룬 실무형 보안 시리즈: 13. inode 이해하기 · 14. 하드 링크와 심볼릭 링크 · 15. Linux 파일 timestamp 이해하기 (atime·mtime·ctime) · 16. stat 명령어로 파일 metadata 분석
11편에서 mv는 inode를 유지하고 cp는 새 inode를 만든다는 것을, 13편에서 파일 종류가 inode에 저장된다는 것을 봤다. 이번 글은 이 inode를 정면으로 다룬다.
inode를 이해하면 다음 질문에 답할 수 있다.
마지막 질문은 침해사고 분석의 타임라인 작성 과 직결된다. "공격자가 언제 이 파일을 만들고 바꿨는가"를 판단하는 근거가 타임스탬프이기 때문이다.
inode(index node)는 파일 하나의 메타데이터와 데이터 위치 를 담는 구조체다.
| inode에 있는 것 | inode에 없는 것 |
|---|---|
| 파일 종류, 권한, 소유자(UID/GID), 크기, 링크 수, 타임스탬프, 데이터 블록 위치 | 파일 이름 (디렉터리 항목에 있음) |
파일 시스템마다 inode 개수가 정해져 있어서, 작은 파일이 너무 많으면 공간이 남아도 파일을 만들 수 없다(df -i, 6편).
| 구분 | 하드 링크 (ln) | 심볼릭 링크 (ln -s) |
|---|---|---|
| 정체 | 같은 inode를 가리키는 또 하나의 이름 | 경로 문자열을 담은 별도 파일 (자체 inode) |
| 원본 삭제 시 | 다른 이름으로 계속 접근 가능 | 깨진 링크 (dangling) |
| 파일 시스템 경계 | 넘을 수 없음 | 넘을 수 있음 |
| 디렉터리 대상 | 불가 | 가능 |
ls -l 표시 | 링크 수 증가, 일반 파일처럼 보임 | l + -> 대상 |
| 시각 | 의미 | 바뀌는 때 | 사용자가 임의 지정 |
|---|---|---|---|
| atime | 마지막 접근 | 내용을 읽을 때 (relatime 규칙) | 가능 (touch -a) |
| mtime | 마지막 내용 수정 | 내용이 바뀔 때 | 가능 (touch -m -d) |
| ctime | 마지막 inode 변경 | 권한·소유자·링크 수·내용 변경 | 불가 (시스템 시계로만 기록) |
| btime | 생성 시각 (Birth) | 파일 생성 시 | 불가 |
ctime은 "creation time"이 아니라 change time 이다. 자주 틀리는 부분이다.
생성 시각(btime)은 xfs·ext4와 최신stat(statx 지원)에서Birth:로 표시된다.
매번 읽을 때마다 atime을 기록하면 디스크 쓰기가 많아진다. 그래서 기본 마운트 옵션인 relatime 은 atime이 mtime·ctime보다 이전이거나, 마지막 갱신 후 24시간이 지났을 때만 atime을 갱신한다. 따라서 atime은 "마지막으로 읽은 정확한 시각"으로 쓰기 어렵다.

/home/roror/report.txt를 열면 커널은 디렉터리 /home/roror에서 이름 report.txt를 찾아 inode 번호 를 얻는다.hard.txt는 같은 inode 번호를 가지므로 완전히 같은 파일 이다. 어느 쪽 이름으로 수정해도 같은 내용이 바뀐다.soft.txt는 자기 inode 안에 "report.txt"라는 경로 문자열 을 가지고 있고, 커널이 그 경로를 다시 해석한다.mkdir -p ~/lab14 && cd ~/lab14
echo "v1" > report.txt
# 1) inode 번호와 상세 정보
ls -li report.txt
stat report.txt
# 2) 하드 링크 — 같은 inode, 링크 수 증가
ln report.txt hard.txt
ls -li report.txt hard.txt
# 3) 심볼릭 링크 — 다른 inode
ln -s report.txt soft.txt
ls -li soft.txt
readlink soft.txt
# 4) 원본 삭제 후 비교
rm report.txt
cat hard.txt # v1 (계속 접근 가능)
cat soft.txt # No such file or directory (깨진 링크)
ls -l soft.txt
# 5) 시각 변화 관찰
stat -c 'm=%y c=%z' hard.txt
chmod 600 hard.txt # 권한 변경 → ctime만 바뀜
stat -c 'm=%y c=%z' hard.txt
echo v2 >> hard.txt # 내용 변경 → mtime, ctime 모두
stat -c 'm=%y c=%z' hard.txt
# 6) 특정 시간대에 바뀐 파일 찾기
sudo find /etc -xdev -newermt '2026-09-23 10:00' ! -newermt '2026-09-23 11:00' -ls
# 7) 링크 수 0인데 열려 있는 파일
sudo lsof +L1 2>/dev/null | head
아래 출력은 형식 설명용 예시다.
① stat
File: hard.txt
Size: 6 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 5021 Links: 1
Access: (0600/-rw-------) Uid: ( 1000/ roror) Gid: ( 1000/ roror)
Access: 2026-09-23 11:02:10.xxx +0900
Modify: 2026-09-23 11:03:44.xxx +0900
Change: 2026-09-23 11:03:44.xxx +0900
Birth: 2026-09-23 11:01:58.xxx +0900
| 필드 | 해석 |
|---|---|
Inode: 5021 | 원래 report.txt와 같은 번호 → 같은 파일 |
Links: 1 | report.txt를 지워 하드 링크 하나만 남음 |
Birth | 원본(report.txt)을 만든 시각 — 하드 링크를 만든 시각이 아님 |
② 위조가 의심되는 시각 패턴
/usr/bin/sysupd
Modify: 2019-06-12 08:00:00.000000000 +0900 ← 나노초가 모두 0
Change: 2026-09-23 03:14:51.482193015 +0900
Birth: 2026-09-23 03:14:50.911034222 +0900
| 단서 | 의미 |
|---|---|
| mtime이 btime보다 과거 | 만들어지기 전에 수정될 수는 없다 → 시각 조작 |
나노초가 .000000000 | touch -d로 직접 지정했을 가능성 |
| ctime·btime이 사고 시간대 | 실제로 생성·변경된 시각 |
단, tar·cp -p·rsync -a처럼 원본 시각을 보존하는 정상 작업도 mtime < btime을 만든다. 다른 로그(설치 기록, audit, 로그인 기록)와 함께 판단한다.
| 기법 / 상황 | inode 관점 설명 | 확인 방법 |
|---|---|---|
| 시각 위조 (timestomping) | mtime·atime은 바꿀 수 있지만 ctime·btime은 못 바꿈 | mtime vs ctime/btime 비교 |
| 삭제 후 실행·기록 | 이름은 없지만 프로세스가 열고 있어 inode 유지 | lsof +L1, /proc/*/exe (deleted) |
| 하드 링크 은닉 | 민감 파일에 다른 이름을 붙여 다른 경로에 보관 | 같은 inode 검색 find / -xdev -inum <번호> |
| 심볼릭 링크 악용 | 로그·history를 /dev/null로 연결, /tmp 링크 공격 | find -type l -lname '/dev/null' |
| inode 고갈 | 작은 파일 대량 생성으로 새 파일 생성 불가 | df -i |
# 사고 추정 시간대에 변경(ctime)된 파일 — 위조가 어려운 ctime 기준
sudo find / -xdev -newerct '2026-09-23 03:00' ! -newerct '2026-09-23 04:00' \
-printf '%C+ %M %u %p\n' 2>/dev/null | sort | head -50
| 옵션 | 기준 시각 |
|---|---|
-newermt | mtime |
-newerct | ctime |
-newerBt | btime (지원 환경) |
# /dev/null 로 연결된 링크 (history 회피 흔적)
sudo find /root /home -xdev -type l -lname '/dev/null' -ls 2>/dev/null
# 깨진 심볼릭 링크 (삭제된 대상)
sudo find /etc /usr/local -xtype l -ls 2>/dev/null
[Event] 무결성 점검: /usr/bin/sysupd 신규 파일
↓
[stat] mtime 2019년(나노초 0) / ctime·btime 2026-09-23 03:14 → 시각 위조
↓
[타임라인] 03:00~04:00 ctime 변경 파일 목록 → 함께 생성된 cron·서비스 파일
↓
[교차 확인] 같은 시각 secure 로그의 로그인, audit 의 execve 기록
↓
[Response] 파일 해시·사본 보존 → 관련 지속성 설정 제거 → 계정 조치
touch로 바꿀 수 있지만 ctime·btime은 사용자가 지정할 수 없다. 타임라인은 ctime 기준이 더 믿을 만하다.find -newerct로 사고 시간대 변경 파일을 뽑아 타임라인을 만든다.다음 글 「15. Linux 파일 권한 이해」 에서는 inode에 저장된 권한(rwx)이 파일과 디렉터리에서 각각 무엇을 의미하는지, 커널이 소유자·그룹·기타 중 어떤 권한을 적용하는지 정리한다.