---
description: 'DATE : 2023/9/17'
---

# File Upload Vulnerability \[3]

## <mark style="color:blue;">File Upload Vulnerability - Labs</mark>

앞선 글에서는 파일 업로드 공격에 대한 <mark style="color:blue;">**그 어떤 조치도 취하지 않는 경우**</mark>를 살펴보았다.

사실 파일을 업로드하는 기능과 관련해 아무런 조치도 취하는 않는 경우는 보기 드물다고 한다.



반대로 결함이 없다고 생각을 하거나 어느 정도 보안 절차가 잘 갖추어졌다고 착각하는 경우!

사실은 파일 업로드 취약점이 존재해 이런 보안 절차를 우회 가능한 상황들이 더 많다고 한다.&#x20;



이번에는 그 중에서도 <mark style="color:blue;">**파일 타입**</mark>을 확인해 image file만을 업로드할 수 있도록&#x20;

제한된 경우를 살펴볼 것이다.



"파일 타입을 제한했는데 뭐가 문제야!" 라는 착각을 하게 되는 경우,&#x20;

어떤 방법으로 공격 받을 수 있는 지 바-로 알아보도록 하자.&#x20;

***

### <mark style="color:blue;">**\[ LAB#2 ]**</mark>



<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2Fr26Dj3NdrYoHq2EOCntW%2Fimage.png?alt=media&#x26;token=861710ab-265c-4e94-9903-716346d65415" alt=""><figcaption></figcaption></figure>

LAB으로 들어가면 우측 상단에 있는 My account 버튼을 눌러Login 페이지로 이동할 수 있다.&#x20;



<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2F9lzjx9Llh3uhkgirC3AE%2Fimage.png?alt=media&#x26;token=777fef19-fe62-4e10-8df3-86b07ca1a9d1" alt=""><figcaption></figcaption></figure>

LAB에서 기본적으로 제공하는 wiener:peter 계정으로 로그인한 후



이전 LAB과 동일하게 업로드할 파일을 선택한다.

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

첫 번째 LAB에서 사용한 코드와 동일한 webshell.php를 선택했다.



이제 Upload 버튼을  눌러보자!

<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2F3S2cXQOSMT9MOx7mzBIz%2Fimage.png?alt=media&#x26;token=8c1ab2ef-a0d9-416e-9b91-4884699108bd" alt=""><figcaption></figcaption></figure>

파일 업로드를 시도했더니 <mark style="color:blue;">**"Only image/jpeg & image/png"**</mark>인 파일만 올릴 수 있다고 한다.&#x20;

여기서 이전 LAB과의 차이점을 알 수 있다.



이미지 파일을 업로드하는 form에서 PHP file을 업로드해도 아무런 문제 없이&#x20;

파일을 올릴 수 있었던 이전 LAB과는 다르게 이번에는&#x20;

<mark style="color:blue;">**업로드할 파일의 유형이(file type) image/jpeg OR image/png 인지 확인**</mark>하고 있다.



그렇다는 건 서버에서는 어떤 값을 통해 업로드 하려는 파일이 이미지 파일인지 아닌 지를

확인하고 있다는 것인데..! 어떤 데이터를 가지고 확인하는 지 packet을 통해 알아보자 :yum:





<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2FeLel9HoqC6BGUf2Wk4l2%2Fimage.png?alt=media&#x26;token=4db18601-7ef8-442a-bbab-fa42848d740c" alt=""><figcaption></figcaption></figure>

다시 파일을 선택해서 Upload 버튼을 누르는 데, 이때 packet을 딱! 잡아보면



<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2FpBEdh47B6GRZoX24Psm5%2Fimage.png?alt=media&#x26;token=fe077f92-cd43-4c90-8a77-7e83a530d995" alt=""><figcaption></figcaption></figure>

위와 같은 내용을 볼 수 있을 것이다.

현재 packet에서는 총 3가지의 데이터를 보내고 있는 걸 확인할 수 있다.



**첫 번째 데이터 ) 업로드 한 파일**

```
Content-Disposition: form-data; name="avatar"; filename="webshell.php"
Content-Type: application/x-php

~php code~
```

사용자가 업로드 하고자 한 파일의 정보를 기재해둔 부분으로&#x20;

Content-Disposition header를 통해 이 데이터는 파일명이 "webshell.php"이고 내용이 \~php code\~이며

Content-Type header를 통해 이 파일의 유형이 php인 걸 서버에 알려주고 있다.&#x20;



