Insecure File Upload

πŸ” Introduction

File uploadλŠ” μ›Ήμ—μ„œ 많이 μ‚¬μš©λ˜λŠ” κΈ°μˆ μž…λ‹ˆλ‹€. λ‘œμ»¬μ— μžˆλŠ” νŒŒμΌμ„ μ„œλ²„λ‘œ μ—…λ‘œλ“œν•˜λŠ” κΈ°λŠ₯인데, μ•ˆμ „ν•˜μ§€ μ•Šμ€ 파일이 μ—…λ‘œλ“œ λ˜λŠ” 것은 λ³΄μ•ˆμ μΈ 문제λ₯Ό κ°€μ§‘λ‹ˆλ‹€. 그리고 μ΄λ ‡κ²Œ File Uploadλ₯Ό μ΄μš©ν•œ 곡격듀을 Insecure File Upload, Upload Insecure FIle, FIle Upload 취약점 λ“±μœΌλ‘œ λΆˆλ¦½λ‹ˆλ‹€.

보톡 μ΄λŸ¬ν•œ Insecure File Upload은 쑰건에 따라 WebShell, XSS, CSRF, μ•…μ„± 파일 배포 κ²½μœ μ§€ λ“±μœΌλ‘œ μ‚¬μš©λ˜λ©° XSS 만큼 ꡉμž₯히 넓은 영ν–₯을 κ°€μ§‘λ‹ˆλ‹€.

πŸ—‘ Offensive techniques

Detect

File이 μ—…λ‘œλ“œ λ˜λŠ” ꡬ간은 λͺ¨λ‘ ν…ŒμŠ€νŒ… ν¬μΈνŠΈκ°€ λ©λ‹ˆλ‹€. λŒ€ν‘œμ μœΌλ‘œ 파일 μ—…λ‘œλ“œκ°€ λͺ©μ μΈ κΈ°λŠ₯λ“€, 이미지 등을 μ—…λ‘œλ“œ ν•˜λŠ” κΈ°λŠ₯듀이며 μ΄λŸ¬ν•œ 뢀뢄은 눈으둜 직접 μ‹λ³„ν•˜κ±°λ‚˜ λ„κ΅¬λ“€μ˜ Passive Scan을 ν†΅ν•΄μ„œ 식별할 수 μžˆμŠ΅λ‹ˆλ‹€.

File Type 별 Attack Vector

Extensions Attack Vectors
JSP, ASP, PHP (ASPX, PHP5, Etc) Webshell / RCE
SVG, XML (And XML Based File) Persistant XSS / SSRF / XXE
GIF Persistant XSS / SSRF
CSV CSV injection
AVI, MP4, MPEG (Videos) LFI / SSRF
HTML, JS HTML injection / XSS / Open redirect
PNG, JPEG Persistant XSS, Pixel flood attack (DoS)
ZIP RCE via LFI / DoS
PDF, XSLX, PPTX, DOCS (OXML) SSRF / BLIND XXE

Exploitation

WebShell

Upload된 파일이 λ™μž‘ν•˜λŠ” μ„œλ²„κ°€ PHP, JSP, ASP, Perl λ“± 파일 자체둜 Server-side λ™μž‘μ΄ κ°€λŠ₯ν•œ 경우 이λ₯Ό 톡해 μ›Ήμ‰˜μ„ μ—…λ‘œλ“œν•˜μ—¬ μ‹œμŠ€ν…œμ„ νƒˆμ·¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Extensions

PHP

.php
.php3
.php4
.php5
.php7
.pht
.phps
.phar
.phpt
.pgif
.phtml
.phtm
.inc

JSP

.jsp
.jspx
.jsw
.jsv
.jspf

ASP

.asp
.aspx
.cer
.asa
.aspx;1.jpg (IIS <= 7.5)
.soap (IIS < 7.0) 

Perl

.pl
.pm
.cgi
.lib

Flash

.swf

Erlang Yaws Web Server

.yaws

Coldfusion

.cfm
.cfml
.cfc
.dbm

XSS

Uploadν•œ 파일의 κ²½λ‘œμ— μ ‘κ·Όν•  λ•Œ Content-Type이 text/html, application/xml λ“± λΈŒλΌμš°μ €μ—μ„œ 슀크립트 λ™μž‘μ΄ κ°€λŠ₯ν•œ Type인 경우 Persistant XSS와 λ™μΌν•˜κ²Œ λ™μž‘ν•©λ‹ˆλ‹€. 이 λ•Œ μ—…λ‘œλ“œλœ λ„λ©”μΈμ˜ μ—­ν• κ³Ό κΆŒν•œμ΄ μ€‘μš”ν•˜λ©°, μ‹€μ œ μ„œλΉ„μŠ€ 도메인과 같은 경우 μ„œλΉ„μŠ€ λ„λ©”μΈμ˜ μΏ ν‚€λ₯Ό νƒˆμ·¨ν•˜κ±°λ‚˜ μ£Όμš” λ³΄μ•ˆ μ •μ±…(SOP, CSP λ“±)을 μš°νšŒν•  수 μžˆμ–΄ λ¦¬μŠ€ν¬κ°€ λ†’μŠ΅λ‹ˆλ‹€.

