syurhia 님의 블로그

6. File path traversal, validation of file extension with null byte bypass 본문

보안관련/PortSwigger

6. File path traversal, validation of file extension with null byte bypass

syurhia 2026. 5. 29. 21:21

이번에는 개발자가 .png로 끝나는 파일명을 유저에게서 입력받았을 때만 검증을 받고 통과가 되는 코드를 짰을 때를 가정한 문제다.

일명 널바이트 취약점인데(구버전 PHP 5.3미만 환경에서 주로 먹혔던 취약점이라고 한다.), %00이라는 널 바이트를 이용한다.

 

웹서버와 리눅스OS의 차이점에 의해 쓸 수 있는 공격기법인데, 웹서버는 보통 PHP나 Python, Java같은 고급 언어들을 사용한다. 얘네들은 문자열의 길이를 기억하는 방식으로 문자열을 관리한다. 즉, 문자열이 몇 바이트였는지 그 크기를 기억하는 것이다.

리눅스는 C언어로 되어있는데, C언어뿐만 아니라 C++도 포함해서 문자열의 끝을 구분할 때 \0(NULL이다)이라는 특수 문자로 구별한다. 문자열의 크기는 모르고, NULL인지를 확인하는 것으로 끝부분만 알 수 있다.

 

이 차이점이 굉장히 큰데, 웹서버에서는 /var/www/html/../../../etc/passwd\0.png라는 값을 입력받아도 .png라는 값을 제대로 받았으니 이 페이로드는 문제없이 통과하게 된다. 그런데, 이 페이로드가 파일탐색 함수에 들어가게 되는 순간 문제가 발생한다.

파일탐색 함수는 OS가 관리하고 C언어이기 때문에, /var/www/html/../../../etc/passwd까지만 읽고 뒷 부분은 \0(NULL)이니까 버리게 된다. 그래서 결론적으로는 /etc/passwd가 불러진다.

 

이런 문제가 있어서, 고급 언어만 공부하는 게 아니라 저급...언어?(뭔가 어감이 좀 이상한데..찾아보니 로우 레벨 언어이니까 이렇게 부르는 게 맞긴 하다.. 굉장히 껄끄럽네) 도 알아두는 게 좋다.

 

문제를 풀어보자.

그림 1. 취약점이 있는 사이트

그림 1의 사이트에 path traversal취약점이 존재한다고 한다.

이것만으로는 뭐가 문제인지 모르겠으니 페이지 소스를 보자.

그림 2. 페이지 소스

그렇다. 그림2를 보면 알 수 있듯이 이미지 태그에서 서버가 image라는 프로그램을 실행시키는 걸 확인할 수 있다.

filename이라는 변수를 쓰고 있으며 22.jpg라는 값을 전달해주는 것도 확인이 가능하다.

직접적으로 실행하는 것 같으니 여기를 찔러보자.

그림 3. image프로그램 실행 결과

 

22.jpg라는 값을 주면 그림 3과 같은 이미지가 반환된다.

그러면 filename의 값을 ../../../etc/passwd%00.jpg로 해서 서버에 요청을 보내보자. (사실 png로 했다가 다시 한 건 안 비밀)

그림 4. /etc/passwd 불러오기

그림 4와 같이 요청을 보내니 /etc/passwd라는 파일이 돌아왔다.

/etc/passwd가 맞는지 서버의 응답을 보는 것을 통해 확인해보자.

그림 5. Response

음. 맞다.

/etc/passwd가 확실하다.