파일 · 권한 · 사용자 관리 04 / 50 · Part 1. Linux 파일 관리 기초
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정analyst)
기초편 연계: 「리눅스 시스템 기초」 12. 절대경로와 상대경로
경로는 Linux에서 파일을 가리키는 주소다. 명령어 대부분이 경로를 인자로 받기 때문에 너무 익숙해서 가볍게 넘기기 쉽지만, 보안 관점에서 경로는 두 가지 공격과 직접 연결된다.
../../../etc/passwd처럼 ..을 이용해 허용된 디렉터리 밖의 파일에 접근PATH 탐색 순서를 이용해 정상 명령 대신 가짜 명령을 실행이번 글에서는 절대경로·상대경로·특수 기호가 커널과 쉘 중 누가, 어떻게 해석하는지 를 정리하고, 두 공격의 원리를 테스트 계정으로 재현한다.
| 구분 | 형태 | 기준점 | 예 |
|---|---|---|---|
| 절대경로 | /로 시작 | 루트 디렉터리 | /etc/ssh/sshd_config |
| 상대경로 | / 이외로 시작 | 프로세스의 현재 작업 디렉터리(cwd) | conf/app.yml, ../logs |
같은 상대경로라도 어느 디렉터리에서 실행했는지 에 따라 전혀 다른 파일을 가리킨다. 그래서 cron·systemd·스크립트처럼 실행 위치가 보장되지 않는 곳에서는 절대경로를 쓰는 것이 원칙이다.
| 기호 | 의미 | 해석 주체 |
|---|---|---|
. | 현재 디렉터리 | 커널 (실제 디렉터리 엔트리) |
.. | 상위 디렉터리 | 커널 (실제 디렉터리 엔트리, /의 ..은 / 자신) |
~ | 현재 사용자의 홈 ($HOME) | 쉘 |
~user | 해당 사용자의 홈 | 쉘 (/etc/passwd 조회) |
- (cd -) | 직전 디렉터리 ($OLDPWD) | 쉘 |
~는 커널이 모르는 기호다. 그래서 C 프로그램이나 설정 파일에 ~/.ssh라고 쓰면 동작하지 않을 수 있다. 쉘이 먼저 /home/analyst/.ssh로 바꿔 준 것이다.
명령어를 이름만으로 실행하면(ls) 쉘은 PATH에 나열된 디렉터리를 왼쪽부터 순서대로 검색해 처음 발견한 실행 파일을 실행한다.

