TigerDemon

Path traversal 정의 및 공격 기법 본문

2025-SWLUG/웹해킹

Path traversal 정의 및 공격 기법

호랑2D 2025. 10. 26. 19:20

Path traversal(directory traversal : 디렉터리 탐색)

  • 경로를 조작해서 상위 디렉터리로 이동('../') 및 원래 접근할 수 없는 파일에 접근한다.
  • 공격자가 애플리케이션이 실행되고 있는 서버의 임의의 파일을 읽을 수 있게 만든다.

공격자가 읽을 수 있는 파일

- 애플리케이션 코드 및 데이터

- 백엔드 시스템의 자격 증명(계정, 비밀번호 등)

- 민감한 운영체제 파일

 

일부 공격에는 공격자가 서버의 임의의 파일에 쓰기(write)할 수도 있다.

이렇게 되면 애플리케이션 데이터를 수정하거나 동작을 바꿀 수 있고, 결국 서버를 완전히 장악하는 문제가 발생할 수 있다.

 

공격기법

1. Reading arbitrary files via path traversal(경로 조작을 통한 임의 파일 읽기)

<img src="/loadImage?filename=218.png">

- 어떤 쇼핑 애플리케이션이 상품 이미지를 보여준다고 가정한다.

- 이 애플리케이션은 아래와 같은 HTML로 이미지를 불러온다.

- loadImage URL은 filename 파라미터를 받아 해당 파일을 읽어 반환한다.

- 이미지 파일은 서버의 /var/www/images/ 디렉터리에 저장되어 있다.

/var/www/images/218.png

- 애플리케이션은 사용자가 요청한 filename 값을 이 기본 경로 뒤에 붙여서 파일 시스템 API로 읽는다. 

즉, 위 경로에서 파일을 읽는 것이다.

- 그런데 이 애플리케이션은 path traversal 방어를 전혀 하지 않는다.

- 따라서 공격자는 다음 URL을 요청해 서버의 /etc/passwd 파일을 읽을 수 있다.

http://insecure-website.com/loadImage?filename=../../../etc/passwd

- 이렇게 하면 애플리케이션이 실제로 읽는 경로는 아래와 같다.

/var/www/images/../../../etc/passwd

- 여기서 ../는 디렉터리에서 한 단계 위로 이동하는 의미이다.

- 세 번 반복된 ../../../는 /var/www/images/에서 루트 디렉터리 /까지 올라가고 결국 읽히는 파일은 /etc/passwd이다.

- /etc/passwd는 Unix 기반 운영체제에서 서버 사용자 계정을 저장하는 표준 파일이다.

- 이 기법으로 공격자는 이 파일뿐 아니라 다른 민감한 파일도 읽을 수 있다.

- Windows 시스템에서는 ../아 ..\ 둘 다 디렉터리 이동에 유효하다.

- Windows 서버를 대상으로 한 동일한 공격 예시는 아래와 같다.

https://insecure-website.com/loadImage?filename=..\..\..\windows\win.ini

 

2. Path Traversal 취약점 악용 시 흔히 겪는 장애물 (Common obstacles)

- 사용자 입력을 파일 경로에 넣는 많은 애플리케이션은 path traversal 공격 방어를 구현해둔다.

- 하지만 이런 방어는 종종 우회(bypass)할 수 있다.

- 예를 들어, 애플리케이션이 사용자 입력에서 '../' 같은 디렉터리 이동 시퀀스를 제거하거나 차단하더라도 다양한 방법으로 이를 우회할 수 있다.

filename=/etc/passwd

- 한 가지 방법은 위와 같이 파일 시스템의 루트 디렉터리에서 시작하는 절대 경로를 사용하는 것이다.

- 이렇게 하면 루트 디렉터리를 바로 사용하게 되므로 ../ 같은 경로 이동 없이 파일을 참조할 수 있다.

 

Path Ttraversal 우회 기법 - 심화(참고)

1. 중첩된 traversal 시퀸스 사용

ex) '....//' 또는 '....\/'

애플리케이션의 내부의 '../'를 제거하더라도, 이들은 제거 후 '../'로 다시 변환되어 우회 가능

 

2. 웹 서버에서 필터링하는 경우

어떤 상황 (예: URL 경로, 'multipard/form-data' 요청의 파일 이름)에서는 웹 서버가 '../' 같은 디렉터리 이동 시퀀스를 애플리케이션에 전달하기 전에 제거함

이 경우 URL 인코딩 또는 이중 URL 인코딩으로 우회 가능

../ -> %2e%2e%2f

../ -> %252e%252e%252f(이중 코딩

심지어 비표준 인코딩도 가능할 수 있음

ex) ..%c0%af 또는 ..%ef%bc%8f

 

3. 특정 폴더로 시작해야 하는 경우

어떤 애플리케이션은 파일 이름이 /var/www/images로 시작해야 한다고 요구함

앞부분은 요구 사항을 만족하고 뒤에 ../../../로 실제 목표 파일로 이동 가능

filename=/var/www/images/../../../etc/passwd

 

4. 특정 확장자로 끝나야 하는 경우

예) '.png'로 끝나야 한다고 요구 이때 Null byte 삽입('%00')으로 확장자를 무시 가능

서버는 .png 로 끝난다고 생각하지만 실제 읽는 파일은 /etc/passwd

filename=../../../etc/passwd%00.png

 

취약점 예방

Path Traversal의 취약점을 예방하는 가장 효과적인 방법은 사용자가 제공한 입력(user Input)을 파일 시스템 API에 직접 전달하지 않는 것이다.

대부분의 애플리케이션 기능은 이 방식 대신 더 안전한 방식으로 다시 작성할 수 있다.

만약 사용자 입력을 파일 시스템 API에 넘겨야 한다면, 다음과 같은 2단계 방어를 적용하는 것이 좋다.

 

1. 입력값 검증(Vaildation)

이상적인 방법은 허용된 값(whitelist) 목록과 사용자 입력을 비교하는 것

그게 어렵다면, 입력값이 허용된 문자(예: 알파벳, 숫자)만 포함하는지 확인

 

2. 경로 정규화 + 검증

입력 검증 후, 입력값을 기본 디렉터리(Base Directory)에 붙인다.

플랫폼의 파일 시스템 API를 이용해 경로를 정규화(canonicallize) 한다.

정규화된 경로가 예상한 기본 디렉터리로 시작하는 지 확인한다.

기본 디렉터리 밖으로 벗어나는 요청은 차단한다.

 

코드 예시

File file = new File(BASE_DIRECTORY, userInput);
if(file.getCanonicalPath().startsWith(BASE_DIRECTORY)){
  //process file
}

new File(BASE_DIRECTORY, userInput) -> 사용자 입력을 BASE_DIRECTORY에 이어 붙임

getCanonicalPath() -> 경로로 정규화해서 ../../../같은 traversal 우회 제거

startsWith(BASE_DIRECTORY) -> 정규화된 경로가 여전히 BASE_DIRECTORY 안에 있는지 확인

조건 만족 시에만 파일을 처리(안전한 요청만 허용)