🦘Bypassing Filters

Many web applications only rely on front-end JavaScript code to validate the selected file format before it is uploaded

we can easily bypass it by directly interacting with the server, skipping the front-end validations altogether. We may also modify the front-end code through our browser's dev tools to disable any validation in place.

Let's say we have an upload image form that blocks our .php file:

Back-end Request Modification

We start by sending the request to burp:

The important thing to look at is filename="HTB.png" and the file content at the end of the request. If we modify the filename to shell.php and modify the content to the web shell we used in the previous section; we would be uploading a PHP web shell instead of an image.

Disabling Front-end Validation

Let's start by [CTRL+SHIFT+C] to toggle the browser's Page Inspector, and then click on the profile image, which is where we trigger the file selector for the upload form:

To get the details of the function checkFile, we can go to the browser's Console by clicking [CTRL+SHIFT+K], and then we can type the function's name (checkFile) to get its details

function checkFile(File) {
...SNIP...
    if (extension !== 'jpg' && extension !== 'jpeg' && extension !== 'png') {
        $('#error_message').text("Only images are allowed!");
        File.form.reset();
        $("#submit").attr("disabled", true);
    ...SNIP...
    }
}

We can add PHP as one of the allowed extensions or modify the function to remove the extension check.

But We can also just remove this function from the HTML code since its primary use appears to be file type validation, and removing it should not break anything.

We can now upload our shell if the verification is on client side and if we did not refresh the page yet since it will not be persistent. If we inspect element and click on our pfp, we should see our web shell ->

<img src="/profile_images/shell.php" class="profile-image" id="profile-image">

And then we can go and look at the webshell in the web page:

http://SERVER_IP:PORT/profile_images/shell.php?cmd=id

Try to bypass the client-side file type validations in the above exercise, then upload a web shell to read /flag.txt (try both bypass methods for better practice)

And now on client side ->

We need to erase the check function:

if(validate()){upload()} becomes upload()

Blacklist Filters

Here we are going to see why using a blacklist of common extensions may not be enough to prevent arbitrary file uploads and discuss several methods to bypass it.

On our new website we tried to intercept an image upload request with Burp, replace the file content and filename with our PHP script's, and forward the request but it did not work

So there is something on the back end retriciting our upload

There are generally two common forms of validating a file extension on the back-end:

  1. Testing against a blacklist of types

  2. Testing against a whitelist of types

We can also check the file type or the file content for type matching. The weakest form of validation amongst these is testing the file extension against a blacklist of extension

To bypass a blacklist of web extensions PayloadsAllTheThings provides lists of extensions for PHP and .NET web applications. We may also use SecLists list of common Web Extensions

Let's try for php:

And they pretty much all work So if we go back in repeater and try modifying the extension with .phtml ->

And to go and verify ->

http://SERVER_IP:PORT/profile_images/shell.phtml?cmd=id

Try to find an extension that is not blacklisted and can execute PHP code on the web server, and use it to read "/flag.txt"

i start by uploading a photo and capturing the request:

I input my webshell, send it to intruder and add the extension for a sniper attack:

I add this little list:https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Upload%20Insecure%20Files/Extension%20PHP/extensions.lst

And it seems to work pretty well:

We forward one of the successful request:

Or we can

Whitelist Filters

the other type of file extension validation is by utilizing a whitelist of allowed file extensions. A whitelist is generally more secure than a blacklist.

Let's say we got the following message:

and after fuzzing we see this output:

We can see that all variations of PHP extensions are blocked

The problem with whitelists is that it checks whether the file name contains the extension and not if it actually ends with it.

We can bypass this flaw by testing with double extensions (e.g. shell.jpg.php), in which case we should be able to pass the whitelist test, while still uploading a PHP script that can execute PHP code.

And the following request would return a webshell:

http://SERVER_IP:PORT/profile_images/shell.jpg.php?cmd=id

In some cases where the regex would be less permissive, we can reverse the extensions (shell.php.jpg) ->

And the web shell would be returned through this request:

http://SERVER_IP:PORT/profile_images/shell.php.jpg?cmd=id

Finally, let's discuss another method of bypassing a whitelist validation test through Character Injection. We can inject several characters before or after the final extension to cause the web application to misinterpret the filename and execute the uploaded file as a PHP script. Here are some of the chars worth trying:

  • %20

  • %0a

  • %00

  • %0d0a

  • /

  • .\

  • .

  • :

This would look like shell.php%00.jpg or shell.aspx:.jpg, which should also write the file as (shell.aspx)

Here is a small bash script to create a list of files worth trying to bypass the whitelist:

for char in '%20' '%0a' '%00' '%0d0a' '/' '.\\' '.' '…' ':'; do
    for ext in '.php' '.phps'; do
        echo "shell$char$ext.jpg" >> wordlist.txt
        echo "shell$ext$char.jpg" >> wordlist.txt
        echo "shell.jpg$char$ext" >> wordlist.txt
        echo "shell.jpg$ext$char" >> wordlist.txt
    done
done

The above exercise employs a blacklist and a whitelist test to block unwanted extensions and only allow image extensions. Try to bypass both to upload a PHP script and execute code to read "/flag.txt"

Last updated