Overwrite Config

.htaccess λ“± μ„œλΉ„μŠ€μ—μ„œ config λͺ©μ μœΌλ‘œ μ‚¬μš©λ˜λŠ” νŒŒμΌμ„ μ—…λ‘œλ“œν•˜μ—¬ μ‹œμŠ€ν…œ 섀정을 λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 점을 μ΄μš©ν•˜μ—¬ λ‹¨μˆœν•œ File Uploadμ—μ„œ RCEλ‚˜ WebShellκΉŒμ§€ 리슀크λ₯Ό ν™•μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

.htaccess
web.config
httpd.conf
__init__.py

.htaccess - run .php file

php_flag engine on

.htaccess - source code disclosure

php_flag engine off

package.json

"scripts": {
    "prepare" : "/bin/touch /tmp/pwned.txt"
}

composer.json

"scripts": {
    "pre-command-run" : [
    "/bin/touch /tmp/pwned.txt"
    ]
}

For 3rd Party CVE

File Uploadλ₯Ό 톡해 μ—…λ‘œλ“œλœ 파일이 λ‹€λ₯Έ CLI Applicationμ΄λ‚˜ Library λ“±μœΌλ‘œ μ²˜λ¦¬λ˜λŠ” κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€. λŒ€ν‘œμ μœΌλ‘œ FFMpeg, Image Magick 이며 μ΄λŸ¬ν•œ 3rd Partyκ°€ μ‚¬μš©λ˜λŠ” ꡬ간이라면 μ•Œλ €μ§„ CVE λ₯Ό μ΄μš©ν•΄μ„œ RCE λ“±μœΌλ‘œ μ—…κ·Έλ ˆμ΄λ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ZIP Slip

μ—…λ‘œλ“œλœ νŒŒμΌμ„ μ„œλ²„μ—μ„œ zip, tar, jar λ“±μœΌλ‘œ μ••μΆ• ν•΄μ œν•˜λŠ” 경우 ZIP Slip 곡격에 μ·¨μ•½ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

β”œβ”€β”€ dir1
β”‚Β Β  β”œβ”€β”€ file1.txt
β”‚Β Β  β”œβ”€β”€ file2.txt
β”œβ”€β”€ ../../../../../../evil.sh

ZIP Slip은 μ••μΆ• 파일 내뢀에 Path Traversal ꡬ문을 ν¬ν•¨ν•œ νŒŒμΌμ„ 넣어두어 μ••μΆ• ν•΄μ œ μ‹œ κ³΅κ²©μžκ°€ μ›ν•˜λŠ” κ²½λ‘œμ— νŒŒμΌμ„ μœ„μΉ˜μ‹œν‚€λŠ” κΈ°λ²•μž…λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜ 링크λ₯Ό μ°Έκ³ ν•΄μ£Όμ„Έμš”.

Cullinan > ZIP Slip

OXML XXE

μ„œλ²„κ°€ pptx, xlsx λ“± Office κ΄€λ ¨ νŒŒμΌμ„ μ²˜λ¦¬ν•˜λŠ” 경우 OXML XXE에 μ·¨μ•½ν•  κ°€λŠ₯성이 λ†’μŠ΅λ‹ˆλ‹€. OXML XXEλŠ” Offirce κ΄€λ ¨ 파일의 νŠΉμ„±(ZIP 포맷이며 내뢀에 XML νŒŒμΌμ„ 가지고 있음)을 μ΄μš©ν•˜μ—¬ XXEλ₯Ό μˆ˜ν–‰ν•˜λŠ” λ°©λ²•μœΌλ‘œ μ—…λ‘œλ“œλœ λ¬Έμ„œ νŒŒμΌμ„ νŒŒμ‹±ν•˜λŠ” 경우 ν•΄λ‹Ή 곡격에 영ν–₯을 받을 수 μžˆμŠ΅λ‹ˆλ‹€.

β”œβ”€β”€ /_rels/.rels
β”œβ”€β”€ [Content_Types].xml
β”œβ”€β”€ Default Main Document Part
β”‚Β Β  β”œβ”€β”€ /word/document.xml
β”‚Β Β  β”œβ”€β”€    /ppt/presentation.xml ⬅️ ν•΄λ‹Ή νŒŒμΌμ— XXE μ½”λ“œ μ‚½μž…
β”‚Β Β  β”œβ”€β”€    /xl/workbook.xml
...

μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜ 링크λ₯Ό μ°Έκ³ ν•΄μ£Όμ„Έμš”.

OOXML XXE Vulnerability (Exploiting XXE In file upload Function!)

Bypass protection

Double Extensions

.jpg.php

Reverse double extension

.php.jpg

Upper/LowerCase

.PhP
.PHp5
.JSp
.asP

Null byte

.php%00.gif
.php\x00.gif
.php%00.png
.php\x00.png
.php%00.jpg
.php\x00.jpg

RTLO

RTLOλŠ” Right to Left Override둜 였λ₯Έμͺ½μ—μ„œ μ™Όμͺ½μœΌλ‘œ 글씨λ₯Ό μ“°λŠ” μ–Έμ–΄κΆŒμ˜ 문자 포맷을 μ΄μš©ν•œ λ°©λ²•μž…λ‹ˆλ‹€.

name.%E2%80%AEphp.jpg

Blank char

file.php%20

CRLF

file.php%0d%0a.jpg

Magic Byte

PNG: \x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03[
JPG: \xff\xd8\xff
GIF: GIF87a OR GIF8;

ADS

file.asp:123.jpg

More special chars

file.php........
file.jsp/././././.

Bypass MIME

μ—…λ‘œλ“œ μ‹œ Content-Type을 ν—ˆμš©λœ Type으둜 λ³€κ²½ν•©λ‹ˆλ‹€. Content-Type 기반의 검사 λ‘œμ§μ„ μš°νšŒν•  수 μžˆμŠ΅λ‹ˆλ‹€.


Content-Type : image/gif
Content-Type : image/gif
Content-Type : image/png
Content-Type : image/jpeg

Truncate File

Linux, macOS, Windows 그리고 JSP, ASP, PHP λ“± Application λͺ¨λ‘ μ„œλ‘œ μ²˜λ¦¬ν•  수 μžˆλŠ” 파일의 μ΅œλŒ€ 크기와 버퍼 크기가 λ‹€λ¦…λ‹ˆλ‹€. μ΄λŸ¬ν•œ 차이λ₯Ό μ΄μš©ν•˜μ—¬ 파일 μ΄λ¦„μ˜ 길이λ₯Ό μž˜λ¦¬λ„λ‘ μœ λ„ν•˜μ—¬ ν™•μž₯자 검사λ₯Ό μš°νšŒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

POST /upload

-----------------------------313131052934083662144000709583
Content-Disposition: form-data; name="file"; filename="AAAAA.....php.jpg"
Content-Type: image/jpeg

예λ₯Όλ“€μ–΄ μœ„μ™€κ°™μ΄ 파일 μ—…λ‘œλ“œ μ‹œ php.jpg둜 μ—…λ‘œλ“œν•˜μ—¬ ν™•μž₯자λ₯Ό application에선 jpg둜 인식 μ‹œν‚€μ§€λ§Œ, νŒŒμΌμ„ μ €μž₯ν•  λ•Œ 길이 차이둜 인해 php κΉŒμ§€ μž˜λ¦¬λŠ” 경우 μ‹€μ œ μ—…λ‘œλ“œλœ νŒŒμΌμ€ php ν™•μž₯자λ₯Ό κ°€μ§€κ²Œλ©λ‹ˆλ‹€.

More

이외에도 정말 λ§Žμ€ 방법듀이 μ‘΄μž¬ν•©λ‹ˆλ‹€. μ„œλ²„μ˜ 검증 λ‘œμ§μ„ νŒŒμ•…ν•˜κ³ , 이에 따라 λ§žμΆ€ν˜• 우회 νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ—¬ μ•…μ˜μ μΈ νŒŒμΌμ„ μ—…λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€ :D

πŸ›‘ Defensive techniques

Defense Mechanism

기본적으둜 File UploadλŠ” ν•œκ°€μ§€μ˜ λŒ€μ‘ λ°©μ•ˆμ΄ μ•„λ‹ˆλΌ μ—¬λŸ¬κ°€μ§€μ˜ λŒ€μ‘λ°©μ•ˆμ„ ꡐ차 μ μš©ν•˜μ—¬ λŒ€μ‘ν•΄μ•Όν•©λ‹ˆλ‹€. 각각의 λ°©μ•ˆ λͺ¨λ‘ 우회의 여지가 있기 λ•Œλ¬Έμ— μ—¬λŸ¬κ²ΉμœΌλ‘œ 검증 둜직이 μ‘΄μž¬ν•΄μ•Ό μ›ν•˜λŠ” 곡격으둜 λΆ€ν„° μ•ˆμ „ν•΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.

In Upload Function

Check file extension

ν™•μž₯자 κ²€μ‚¬λŠ” κ°€μž₯ File Upload의 κ°€μž₯ 기본적인 λŒ€μ‘λ°©μ•ˆμž…λ‹ˆλ‹€. μ—…λ‘œλ“œλ˜λŠ” 파일의 ν™•μž₯자λ₯Ό ν—ˆμš©ν•  ν™•μž₯자만 Allow-list ν˜•νƒœλ‘œ μ²΄ν¬ν•©λ‹ˆλ‹€.

.jpg => O
.png => O
.svg => X
.php => X
.html => X

Check file MIME

File upload μ‹œ MIME Type에 λŒ€ν•œ 검증도 λŒ€μ‘λ°©μ•ˆ 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€. 일반적으둜 ν™•μž₯자 검사 λ˜λŠ” File header 검사와 λ³‘ν–‰λ©λ‹ˆλ‹€.

Content-Type: image/jpeg => O
Content-Type: text/html => X

Check file header

파일 μ—…λ‘œλ“œ μ‹œ μ—…λ‘œλ“œλœ 파일의 Headerλ₯Ό κ²€μ¦ν•˜μ—¬ λŒ€μ‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이미지 μ—…λ‘œλ“œ λ“± νŠΉμ • 파일만 ν—ˆμš©ν•˜λŠ” 경우 νš¨κ³Όμ μž…λ‹ˆλ‹€.

ÿØÿàJFIF => O
ThisisHackCode => X

Uploaded server

Content-Type of Uploaded File

μ—…λ‘œλ“œλœ 파일의 Content-Type을 λͺ©μ μ— 맞게 κ³ μ •ν•˜λŠ” ν˜•νƒœλ‘œλ„ λŒ€μ‘μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€. λ˜ν•œ νŒŒμΌμ„ λ‹€μš΄λ‘œλ“œ μ²˜λ¦¬ν•˜λŠ” Content-Disposition: attachment 도 XSS λ“±μ˜ κ³΅κ²©μ—λŠ” 효과적으둜 λŒ€μ‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ§Œμ•½ μ—…λ‘œλ“œλœ 이미지가 μ €μž₯된 μ„œλ²„λΌκ³  κ°€μ •ν•œλ‹€λ©΄, μ•„λž˜μ™€ 같이 Type을 κ³ μ •ν•˜μ—¬ HTML 등이 λ Œλ”λ§λ˜μ§€ μ•Šλ„λ‘ μ œν•œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Content-Type: image/jpeg

Random filename

μ—…λ‘œλ“œλœ νŒŒμΌμ€ μ‚¬μš©μžκ°€ μ „λ‹¬ν•œ 파일 이름과 ν™•μž₯자λ₯Ό κ·ΈλŒ€λ‘œ 쓰기보단 Randomν•˜κ²Œ μƒμ„±ν•œ λ¬Έμžμ—΄λ‘œ κ΄€λ¦¬ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. μ΄λŠ” 파일 이름과 ν™•μž₯자λ₯Ό κΈ°λ°˜μœΌλ‘œν•œ 곡격에 효과적으둜 λŒ€μ‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

MyFile.png => X
6FC2321BF061F344AF2A45A74D2809F540C16907CBD986D8187979C4541E33E8.png => O

Hide upoaded path

μ‚¬μš©μžμ—κ²Œ μ—…λ‘œλ“œλœ νŒŒμΌμ„ μ œκ³΅ν•˜λŠ” 것이 μ•„λ‹ˆλΌλ©΄ μ—…λ‘œλ“œλœ 파일이 μœ„μΉ˜ν•˜λŠ” μ„œλ²„λŠ” λ‚΄λΆ€λ‘œ μˆ¨κΈ°κ±°λ‚˜, 외뢀에 ν•„μš”ν•˜λ”λΌλ„ μ‚¬μš©μžκ°€ μ‰½κ²Œ 경둜λ₯Ό νŒŒμ•…ν•  수 없도둝 μ²˜λ¦¬ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

/uploaded_file/user.txt => X
/A45A74D2809F540C16907CBD986D8/1BF061F344AF2A/user.txt

Use Key/Value Storage

S3 같이 K/V 기반의 StorageλŠ” 기본적으둜 File upload에 μ‚¬μš©λ˜λŠ” μ—¬λŸ¬κ°€μ§€ 기법을 μ‚¬μš©ν•  수 μ—†κ²Œ λ§Œλ“­λ‹ˆλ‹€. κ·Έλž˜μ„œ μ΄λŸ¬ν•œ Storage의 μ„ νƒμœΌλ‘œ 곡격 포인트λ₯Ό 많이 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ•Ή Tools

πŸ“š Articles

πŸ“Œ References