Arguably, a more straightforward approach to finding shell injection vulnerabilities is to just try performing shell injection. This works even without access to the source code, though it’s helpful to have access.
Suppose you suspect an input field is somehow linked to the execution of a shell command. In that case, you can provide unusual inputs and see if any unexpected behavior occurs. For example, if you put a colon (:
) into an input field and get a 500 internal server error, that’s a sign that something interesting may be happening. The exact characters that can cause problems vary depending on the server operating system, but some variety of Linux distro is a reasonable initial assumption.
Instructions
We’ve created a program to allow you to experiment with shell injection. The program’s “intended” use is to determine whether or not an IP address is reachable, but it has serious security flaws. You can run the program by typing ./demo.py
in the terminal.
Let’s first see how the program is intended to work. After running the program, give it a valid IP address, like 127.0.0.1
.
Let’s see what happens if we give the program something that isn’t valid, like a qwerty. Run the program again and insert qwerty
.
These responses look an awful lot like the output of the ping command. What happens if we type ;echo "vulnerable!"
into the program? Rerun the program and type ;echo "vulnerable!"
We get our error from the ping command as we expect, but the shell also executes our echo command! This demonstrates that shell injection is occurring. If you could do something like this through an input field on a website, that would likely be a critical vulnerability.
There’s more than one way to perform shell injection! If you want to challenge yourself, you can run the program with increasingly strict input validation using ./demo.py hard
and ./demo.py veryhard
. You can also view the source code of the program using cat demo.py
if you’d like to see how the different levels of validation work under the hood. There is also an impossible difficulty level that follows best practices for input validation but isn’t meant to be beatable.