파일 · 권한 · 사용자 관리 05 / 50 · Part 1. Linux 파일 관리 기초
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정analyst)
기초편 연계: 「리눅스 시스템 기초」 11. Linux 파일과 디렉터리 관리
pwd와 ls는 Linux를 처음 배울 때 가장 먼저 쓰는 명령이다. 그런데 서버 점검이나 침해 조사에서 이 두 명령을 "제대로" 쓰는 사람은 생각보다 적다.
pwd가 보여 주는 경로가 실제 물리 경로가 아닐 수 있다 는 것ls가 보여 주는 정보는 디렉터리 엔트리와 inode 중 어디에서 온 것인지이번 글은 이 세 가지를 실제 출력으로 확인한다.
| 형태 | 출력 | 설명 |
|---|---|---|
pwd (= pwd -L) | 논리 경로 | 쉘이 기억하는 $PWD. 심볼릭 링크 이름이 그대로 보임 |
pwd -P | 물리 경로 | 심볼릭 링크를 모두 풀어낸 실제 경로 |
모든 프로세스는 커널에 현재 작업 디렉터리(cwd) 를 하나씩 갖고 있다. /proc/<PID>/cwd에서 확인할 수 있으며, 이것은 항상 물리 경로다.
| 정보 | 출처 |
|---|---|
| 파일 이름, inode 번호 | 디렉터리 엔트리 (getdents64 시스템 콜) |
| 종류, 권한, 링크 수, 소유자, 크기, 시간 | inode (statx / lstat 시스템 콜) |
ls만 입력하면 이름만 읽으면 되지만, ls -l은 파일마다 inode를 추가로 읽는다. 파일이 수십만 개인 디렉터리에서 ls -l이 느린 이유다.

ls의 기본 동작에는 두 가지 필터가 있다.
.으로 시작하는 이름을 숨긴다. 커널이 숨기는 것이 아니라 ls 프로그램이 출력에서 빼는 것이다. 그래서 -a만 붙이면 보인다. 파일 시스템에 "숨김 속성"이 따로 있는 것이 아니다 (19편).-d가 필요하다.또한 ls는 출력 대상이 터미널이 아니면(파이프·파일) 한 줄에 하나씩 이름을 출력한다. 이 실습의 ls 결과가 세로로 나온 것도 스크립트로 실행해 출력이 터미널이 아니었기 때문이다. 스크립트에서 ls 출력을 파싱하기보다 find나 stat을 쓰는 것이 안전한 이유이기도 하다.
# 1) 논리 경로 vs 물리 경로
mkdir -p ~/lab05/real && cd ~/lab05 && ln -s real link
cd link && pwd && pwd -P && cd ~/lab05
# 2) 테스트 파일: 숨김 파일, 큰 파일, 빈 파일
echo "x" > .env && head -c 3000000 /dev/zero > big.bin && touch notes.txt
# 3) 옵션별 비교
ls
ls -la
ls -lh big.bin
ls -li notes.txt .env
ls -ld real
ls -lt --time-style=full-iso

