취약점 개요(CWE-22, 99)
"지정된 리소스 경로를 벗어나 허락되지 않은 리소스에 접근할 수 있는 취약점"
경로에는 절대 경로(Absolute Path)와 상대 경로(Relative Path)가 있다.
절대 경로(Absolute Path)는 "C:\windows\test.php" 처럼 처음부터 끝까지의 모든 경로를 의미한다.
상대 경로(Relative Path)는 " C:\windows\" 의 경로에 있다고 가정하면 windows 디렉토리가 중심이 되고, ..\ 로 상위 경로로 이동할 수 있다. 즉 현 디렉토리를 기준으로 한 상대적인 경로이다.
예시로 C:\test2.php 파일이 있을 때 ..\test2.php 로 현재 경로에서 상위 경로로 이동해 test2.php 파일 실행 가능하다.
이를 이용해 허락되지 않은 리소스 접근이 가능하며, Path Traversal 취약점은 경로를 조작(벗어나)하여 허락되지 않은 리소스에 접근할 수 있는 취약점이라 정의할 수 있다.
공격 방법

공격대상 기본 경로에는 index.php 파일 및 2개의 디렉토리, help 경로에는 help.php 파일이 있다.

상위 경로에는 위 사진과 같은 파일들이 있으며, 그 이상으로는 웹 설정 상 웹 루트를 벗어나지 못한다.

cat 명령어와 상대 경로 이동 값을 이용해 상위 경로의 view_source.php 파일 열람이 가능하다. 취약 함수 별 그리고 운영환경에 따라 cat 같은 시스템 명령어가 필요한 것도 있으며, 필요 없는 것도 있다. 이는 상황에 따라 다르다.

절대 경로(Absolute Path)를 이용해도 동일한 결과를 얻을 수 있다.
* 개인용
LFImap 사용, 이 내에 log poisoning, reverse shell, php wrapper 등 기능이 많음. 사용법 학습 필요
예상 피해
정보 유출 가능. 이는 개인정보, 계정정보, 공격 범위 확장을 위한 시스템 정보 등이 있다.
즉 해당 시스템에 있는 가능한 모든 정보를 가져올 수 있으며, 정보 범위는 웹에서 허용하는 최대 범위에 따라 다르다.
또한 서버에서 심볼릭 링크로 이동 가능하도록 설정 시 정보 수집 범위 확장이 가능하다.
보안대책
1. 코드 내 특수 문자 필터링 기능 삽입
2. WAF(Web Application Firewall) 도입
3. 심볼릭 링크 허용 금지
4. 웹 루트 경로 설정
위 중 특수 문자 필터링만 제대로 되어도 문제는 없지만, 다중 보안이 중요하기에 모두 적용하여야 한다.
하나씩 살펴보자.
1. 코드 내 특수 문자 필터링 기능 삽입
안전하지 않은 코드
| import os from django.shortcuts import render def get_info(request): request_file = request.POST.get('request_file') (filename, file_ext) = os.path.splitext(request_file) file_ext = file_ext.lower() if file_ext not in ['.txt', '.csv']: return render(request, '/error.html', {'error':'파일을 열 수 없습니다.'}) with open(request_file) as f: data = f.read() return render(request, '/success.html', {'data':data}) |
request_file 은 사용자 입력 값, 이를 파일명과 확장자를 나눈 후 확장자를 검증한다.
그리고 파일을 오픈한 후 렌더링하여 success.html 로 돌려준다.
파일명에 대한 검증이 없다. 확장자만 맞으면 허용된 범위 내 모든 자료를 가져올 수 있다.
예시로 상위 경로에 secret.txt 파일이 있을 시 ../secret.txt 로 가져올 수 있다.
안전한 코드
| import os from django.shortcuts import render def get_info(request): request_file = request.POST.get('request_file') (filename, file_ext) = os.path.splitext(request_file) file_ext = file_ext.lower() if file_ext not in ['.txt', '.csv']: return render(request, '/error.html', {'error':'파일을 열 수 없습니다.'}) filename = filename.replace('.', '') filename = filename.replace('/', '') filename = filename.replace('\\', '') try: with open(filename + file_ext) as f: data = f.read() except: return render( request, "/error.html", {"error':'파일을 열 수 없습니다.'"} ) return render(request, '/success.html', {'data':data}) |
특수문자를 공백으로 리플레이스한다.
그러나 중요파일로 이동하는 심볼릭 링크가 웹 디렉토리에 있고, 이 사용을 허용할 시 정보 유출이 가능하다.
예시
1. test.lnk -> /etc/secret.txt 로 연결되어 있음
2. test.lnk 접근 시 /etc/secret.txt 열람
| def get_safe_path(filename): safe_path = os.path.realpath(os.path.join(BASE_DIR, filename)) # 절대경로 변환 if not safe_path.startswith(BASE_DIR): # BASE_DIR 내부 파일만 허용 raise ValueError("🚨 경로 탐색 공격 탐지됨!") return safe_path |
위 코드로 보완이 가능하지만, 모든 요청에 대해서 이를 검증하기엔 리소스 낭비이다.
따라서 웹 서버 설정에서 Followsymlink 같은 설정을 이용하여 차단하는 것이 효율적이다.
2. WAF(Web Application Firewall) 도입
ModSecurity, NAXSI, Shadow Daemon, AWS WAF 등 오픈소스 WAF가 많다. 웹 서버에 맞춰 특성화 되어 있는 경우가 대부분이니 이에 맞춰 도입하여야 한다.
| 웹 방화벽 | 사용 서버 및 언어 |
| ModSecurity | Apache, Nginx, IIS |
| NAXSI | Nginx 전용 |
| Shadow Daemon | 독립 실행 (PHP, Python, Perl) |
| OpenWAF | Nginx |
| WebKnight | IIS 전용 |
3. 심볼릭 링크 허용 금지
패스
4. 웹 루트 경로 설정
Apache(httpd.conf 또는 apache2.conf
| DocumentRoot /var/www/html/public <Directory /home/user/public_html> AllowOverride All Require all granted </Directory> |
DocumentRoot 이용하여 웹 루트를 public으로 지정
php 내장 서버 이용 시 php -S 명령과 -t 를 이용해 지정 가능
| php -S localhost:8000 -t /var/www/html |
참고문헌
1. KISA 주요정보통신기반시설 기술적 취약점 분석 평가 방법 상세가이드
2. KISA Python_시큐어코딩_가이드(2023년_개정본)
'주요통신기반시설 취약점 가이드 > 주통기 웹' 카테고리의 다른 글
| 파일 업로드(File Upload) (0) | 2025.03.18 |
|---|---|
| 크로스 사이드 스크립트(XSS) (0) | 2025.03.18 |
| 관리자 페이지 노출 (0) | 2025.02.20 |
| LDAP Injection (0) | 2025.02.19 |
| Buffer Overflow (0) | 2025.02.19 |