경로 순회 공격(Path Traversal, Directory Traversal)은 공격자가 상위 디렉토리 이동 시퀀스(../)를 이용하여 웹 루트 외부의 파일에 접근하는 취약점이다. 서버 설정 파일, 비밀키, 개인정보 등을 탈취하는 데 사용된다.
공격 원리
정상 요청:
GET /files/report.pdf
→ 서버: /var/www/html/files/report.pdf ✓
공격 요청:
GET /files/../../../etc/passwd
→ 서버: /var/www/html/files/../../../etc/passwd
= /etc/passwd ← 민감한 파일 노출!
취약한 코드
python
# 취약한 파일 다운로드
from flask import Flask, send_file, request
app = Flask(__name__)
@app.route('/download')
def download():
filename = request.args.get('file')
# 취약: 경로 검증 없음
return send_file(f'/var/uploads/{filename}')
# 공격: /download?file=../../../../etc/passwd
우회 기법
기본: ../../../etc/passwd
URL 인코딩: ..%2F..%2F..%2Fetc%2Fpasswd
이중 인코딩: ..%252F..%252Fetc%252Fpasswd
유니코드: ..%c0%af..%c0%afetc/passwd
Null 바이트: ../../../etc/passwd%00.jpg
윈도우 경로: ..\..\..\windows\win.ini
자주 탈취되는 파일
| 파일 | 내용 |
|---|
| /etc/passwd | 사용자 계정 목록 |
| /etc/shadow | 비밀번호 해시 |
| ~/.ssh/id_rsa | SSH 개인키 |
| /proc/self/environ | 환경변수 (시크릿 포함) |
| /app/.env | 애플리케이션 설정 |
| /etc/nginx/nginx.conf | 웹 서버 설정 |
방어 방법
python
import os
from pathlib import Path
SAFE_DIR = Path('/var/uploads').resolve()
def safe_download(filename: str):
# 경로 정규화 후 안전 디렉토리 내에 있는지 확인
requested = (SAFE_DIR / filename).resolve()
if not str(requested).startswith(str(SAFE_DIR)):
raise ValueError("경로 순회 공격 탐지")
if not requested.exists():
raise FileNotFoundError
return requested.read_bytes()
관련 개념