커널은 경로를 / 단위로 나누어 한 칸씩 따라간다. 각 단계에서 해당 디렉터리의 x(통과) 권한 을 검사한다. 그래서 /home/analyst/secret/a.txt를 읽으려면 a.txt의 r 권한만이 아니라 /, /home, /home/analyst, /home/analyst/secret 모두에 x가 있어야 한다 (22편).
..은 문자열 처리가 아니라 디렉터리 안의 실제 엔트리 다. 따라서 /var/www/html/../../../etc/passwd는 커널 입장에서 완전히 정상적인 경로이며 /etc/passwd로 해석된다. 웹 애플리케이션이 사용자 입력을 경로에 그대로 붙이면 이 동작 때문에 Path Traversal이 발생한다.
bash는 명령 이름을 다음 순서로 찾는다.
cd, echo) → 4. hash 캐시 → 5. PATH 순서 검색PATH에 .(현재 디렉터리)나 누구나 쓸 수 있는 디렉터리가 앞쪽에 있으면, 공격자가 그 위치에 ls, sudo, ps 같은 이름의 파일을 두는 것만으로 정상 명령 대신 실행된다. 특히 root가 그 디렉터리에서 명령을 실행하면 가짜 명령이 root 권한으로 실행된다.
# 1) 절대경로 / 상대경로
mkdir -p ~/lab04/app/conf && cd ~/lab04/app/conf
pwd
ls ../../ # 두 단계 위
cd ~/lab04 && ls -l ./app/conf/../conf
# 2) .. 이 정규화되는 결과 (Path Traversal 원리)
realpath -m /var/www/html/../../../etc/passwd
# 3) PATH 와 명령 탐색
echo $PATH
type ls cd passwd
# 4) PATH 하이재킹 재현 (테스트 디렉터리에서만)
printf '#!/bin/bash\necho "[!] fake ls executed as $(id -un)"\n' > ls && chmod +x ls
export PATH=.:$PATH # 위험: 현재 디렉터리를 PATH 맨 앞에 추가
ls # 진짜 ls 대신 가짜가 실행됨
export PATH=${PATH#.:} # 원복
type ls
| 명령 | 의미 |
|---|---|
realpath -m | 경로를 정규화해 최종 절대경로 출력 (-m: 파일이 없어도 계산) |
type | 명령이 alias·builtin·파일 중 무엇이고 어디 있는지 표시 |
${PATH#.:} | PATH 문자열 앞의 .: 제거 (bash 매개변수 확장) |
하이재킹 재현은 테스트 계정의 테스트 디렉터리 에서만, 현재 쉘 안에서만 진행한다.
~/.bashrc나/etc/profile에.을 추가하지 않는다.

텍스트 원본(실제 출력):
[analyst@rocky9-lab ~]$ mkdir -p ~/lab04/app/conf && cd ~/lab04/app/conf
[analyst@rocky9-lab conf]$ pwd
/home/analyst/lab04/app/conf
[analyst@rocky9-lab conf]$ ls ../../
app
[analyst@rocky9-lab conf]$ cd ~/lab04 && ls -l ./app/conf/../conf
total 0
[analyst@rocky9-lab lab04]$ realpath -m /var/www/html/../../../etc/passwd
/etc/passwd
[analyst@rocky9-lab lab04]$ echo $PATH
/home/analyst/.local/bin:/home/analyst/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
[analyst@rocky9-lab lab04]$ type ls cd passwd
ls is hashed (/usr/bin/ls)
cd is a shell builtin
passwd is /usr/bin/passwd
[analyst@rocky9-lab lab04]$ printf '#!/bin/bash\necho "[!] fake ls executed as $(id -un)"\n' > ls && chmod +x ls
[analyst@rocky9-lab lab04]$ export PATH=.:$PATH
[analyst@rocky9-lab lab04]$ ls
[!] fake ls executed as analyst
[analyst@rocky9-lab lab04]$ export PATH=${PATH#.:}
[analyst@rocky9-lab lab04]$ type ls
ls is /usr/bin/ls
| 출력 | 해석 |
|---|---|
/home/analyst/lab04/app/conf | pwd는 항상 절대경로로 현재 위치를 보여 준다 |
ls ../../ → app | conf에서 두 단계 위(lab04)의 내용 |
./app/conf/../conf → total 0 | .과 ..이 섞여도 결국 같은 conf 디렉터리 (빈 디렉터리) |
realpath → /etc/passwd | /var/www/html에서 .. 세 번이면 루트. 웹 루트 밖으로 탈출 한다 |
PATH 앞쪽 /home/analyst/.local/bin:/home/analyst/bin | Rocky의 기본 사용자 PATH에는 사용자 홈 아래 디렉터리가 시스템 경로보다 앞 에 있다 |
ls is hashed (/usr/bin/ls) | 이전에 찾은 경로를 캐시에서 사용 |
cd is a shell builtin | cd는 파일이 아니라 쉘 내부 명령 (06편) |
[!] fake ls executed as analyst | PATH 맨 앞의 .에 있던 가짜 ls가 실행됨 → 하이재킹 성공 |
원복 후 ls is /usr/bin/ls | PATH에서 . 제거 후 정상 명령으로 돌아옴 |
두 번째 type ls 결과가 hashed가 아닌 이유는 PATH를 바꾸면 bash가 hash 캐시를 비우기 때문이다.
PATH 해석에서 한 가지 더 볼 점이 있다. ~/.local/bin과 ~/bin이 /usr/bin보다 앞에 있으므로, 사용자 계정을 탈취한 공격자는 ~/bin/sudo 같은 가짜 명령을 만들어 그 사용자가 입력하는 sudo 비밀번호를 가로챌 수 있다. 계정 탈취 후 권한 상승으로 이어지는 실제 기법이다.
| 공격 | 원리 | 방어 |
|---|---|---|
| Path Traversal | 입력값의 ..이 허용 디렉터리 밖으로 이동 | 입력 검증, 정규화 후 기준 디렉터리 포함 여부 확인, chroot/컨테이너 격리 |
PATH에 . 포함 | 현재 디렉터리의 동명 파일이 먼저 실행 | PATH에 .·상대경로·빈 항목(::) 금지 |
| 사용자 bin 우선 | ~/bin/sudo로 비밀번호 탈취 | 계정 탈취 대응 시 ~/bin, ~/.local/bin, alias 점검 |
| 스크립트의 상대 명령 호출 | root cron 스크립트가 tar만 호출 → PATH 조작 | 스크립트에서 절대경로 사용, 스크립트 상단에서 PATH 고정 |
| sudo의 PATH | sudo 실행 시 PATH가 바뀔 수 있음 | sudoers secure_path 사용 (42편) |
realpath 결과가 /etc/passwd라고 해서 곧바로 취약점은 아니다. 실제로 그 경로를 읽는 프로그램이 사용자 입력을 검증 없이 경로로 쓰는지 가 취약점 여부를 결정한다.
| 탐지 대상 | 데이터 소스 | 탐지 아이디어 |
|---|---|---|
| Path Traversal 시도 | 웹 액세스 로그 | ../, ..%2f, %2e%2e/, ..\ 패턴 + 응답 코드 200 |
| PATH 조작 | 쉘 히스토리, auditd execve | export PATH=., PATH=/tmp: 형태 |
| 사용자 bin에 시스템 명령명 생성 | 파일 무결성 모니터링 | ~/bin/sudo, ~/.local/bin/ls 생성 |
| root가 사용자 쓰기 경로의 파일 실행 | auditd execve + euid=0 | 실행 파일 경로가 /home, /tmp 아래 |
[Detection] 웹 로그: GET /download?file=../../../../etc/passwd 200 1.9KB
↓
[판단] 200 + 응답 크기가 passwd 파일 크기와 유사 → 실제 노출 가능성
↓
[Evidence] 같은 IP의 다른 요청 (/etc/shadow, .ssh/id_rsa 시도 여부)
↓
[Response] 취약 파라미터 차단, 노출된 파일 범위 확인, 계정 비밀번호·키 교체 검토
탐지 시에는 시도(4xx)와 성공 가능성(200 + 응답 크기) 을 구분한다. ../ 문자열이 로그에 있다는 것만으로 침해가 확정되지 않는다.
| 실수 | 결과 | 예방 |
|---|---|---|
| cron 스크립트에서 상대경로 사용 | cron의 cwd는 홈 디렉터리 → 파일을 못 찾음 | 스크립트 안에서 절대경로 |
편하려고 PATH에 . 추가 | 하이재킹 위험 | ./script.sh처럼 명시적으로 실행 |
~가 어디서나 동작한다고 생각 | 설정 파일·프로그램에서 실패 | $HOME 또는 절대경로 사용 |
문자열로 ..만 제거해 검증 | ....// 같은 우회 가능 | realpath로 정규화한 뒤 기준 경로 비교 |
rm -rf $DIR/에서 변수가 빈 값 | rm -rf /로 확장 | ${DIR:?} 사용, 실행 전 echo로 확인 |
[ ] 절대경로와 상대경로의 기준점 차이를 설명할 수 있다
[ ] . 과 .. 은 커널, ~ 은 쉘이 해석한다는 것을 이해했다
[ ] realpath 로 Path Traversal 결과 경로를 확인했다
[ ] type 으로 명령의 실제 위치를 확인했다
[ ] PATH 앞의 . 이 하이재킹을 일으키는 것을 테스트 디렉터리에서 재현했다
[ ] PATH 를 원래대로 복구했다
/부터, 상대경로는 현재 작업 디렉터리 부터 해석된다..과 ..은 실제 디렉터리 엔트리이고, ~와 cd -는 쉘이 치환하는 기호다.x 권한을 검사한다... 정규화 때문에 사용자 입력을 경로에 그대로 붙이면 Path Traversal 이 발생한다.PATH를 왼쪽부터 검색하므로 앞쪽에 쓰기 가능한 경로가 있으면 PATH Hijacking 이 가능하다.../ 문자열은 "시도"이고, 성공 여부는 응답 코드·크기로 판단한다.다음 글 「05. pwd와 ls로 파일 구조 확인」 에서는 pwd의 논리 경로와 물리 경로 차이, 그리고 ls의 주요 옵션(-l, -a, -h, -i, -d, -t)을 분석가가 실제로 쓰는 조합 중심으로 정리한다.