**두 번째 데이터 ) 파일 업로드를 요청한 계정 이름**

```
Content-Disposition: form-data; name="user"

wiener
```

두 번째 데이터는 계정 이름에 대한 데이터를 알려주고 있다.



**세 번째 데이터 ) csrf**&#x20;

```
Content-Disposition: form-data; name="csrf"

4OwD~~v5fh
```

세 번째 데이터는 CSRF 공격을 방지하기 위해 서버에서 만들어 준 CSRF token 값을 다루고 있다.



세 가지 데이터에 대해 Content-Disposition header로 기본적인 정보를 알려주고 있는 데

<mark style="color:blue;">PHP file과 연관된 부분에만</mark> <mark style="color:blue;"></mark><mark style="color:blue;">**Content-Type header**</mark>가 존재하는 걸 볼 수 있다.



<mark style="color:blue;">**Content-Type header**</mark>는 <mark style="background-color:blue;">**application/x-php와 같이 파일 유형에 대한 정보를 알려주는 헤더**</mark>로&#x20;

서버는 이 header의 값을 보고 지금 전달하고자 하는 파일이 어떤 유형 인지를 알 수 있다.&#x20;



이번 LAB에서는 file type이 오직 image/jpeg or image/png 이어야 한다고 했으므로

Content-Type 값을 조작해 packet을 보내볼까 한다.





<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2FhPfgm5TLqcM4o3XI2EJN%2Fimage.png?alt=media&#x26;token=77a2d60b-c940-4582-aa25-233f004d9f57" alt=""><figcaption></figcaption></figure>

다른 부분은 손대지 않고 Content-Type 값만 image/jpeg로 바꿨다.

이 상태로 packet forward를 하면&#x20;



<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2Fc8ghRWs3M76iPut4GoNT%2Fimage.png?alt=media&#x26;token=7c1bf3e6-e8b8-468e-a1f9-23c8c91ea73b" alt=""><figcaption></figcaption></figure>

성공적으로 파일이 업로드 되었다고 한다!! :thumbsup:

파일을 올렸으니 이제는 실행시킬 일만 남았다..!



<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2FRWoDOToSMebI4XBRwzQT%2Fimage.png?alt=media&#x26;token=6f8c5d43-8798-452e-9606-829e0c10d6ec" alt=""><figcaption></figcaption></figure>

URL 바에 /files/avatars/webshell.php를 입력하면 업로드한 파일이 실행되면서&#x20;

/home/carlos/secret file 내용을 알 수 있게 된다.

(여기서 주목할 점은 현재 공격자의 계정은 wiener인데, carlos 계정의 파일을 읽을 수 있다는 것!)





<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2F2nB8BOtFCAcrpBzWwNbJ%2Fimage.png?alt=media&#x26;token=35f1d792-7a5c-4e02-bc32-0af8e8dc9a0b" alt=""><figcaption></figcaption></figure>

찾아낸 flag를 제출하면&#x20;



<figure><img src="https://2050385856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnJpS96NZbYerJIEOTo8i%2Fuploads%2Fq15Chc0r06l5PMDwOSYb%2Fimage.png?alt=media&#x26;token=f34fbeac-68c1-4881-a542-4ad6897cac7f" alt=""><figcaption></figcaption></figure>

이번 LAB도 마무리 =D



***

이번 LAB에서는 파일 유형을 확인해 서버에서 업로드 할 수 있는 파일 유형을 제한해두고 있었다.

하지만, Content-Type header 값을 바꿈으로써 간단하게 검증 체제를 우회했다..!



그럴 수 있었던 이유는 정말 단순하게 <mark style="color:blue;">**Content-Type 값만 확인**</mark>했기 때문이다.

"Content-Type: image/jpeg"의 의미는 업로드 할 파일이 이미지 파일이라는 건데

<mark style="background-color:blue;">**실제로 업로드 할 파일의 확장자가 jpeg인지 또는 파일 내용이 jpeg 값 인지 확인**</mark>하는 과정이 없다!!



그렇다 보니 Content-Type header 값만 조작해서 파일 유형을 확인하는 과정을 통과하고

실제로는 PHP code가 서버로 업로드 되는 것이다.&#x20;



이렇게 파일 업로드 공격을 예방하기엔 빈 틈 있는 검증 체제가 존재할 수 있다는 것이고

결함이 존재하는 지, 충분한 방어가 이루어지는 지 꼼꼼하게 따져볼 필요성을 보여주는 LAB이었다!&#x20;
