Arbitrary File Upload is a type of command injection technique in which a malicious user can upload a malicious file on the web server (generally a web shell page) to execute arbitrary commands on the web application.
For example, a vulnerable PHP application allows an user to upload a PHP page onto the server, then the newly uploaded malicious page can be browsed by the malicious user to perform malicious actions provided by the newly uploaded PHP page.
In the following guide, we will be using the same vulnerable sample application used in the previous section of Arbitrary Command Injection, to upload a maliciously crafted web shell written in PHP.
Note
A web shell is a shell-like interface (typically a web page with a input field to take command as input and output field to display the executed command output) to remotely interact with the web server hosting the application, allowing execution of arbitrary commands.
How it works
All the examples shown below uses a docker image containing the example application. The guide to install the same can be found on Docker Docs .
A sample application where a gallery is maintained and the user can upload or delete a file from the gallery as per their convenience.
Run the application using docker:
docker run --rm -p8080:80 --name command_injection projectasuras/command_injection
Note: Docker image version shown in the guide is v1.0.0
.
Now navigate to http://127.0.0.1:8080
to access the application’s web portal.
Now’s lets try to upload some images into the application, by clicking on Upload New Image
or navigate to http://127.0.0.1:8080/upload.php
URL. And select the image file you intend to upload.
Now, click on Upload Image
button to upload the image on the application.
Once, the files are uploaded click on Back to Gallery
or navigating the http://127.0.0.1:8080/
endpoint.
Note
If the application supports uploading of a file (in any form possible like direct file upload or input being rendered to a file), then the application needs to be analysed for Arbitrary File Upload vulnerability i.e. uploading of a file which the application developers did not intended to be uploaded onto the server.
As our sample Gallery application is developed to upload images onto the application. Let’s try to upload a pdf
file for testing whether it is allowing a pdf
file to be uploaded onto the server.
Now, let’s hit the Upload Image
button to check whether we have encountered any error not during uploading of a pdf
file.
The application seemed to have uploaded the file by displaying the message “File is valid, and was successfully uploaded.”. But let’s double check whether our asuras.pdf
file have been uploaded to the Gallery or not by visiting the homepage of the application.
Question
How to access this newly uploaded
webshell.php
from our browser?
Let’s try to view the .pdf
file by hitting the View
operation on the Gallery application.
A failed attempt, SAD!!. Seems like the view.php
internally is using image rendering logic and therefore unable to process the pdf
file uploaded by us. But let’s not loose our hopes, if the source code of the application is available then we can look into it to check the directory of the file uploads. If the source code is not available, then we can use directory brute-force approach by trying different keywords such as storage
, upload
, images
, files
, etc.
By performing the above mentioned technique we are able to find the upload path of all the files be /uploads/
. So, let’s modify the URL endpoint to http://127.0.0.1:8080/uploads/asuras.pdf
and view the uploaded pdf
file.
Voila!!! We are able to view the pdf
file uploaded. Now, let’s try to upload a file which can facilitate use to execute arbitrary commands on the Gallery’s application server.
As our Gallery application is written in PHP, let’s try to create a simple PHP web shell.
<?php
if(isset($_REQUEST['cmd'])){
echo "<pre>" . shell_exec($_REQUEST['cmd']) . "</pre>";
}
?>
The above PHP code takes cmd
as a GET
parameter for passing the command to the shell_exec
PHP function to execute arbitrary commands on the shell.
Let’s try to upload this .php
file onto the Gallery application.
Now, let’s hit the Upload Image
button to check whether we have encountered any error or not during uploading of a php
file.
File have been uploaded and can be verified by visiting the index page of the website.
Now, let’s try to access our shell.php
using:
http://127.0.0.1:8080/uploads/shell.php
But the above URL endpoint results in a blank screen, as we have not provided the GET
parameter cmd
while accessing the web shell. Let’s try to execute the id
command.
http://127.0.0.1:8080/uploads/shell.php?cmd=id
The id
command is executed on the web server and the response of the same is visible on the web page, therefore successfully executing the Arbitrary File Upload vulnerability on the Gallery application.
Source Code Evaluation
To evaluate the source code of the application and find the root cause of the vulnerability, we need to evaluate the upload.php
file, as upload.php
is the endpoint allowing us to upload arbitrary files onto the server.
To interactively attach the shell inside docker, use the following command:
docker exec -it command_injection /bin/bash
The source code of upload.php
is as follows:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_FILES['image']) && $_FILES['image']['error'] == UPLOAD_ERR_OK) {
$uploadDir = 'uploads/';
$uploadFile = $uploadDir . basename($_FILES['image']['name']);
// upload the file
if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadFile)) {
$uploadMessage = "File is valid, and was successfully uploaded.";
} else {
$uploadMessage = "Possible file upload attack!";
}
} else {
$uploadMessage = "No file uploaded or upload error occurred.";
}
}
?>
Initially the developer have verified whether the request is a POST
request or not, as mentioned in Line 2
of the file.
if ($_SERVER['REQUEST_METHOD'] == 'POST')
If a POST
request is triggered by the user, then the user is checking whether a file named image
is passed as part of the data and no error is encountered during the upload.
if (isset($_FILES['image']) && $_FILES['image']['error'] == UPLOAD_ERR_OK)
The $uploadDir
variable stores the directory of the file to be uploaded i.e. uploads/
, and $uploadFile
creates the file path for storing the file using the filename of the file being uploaded.
The problem lies in the code segment mentioned below:
// upload the file
if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadFile)) {
$uploadMessage = "File is valid, and was successfully uploaded.";
} else {
$uploadMessage = "Possible file upload attack!";
}
Bug
The developer is storing the file irrespective of checking whether the file is an image or not. Due to which, any arbitrary file can be uploaded onto the web server.
To overcome this issue we will add the file checking logic before actually moving our file from /tmp
storage to our uploads/
directory.
// Check if the file is an image
$check = getimagesize($_FILES['image']['tmp_name']);
if ($check !== false) {
// upload the file
if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadFile)) {
$uploadMessage = "File is valid, and was successfully uploaded.";
} else {
$uploadMessage = "Possible file upload attack!";
}
} else {
$uploadMessage = "File is not an image.\n";
}
The above code snippet uses getimagesize()
1 to get the size of an image. This function call will return a false
in case, the file is not a valid image. Let’s modify our web server’s upload.php
file to check whether we are able to upload a .php
file again.
Now let’s click the Upload Image
button to upload .php
file.
We have now encountered a message stating that the “File is not an image” and therefore not uploaded onto the server, therefore mitigating the Arbitrary File Upload vulnerability and hence only valid image files can be uploaded to the server.
This guide demonstrated the command injection vulnerability and it’s different types.
Soon there will be separate guides to explain the Deserialization and XML external entity injection attacks.
Task
The sample gallery application is also vulnerable to one more attack vector. Can you spot and use that vulnerability to extract some crucial information. Hint: Path Traversal
You can checkout our blog to learn about Path Traversal vulnerability.