파일 · 권한 · 사용자 관리 08 / 50 · Part 1. Linux 파일 관리 기초
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정 analyst)
기초편 연계: 「리눅스 시스템 기초」 11. Linux 파일과 디렉터리 관리 · 14. inode와 파일 시스템

1. 들어가며

touch는 보통 "빈 파일을 만드는 명령"으로 소개된다. 하지만 이름 그대로 touch의 본래 목적은 파일의 시간을 건드리는 것 이다. 파일이 없으면 만들고, 있으면 시간을 현재로 갱신하며, 옵션을 주면 임의의 과거 시간 으로도 바꿀 수 있다.

마지막 기능은 공격자가 자주 사용한다. 웹셸이나 백도어를 심은 뒤 주변 파일과 같은 날짜로 시간을 바꿔 ls -lt에서 눈에 띄지 않게 하는 타임스탬프 조작(timestomping) 이다.

이번 글에서는 touch의 파일 생성과 시간 변경 동작을 실제로 재현하고, 조작할 수 있는 시간과 조작할 수 없는 시간 을 구분한다. 네 가지 타임스탬프의 상세 의미는 15편에서 다룬다.


2. 핵심 개념

2-1. touch 동작

상황동작
파일이 없음크기 0인 파일 생성 (-c를 주면 생성하지 않음)
파일이 있음atime·mtime을 현재 시각으로 갱신 (내용은 그대로)

2-2. 주요 옵션

옵션의미예
-aatime만 변경touch -a f
-mmtime만 변경touch -m f
-d "문자열"지정한 날짜로 설정touch -d "2021-03-15 09:00" f
-t [[CC]YY]MMDDhhmm[.ss]숫자 형식 날짜touch -t 202103150900 f
-r 참조파일다른 파일과 같은 시간으로touch -r /etc/hosts f
-c파일이 없으면 만들지 않음touch -c f
-h심볼릭 링크 자체의 시간 변경touch -h link

2-3. 네 가지 시간 (요약)

시간바뀌는 때ls -l 표시
atime내용을 읽을 때 (relatime 정책 적용)ls -lu
mtime내용을 수정할 때기본 표시
ctimeinode(권한·소유자·링크·시간 등)가 바뀔 때ls -lc
birth파일이 생성될 때 (지원 FS에서만)stat의 Birth

3. 동작 원리

touch 와 타임스탬프 조작 — 바꿀 수 있는 시간과 없는 시간

touch는 파일이 없으면 open(O_CREAT)로 만들고, 그다음 utimensat() 시스템 콜로 atime·mtime을 설정한다. 이때 중요한 규칙이 있다.

  1. atime·mtime은 사용자가 원하는 값으로 설정할 수 있다. 파일 소유자(또는 root)라면 과거·미래 어떤 값이든 가능하다.
  2. ctime은 사용자가 직접 설정할 수 없다. inode가 변경되는 순간 커널이 현재 시스템 시각 으로 기록한다. utimensat() 호출 자체가 inode 변경이므로 ctime은 오히려 "조작한 시각"으로 갱신된다.
  3. birth time은 파일 생성 시 한 번 기록된다. ext4, xfs, btrfs처럼 생성 시간을 저장하는 파일 시스템에서만 볼 수 있다.

단, ctime도 절대적인 증거는 아니다. root 권한이 있으면 시스템 시계를 바꾼 뒤 조작하거나, debugfs로 inode를 직접 수정하는 방법이 존재한다. 이런 경우에는 시스템 시계 변경 로그, 다른 파일·로그와의 상호 모순 을 찾아야 한다.


4. 명령어 실습

실습은 실습용 ext4 볼륨(/data)에서 진행했다. ext4는 birth time을 지원한다.

cd /data && mkdir lab08 && cd lab08

# 1) 파일 생성 직후 — 네 시간이 모두 같다
touch new.txt
stat new.txt

# 2) 내용 수정 → mtime, ctime 갱신
sleep 2; echo "data" >> new.txt
stat --printf 'mtime=%y\nctime=%z\n' new.txt

# 3) 타임스탬프 조작 재현
touch -d "2021-03-15 09:00:00" new.txt
stat --printf 'atime=%x\nmtime=%y\nctime=%z\nbirth=%w\n' new.txt
ls -l --time-style=full-iso new.txt