텍스트 원본(실제 출력):
[analyst@rocky9-lab ~]$ mkdir -p ~/lab05/real && cd ~/lab05 && ln -s real link
[analyst@rocky9-lab lab05]$ cd link && pwd && pwd -P && cd ~/lab05
/home/analyst/lab05/link
/home/analyst/lab05/real
[analyst@rocky9-lab lab05]$ echo "x" > .env && head -c 3000000 /dev/zero > big.bin && touch notes.txt
[analyst@rocky9-lab lab05]$ ls
big.bin
link
notes.txt
real
[analyst@rocky9-lab lab05]$ ls -la
total 2948
drwxr-xr-x 3 analyst analyst 4096 Sep 24 10:15 .
drwx------ 3 analyst analyst 4096 Sep 24 10:15 ..
-rw-r--r-- 1 analyst analyst 2 Sep 24 10:15 .env
-rw-r--r-- 1 analyst analyst 3000000 Sep 24 10:15 big.bin
lrwxrwxrwx 1 analyst analyst 4 Sep 24 10:15 link -> real
-rw-r--r-- 1 analyst analyst 0 Sep 24 10:15 notes.txt
drwxr-xr-x 2 analyst analyst 4096 Sep 24 10:15 real
[analyst@rocky9-lab lab05]$ ls -lh big.bin
-rw-r--r-- 1 analyst analyst 2.9M Sep 24 10:15 big.bin
[analyst@rocky9-lab lab05]$ ls -li notes.txt .env
984752 -rw-r--r-- 1 analyst analyst 2 Sep 24 10:15 .env
984754 -rw-r--r-- 1 analyst analyst 0 Sep 24 10:15 notes.txt
[analyst@rocky9-lab lab05]$ ls -ld real
drwxr-xr-x 2 analyst analyst 4096 Sep 24 10:15 real
[analyst@rocky9-lab lab05]$ ls -lt --time-style=full-iso
total 2936
-rw-r--r-- 1 analyst analyst 3000000 2026-09-24 10:15:37.283687742 +0900 big.bin
-rw-r--r-- 1 analyst analyst 0 2026-09-24 10:15:37.283687742 +0900 notes.txt
lrwxrwxrwx 1 analyst analyst 4 2026-09-24 10:15:37.259687742 +0900 link -> real
drwxr-xr-x 2 analyst analyst 4096 2026-09-24 10:15:37.259687742 +0900 real
| 출력 | 해석 |
|---|---|
pwd → .../lab05/link | 쉘이 기억한 논리 경로 (링크 이름 유지) |
pwd -P → .../lab05/real | 실제 위치. 조사 기록에는 물리 경로 를 남긴다 |
ls 결과에 .env 없음 | 기본 ls는 점 파일을 출력하지 않는다 |
ls -la의 .env | -a를 붙이자 보임. 이름이 .env인 파일은 웹 프로젝트에서 DB 비밀번호·API 키 를 담는 경우가 많다 |
drwx------ ... .. | 상위 디렉터리 /home/analyst의 권한이 700 이다. Rocky 9는 새 홈 디렉터리를 700으로 만든다 (Ubuntu 24.04는 750, 35편) |
total 2948 | 이 디렉터리 항목들이 차지하는 블록 수 합계(1KiB 단위) |
lrwxrwxrwx ... link -> real | 심볼릭 링크. 크기 4는 대상 문자열 real의 길이 (14편) |
ls -lh → 2.9M | 3,000,000바이트 ÷ 1024² ≈ 2.86MiB → 반올림 표기 |
ls -li 의 984752, 984754 | 홈은 컨테이너 overlay FS에 있어 inode 번호가 크다. 번호 자체보다 같은지·다른지 가 의미 있다 |
ls -lt --time-style=full-iso | 나노초와 시간대(+0900)까지 표시. 여러 서버 로그와 대조할 때 필요 |
-lt 결과에서 .env가 보이지 않는 점도 눈여겨보자. -a 없이 -t만 쓰면 최근에 바뀐 숨김 파일을 놓친다. 침해 조사에서는 ls -lat처럼 -a를 항상 함께 쓴다.
| 점검 목적 | 명령 | 이유 |
|---|---|---|
| 숨김 파일 포함 확인 | ls -la | 공격 도구·설정이 점 파일로 저장되는 경우가 많음 |
| 최근 변경 파일 | ls -lat, ls -lat --time-style=full-iso | 사고 시간대와 비교 |
| 디렉터리 권한 | ls -ld /var/www/html | 파일 목록이 아니라 디렉터리의 w 여부 확인 |
| 소유 계정 불명 | ls -ln | 삭제된 계정의 UID가 숫자로 남은 파일 확인 (37편) |
| 링크 위장 | ls -la 의 -> | 로그 파일이 /dev/null로 링크되어 있는지 |
주의: ls 역시 파일일 뿐이다. 루트킷이 설치된 시스템에서는 ls 자체가 변조되어 특정 파일을 숨길 수 있다. 중요한 조사는 신뢰할 수 있는 바이너리(외부 매체, 정적 빌드 도구) 나 오프라인 분석으로 교차 확인한다.
| 관점 | 적용 |
|---|---|
| Evidence | 조사 명령과 출력은 script 명령이나 tee로 저장하고, 경로는 pwd -P 기준으로 기록 |
| Detection | ls 실행 자체는 탐지 대상이 아니다. 다만 웹 서버 계정(apache, www-data)이 ls, id, whoami를 실행했다면 웹셸 명령 실행 의 강한 신호다 |
| Investigation | 사고 시간대 전후 변경 파일 → ls -lat --time-style=full-iso 또는 find -newermt (15편) |
| Response | 파일을 옮기거나 열기 전에 ls -la + stat 결과를 먼저 기록 (접근 자체가 atime을 바꿀 수 있음) |
[Detection] auditd execve: uid=48(apache) exe=/usr/bin/ls cwd=/var/www/html/upload
↓
[판단] 웹 서버 프로세스가 쉘 명령을 실행할 정상 이유가 거의 없음 → 웹셸 의심
↓
[Evidence] ls -lat --time-style=full-iso /var/www/html/upload → 최근 생성된 .php 확인
↓
[Response] 파일 보존(해시), 웹 로그에서 해당 파일 첫 요청 IP 확인
| 실수 | 결과 | 예방 |
|---|---|---|
ls -lt만 사용 | 최근 바뀐 숨김 파일 누락 | 조사 시 -a 필수 |
ls -l DIR로 디렉터리 권한 확인 | 안의 파일 목록만 보임 | ls -ld DIR |
ls 출력을 스크립트에서 파싱 | 공백·줄바꿈이 든 파일명에서 오작동 | find -print0, stat 사용 |
pwd 결과를 보고서에 그대로 기록 | 링크 경로와 실제 경로 혼동 | pwd -P 기록 |
크기 2.9M을 정확한 값으로 기록 | 해시·크기 대조 시 오차 | 증거 기록은 바이트 단위(ls -l, stat -c %s) |
[ ] pwd 와 pwd -P 결과가 다른 경우를 재현했다
[ ] ls 와 ls -la 에서 .env 가 보이는지 비교했다
[ ] ls -ld 로 디렉터리 자체의 권한을 확인했다
[ ] ls -lh 크기가 반올림된 값임을 확인했다
[ ] ls -lt 와 ls -lat 의 차이를 이해했다
[ ] --time-style=full-iso 로 나노초·시간대를 확인했다
pwd는 논리 경로, pwd -P는 물리 경로다. 조사 기록에는 물리 경로를 남긴다.ls는 이름·inode 번호는 디렉터리 엔트리에서, 권한·소유자·시간은 inode에서 읽는다.ls의 기본 동작이다. -a로 확인한다.ls -ld로 본다.ls -lat --time-style=full-iso다.ls를 실행했다면 명령어보다 실행 주체 가 탐지 포인트다.다음 글 「06. cd와 디렉터리 이동」 에서는 cd가 왜 외부 프로그램이 아니라 쉘 내장 명령이어야 하는지, 그리고 디렉터리의 x 권한이 없으면 소유자 본인도 들어갈 수 없는 이유 를 실습으로 확인한다.