Command Injections
OWASP’s Description of Command Injection:
Command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In this attack, the attacker-supplied operating system commands are usually executed with the privileges of the vulnerable application. Command injection attacks are possible largely due to insufficient input validation.
This attack differs from Code Injection in that code injection allows the attacker to add their own code that is then executed by the application. In Command Injection, the attacker extends the default functionality of the application, which execute system commands, without the necessity of injecting code.
The last part of that sentence, without the necessity of injecting code, is an important one when trying to differentiate between whether something would be considered a Code Injection or a Command Injection. Yes, we executed commands in a system shell in the previous example through a Python web application, but the only way we were able to execute those system commands was through the initial Python code injection.
In the following Command Injection example from TryHackMe’s Devie, we will be injecting commands into a bash script that is being run from a root owned cron job. This is the script being run by the root user every few minutes:
#!/bin/bash
cd /home/gordon/reports/
cp * /home/gordon/backups/
The shell script is using the *
wildcard with cp
to copy all files from /home/gordon/reports/
into /home/gordon/backups/
, which is what will allow us to inject a command, or in this case, we will be creating a file name that will be interpreted as a switch by cp
. This is similar to the tar exploit. The switch we’ll be injecting is --preseve=mode
, which will save the file’s modes (e.g. srwx
) from one file into another file. In this case we want to preserve the sticky bit that we will be adding to a copy of bash.
First change to the directory where the cron script will be copying files from
cd /home/gordon/reports/
Then copy bash into that directory and set it as a suid binary
cp /usr/bin/bash ./rootbash
chmod 4777 rootbash
This is what the file permissions and attributes will look like after we do that
Notice that after we copy /bin/bash
to our current directory as rootbash
that the owner and group has been changed to Gordon, rather than having root
as the owner and group as is typical of /bin/bash
. The cp
command by default changes the group and owner to that of the user executing cp
. If we left this as is, and the root cron script ran, then the rootbash
file would be copied to /home/gordon/backups/
, it’s new owner would be root
since the cron job is owned by root, however the suid bit would get removed in the process, making the newly copied rootbash
useless as a method to escalate to the root user. What we want to do is preserve the sticky bit when the file is copied, and to do that we will be using the --preserve
switch with cp
.
from the cp
man page
–preserve[=ATTR_LIST] preserve the specified attributes (default: mode,ownership,timestamps), if possible additional attributes: context, links, xattr, all
We’ll be using mode
with --preserve
to preserve the sticky bit that we already set on the rootbash
binary. The term mode
might not be famililar to you, but if you understand that the chmod
command stands for ‘change mode’, which is what we did when we added the numeric mode
4777 to the copied rootbash
binary, then it might make more sense. If we were to use --perserve=all
then not only would it copy over the binary’s mode, it would also copy the owner and the group, which for our rootbash
binary is currently Gordon, which again would make the binary useless as a means to escalate to the root user. What we want to do is preserve the sticky bit only and have the user ownership switch over to root, which will happen automatically when the cronjob owned by root executes the script copying all those files.
To perform the command injection we will create the following file in /home/gordon/reports/
echo '' > '--preserve=mode'
The directory will then contain the following files
Once the cronjob executes we can see that rootbash
was copied into the backups directory and that the sticky bit. In addition, rootbash
is now owned by root. To elevate to the root user run ./rootbash -p