# 4) 조작된 파일 찾기 — mtime 기준 vs ctime 기준
find . -newermt "2026-01-01" -ls
find . -newerct "2026-01-01" -ls
형식 지정자의미
%x / %y / %z / %watime / mtime / ctime / birth (사람이 읽는 형식)
find -newermt 날짜mtime이 날짜보다 최근인 파일
find -newerct 날짜ctime이 날짜보다 최근인 파일

5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · analyst@rocky9-lab — touch 와 timestomping

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

[analyst@rocky9-lab ~]$ cd /data && mkdir lab08 && cd lab08
[analyst@rocky9-lab lab08]$ touch new.txt
[analyst@rocky9-lab lab08]$ stat new.txt
  File: new.txt
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: 700h/1792d	Inode: 12          Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/ analyst)   Gid: ( 1000/ analyst)
Access: 2026-09-24 10:16:04.851687911 +0900
Modify: 2026-09-24 10:16:04.851687911 +0900
Change: 2026-09-24 10:16:04.851687911 +0900
 Birth: 2026-09-24 10:16:04.851687911 +0900
[analyst@rocky9-lab lab08]$ sleep 2; echo "data" >> new.txt
[analyst@rocky9-lab lab08]$ stat --printf 'mtime=%y\nctime=%z\n' new.txt
mtime=2026-09-24 10:16:06.879687923 +0900
ctime=2026-09-24 10:16:06.879687923 +0900
[analyst@rocky9-lab lab08]$ touch -d "2021-03-15 09:00:00" new.txt
[analyst@rocky9-lab lab08]$ stat --printf 'atime=%x\nmtime=%y\nctime=%z\nbirth=%w\n' new.txt
atime=2021-03-15 09:00:00.000000000 +0900
mtime=2021-03-15 09:00:00.000000000 +0900
ctime=2026-09-24 10:16:06.899687923 +0900
birth=2026-09-24 10:16:04.851687911 +0900
[analyst@rocky9-lab lab08]$ ls -l --time-style=full-iso new.txt
-rw-r--r-- 1 analyst analyst 5 2021-03-15 09:00:00.000000000 +0900 new.txt
[analyst@rocky9-lab lab08]$ find . -newermt "2026-01-01" -ls
       11      4 drwxr-xr-x   2 analyst  analyst      4096 Sep 24 10:16 .
[analyst@rocky9-lab lab08]$ find . -newerct "2026-01-01" -ls
       11      4 drwxr-xr-x   2 analyst  analyst      4096 Sep 24 10:16 .
       12      4 -rw-r--r--   1 analyst  analyst         5 Mar 15  2021 ./new.txt

6. 결과 해석

단계관찰해석
생성 직후 statAccess·Modify·Change·Birth 모두 10:16:04.851생성 순간 네 시간이 같다. regular empty file, 크기 0
내용 추가 후mtime·ctime 10:16:06.879내용이 바뀌면 mtime, 크기(inode)가 바뀌어 ctime도 갱신
touch -d 후 atime·mtime2021-03-15 09:00:00.000000000과거로 조작 성공. 나노초가 정확히 .000000000인 점도 특징
touch -d 후 ctime10:16:06.899조작한 순간의 실제 시각 으로 갱신됨
birth10:16:04.851 (변화 없음)최초 생성 시각이 그대로 남아 있다
ls -l --time-style=full-iso2021-03-15 09:00:00ls -l은 mtime을 보여 주므로 조작된 시간만 보인다
find -newermt 2026-01-01new.txt 없음mtime 기준 검색은 조작된 파일을 놓친다
find -newerct 2026-01-01./new.txt 발견ctime 기준 검색은 조작된 파일을 찾아낸다

마지막 두 줄이 실무 결론이다. 침해 조사에서 "최근 변경 파일"을 찾을 때 mtime만 보면 공격자가 의도한 결과를 보게 된다. ctime(-newerct, -cmin, -ctime)을 함께 사용한다.


7. 보안 관점

구분내용
공격 기법MITRE ATT&CK T1070.006 (Indicator Removal: Timestomp) — 파일 시간을 주변 정상 파일과 같게 맞춰 은닉
흔한 패턴touch -r /var/www/html/index.php shell.php — 기존 파일과 동일한 시간으로 위장
판별 단서mtime < ctime 차이가 비정상적으로 큼, 나노초가 .000000000, birth가 mtime보다 늦음
과장 금지cp -p, tar x, rsync -a, 패키지 설치도 원본 mtime을 보존해 같은 패턴을 만든다. 단독 증거가 아니라 다른 로그와 결합 해 판단

