Arbitrary Command Injection is a type of command injection vulnerability, which can be triggered to execute arbitrary command or in simple words any of the available command within the application server.
In the following guide, we will look at how Arbitrary Command Injection vulnerability can be triggered to execute a simple command such as id
on a sample vulnerable application.
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 navigating to http://127.0.0.1:8080/upload.php
webpage. 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.
In the above screenshot, If you may have noticed, we have three options for each image file uploaded:
- View: To view the image on the browser
- Download: To download the image file from the application
- Delete: To delete the file from the web server
Go and try all the available operations.
view operation
By clicking the View
, the user can be able to view that uploaded image from the web application.
Download operation
By clicking the Download
button downloads that particular uploaded image to the system.
delete operation
The last operation permitted within the web application, is to delete the image from the web application.
The application prompts for the confirmation to permanently delete the file from the server. Once confirmed, the web server deletes that particular image.
If you may have noticed during the delete
operation, the following endpoint is accessed in the browser:
http://127.0.0.1:8080/delete.php?file=pompompurin.jpg
And as, the file is being deleted from the system there is a possibility that the developer have used a remove system call or rm
command to delete the file from the server’s file system.
Now, we need to figure out some way to execute other commands instead or along with rm
command.
Note
In a Linux system, multiple commands can be executed in a single line by separating each command via semi-colon
;
So, we will try to append semi-colon and see whether we have encountered any error or not while removing the file from the server.
http://127.0.0.1:8080/delete.php?file=pompompurin.jpg;
Note
As the file has been already deleted from the webserver, a different image is needed for carrying out our analysis or the same file can be re-uploaded. In our demonstration, we have re-uploaded the same file after every delete operation.
Interesting to note that, the above location access did not encountered any error and we have successfully deleted the pompompurin.jpg
file.
So, delete.php
is inherently using a command line utility to execute a command to remove the file from the server. Let’s try to execute the id
command to check whether commands are being executed or not.
http://127.0.0.1:8080/delete.php?file=pompompurin.jpg;id
Voila Fellow Asuras!!! We have successfully executed the id
command on the web application, confirming the presence of Arbitrary Command Injection vulnerability.
Question
Can you think about some other vulnerability which may be present in the Gallery application. Hint: It’s something related to file upload.
Source Code Evaluation
To evaluate the source code of the application and find the root cause of the vulnerability, we need to evaluate the delete.php
file, as the vulnerability exists in the delete.php
endpoint of the web application.
To interactively attach the shell inside docker, use the following command:
docker exec -it command_injection /bin/bash
The truncated source code of delete.php
is as follows:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (isset($_GET['file'])) {
$output = [];
$returnVar = 0;
// Ensure the file name is sanitized to prevent security issues
$fileToDelete = basename($_GET['file']);
// Attempt to delete the file from the uploads directory
exec("rm uploads/" . $fileToDelete, $output, $returnVar);
if ($returnVar == 0) {
$message = "File deleted successfully.";
} else {
$message = "There was an issue deleting the file.";
}
// Display output from the exec command, if any
$message .= "<br><br>";
foreach ($output as $line) {
$message .= htmlspecialchars($line) . "<br>";
}
} else {
$message = "No file specified.";
}
} else {
$message = "Invalid request method.";
}
?>
During the evaluation, you may notice a interesting function call i.e. exec()
, which is used to Execute an external program 1.
Bug
A direct call to
exec()
is made without checking the arguments which are being passed as filename.
The above operation only requires us to delete the file from the web server. So, we can use PHP’s native file operations to do the task, instead of directly executing the rm
command in the shell.
The following code removes the use of exec()
, and uses PHP native unlink()
2 file operation to delete a file from the server.
<?php
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (isset($_GET['file'])) {
$returnVar = 0;
// Ensure the file name is sanitized to prevent security issues
$fileToDelete = basename($_GET['file']);
$file = 'uploads/' . $fileToDelete;
if (file_exists($file)) {
if (unlink($file)) {
$returnVar = 0;
} else {
$returnVar = 1;
}
} else {
$returnVar = 2;
}
if ($returnVar == 0) {
$message = "File deleted successfully.";
} else {
$message = "There was an issue deleting the file.";
}
// Display output from the exec command, if any
$message .= "<br><br>";
} else {
$message = "No file specified.";
}
} else {
$message = "Invalid request method.";
}
?>
After mitigating the vulnerability, let’s again try accessing the web page again with the id
command:
http://127.0.0.1:8080/delete.php?file=pompompurin.jpg;id
Now, the output shows did not triggered the command and resulted in an error, therefore we were successfully able to mitigate the arbitrary command injection vulnerability.
In the next part of the series, we will learn about Arbitrary File Upload.