정상 사례와 구분하는 기준:

단서정상 가능성이 높은 경우의심 경우
mtime ≪ ctime패키지·백업 복원으로 설치된 파일웹 업로드 폴더의 단일 스크립트 파일
나노초 .000000000tar로 푼 파일(초 단위 보존)단일 파일만 해당
birth > mtime복사·복원 파일최근 생성인데 수년 전 mtime을 가진 실행 파일

8. 보안관제 관점

[Detection]   FIM 알림: /var/www/html/assets/img/logo.php 신규 파일
     ↓
[Evidence]    stat → Modify 2023-05-02 (주변 파일과 동일)
                       Change 2026-09-24 02:13:55  ← 실제 작업 시각
                       Birth  2026-09-24 02:13:54
     ↓
[판단]        이미지 폴더의 .php + mtime/ctime 불일치 → timestomping 된 웹셸
     ↓
[Timeline]    웹 로그 02:13:5x 전후 POST 요청 → 업로드 경로·공격 IP 확인
     ↓
[Response]    파일 보존(해시) → 차단 → 동일 시각(ctime) 파일 전체 검색
              find /var/www -newerct "2026-09-24 02:00" ! -newerct "2026-09-24 02:30"
관점내용
SIEM파일 시간 조작 자체는 기본 로그에 남지 않는다. auditd로 utimensat/utimes 시스템 콜을 감시하면 기록할 수 있지만 정상 이벤트가 많아 민감 경로 한정 으로 적용한다
Timeline타임라인 분석은 ctime·birth 우선, mtime은 참고값으로 사용한다
Evidence증거 수집 시 stat 결과 전체를 저장한다. ls -l의 날짜 하나만 기록하면 조작 여부를 판단할 수 없다

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

실수결과예방
ls -lt로만 최근 파일 조사timestomping된 파일 누락find -newerct, ls -lct 병행
mtime ≠ ctime이면 무조건 공격으로 판단오탐 (패키지·백업 복원)위치·형식·소유자·로그와 결합
증거 파일을 열어 본 뒤 stat 수집atime 변경 가능stat 먼저, 내용 확인은 나중에
touch로 로그 파일을 "초기화"하려 함내용은 그대로, 시간만 바뀜로그 비우기는 logrotate 또는 : > file
birth가 항상 있다고 가정FS·도구에 따라 - 표시stat 출력에서 Birth 지원 여부 확인

10. 실습 체크리스트

[ ] touch 로 빈 파일을 만들고 네 시간이 같음을 확인했다
[ ] 내용 수정 시 mtime 과 ctime 이 함께 바뀌는 것을 확인했다
[ ] touch -d 로 atime·mtime 을 과거로 바꿨다
[ ] ctime 과 birth 가 조작되지 않음을 확인했다
[ ] find -newermt 와 -newerct 결과 차이를 확인했다
[ ] timestomping 과 정상 복원을 구분하는 기준을 정리했다

11. 핵심 정리

  • touch는 파일이 없으면 만들고, 있으면 atime·mtime을 갱신 한다.
  • -d, -t, -r 옵션으로 atime·mtime은 임의의 시간 으로 바꿀 수 있다.
  • ctime은 커널이 현재 시각으로 기록 하므로 일반 사용자는 조작할 수 없고, 조작한 시각이 오히려 ctime에 남는다.
  • birth time은 지원 파일 시스템에서 최초 생성 시각을 보존한다.
  • ls -l과 find -newermt는 mtime 기준이라 timestomping에 속는다. -newerct로 교차 확인 한다.
  • mtime/ctime 불일치는 정상 복원에서도 생기므로 단독 증거로 쓰지 않는다.

12. 다음 편 예고

다음 글 「09. cp로 파일 복사하기」 에서는 복사할 때 무엇이 보존되고 무엇이 바뀌는지 를 확인한다. 증거 파일을 복사할 때 cp만 쓰면 소유자·시간·SUID가 사라지는 이유와, cp -a로 속성을 보존하는 방법을 실습한다.


참고 자료


시리즈 이동

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

0개의 댓글