I had the recent opportunity to speak at BSides SLC, held on the Sandy campus of Salt Lake Community College. I tailored my presentation to the student demographic and chose to talk about one of the fundamental concepts that a penetration tester must understand: types of shells. I touched on the differences between simple shell interaction and a full-featured terminal and then launched into a discussion focusing on web shells. Following the theory conversation, I demonstrated how control over a server could be established by exploiting a file inclusion vulnerability and default credentials to deploy two different web shells, each adapted for the particular platform.
To start with, there are generally two accepted categories of shells with respect to input and output: interactive, or terminal, versus a simple shell. The interactive/terminal shell is likely the form most people are familiar with. When a Windows cmd prompt or Linux SSH session is used, that’s an interactive terminal. It’s a robust user experience, as it supports Ctrl sequences for controlling processes and input such as Ctrl+C to kill processes, Ctrl+Z to background processes, and Ctrl+W to delete words at a time. It adapts to screen size if you adjust the window, and colors can be configured. The interactive terminal also supports commands such as top, sudo, and nested SSH sessions, due to the ability to receive and process input and output from users and the computer.
Contrast that idea with the basic pipe for input and output that is a simple shell. This interaction is often conducted through the use of Netcat or Ncat, basic scripts, or compact shellcode. In an Ncat shell, Ctrl+C will break the shell entirely and likely lose the foothold on the compromised host. Arrow keys and the Backspace key won’t work, so typos are not forgiven. This interface does not support interactive commands like sudo or SSH due to the inability to present the prompts for additional user input after invoking the command. The primary advantage is that the simple shell is quite small, efficient, and can be invoked in innumerable ways.
As seen in the two images below, these shell types are contrasted. In the first image, the prompt and output are clearly separated, and a Ctrl+C merely presented a new line. In the second, the commands and output are grouped together, and Ctrl+C killed the session.
Now that the interactions have been addressed, the next category to discuss is how an attacker connects to the shell. Again, these methods can be categorized into two approaches: either the attacker connects to a listening shell (bind), or the shell connects back to a listening handler (reverse). In the former case of a bind shell, the payload opens a port on the compromised host and listens for connections. When an attacker connects to that port, it serves up cmd.exe or /bin/sh with stdin and stdout directed over the network connection. The major drawbacks of bind shells are presented by firewalls and NAT. If a firewall is blocking a program from listening on a port or preventing inbound connections, the attacker cannot connect to the listening shell. Alternatively, if the compromised host is behind a NAT router, then the attacker can most likely not initiate a connection to the internal network from outside that router. Most routers will drop uninitiated external traffic destined for an internal address.
This diagram depicts how a shell would open a port and listen on the victim machine for the attacker to connect to the host. Any firewall or NAT configurations between the two, however, would prevent a successful connection. It also demonstrates the technical nature of the article, not the graphic design emphasis.
An attacker can either connect to the listening shell or have the compromised computer connect out to a server with a listening handler. When the payload executes on the target and then sends the connection back out to the attacker, this payload is called a reverse shell. As most networks have to allow outbound traffic, this approach will usually have a higher rate of success than using a bind shell. An attacker could host the listener on commonly permitted ports such as 80 and 443, and cursory network observations would likely assume HTTP/HTTPS traffic.
In this scenario, imagine that the victim computer received a phishing email with a Microsoft Word document containing a macro. When triggered, that macro connected out to the attacker’s server and handed over control access to that machine. This attack solves the NAT issue and will frequently bypass firewall defenses, as the traffic appears to originate from inside the network.
Yet another means of cataloguing shells is the delivery method. Web shells were the focus of the talk, which are delivered or executed through web applications. These payloads can be delivered by exploiting vulnerabilities or features in the platform such as file uploads, inclusion vulnerabilities, or by leveraging external services such as FTP or SMB. They are somewhat OS agnostic, apart from some that depend on executing cmd.exe instead of /bin/sh or vice versa. Instead, they are more reliant upon the language of the application. That is to say, a Ruby payload will likely not successfully deploy on a PHP application.
An example PHP web shell is the following line of code: ‘<?php echo shell_exec($_GET['cmd']); ?>’.
If an attacker could write that line to a file on a PHP web server, and then access that file, the web stack would execute the code and “shell_exec” whatever value was passed in the cmd parameter. For example, if a text file with that line was uploaded via FTP, and the following directory traversal could be successfully accessed (../../../../../../../../../ftp/webshell.php&cmd=id), the application would execute the “id” command. Any other commands could also be executed to continue the path of privilege escalation and full compromise.
Here are some repositories to help demonstrate the myriad possibilities for shell creation, deployment, and usage.
Pentestmonkey: https://github.com/pentestmonkey/php-reverse-shell; http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
Of course, shells and other payloads can also be created with tools like MSFvenom, which is a tool bundled with the Metasploit Framework for generating shellcode. It supports approximately 500 base payloads, without taking into consideration the various possible permutations. MSFvenom generates shellcode, language-specific shell invocations, and executable files, including the Meterpreter shell. Meterpreter is a feature-packed custom shell with module support to expedite tasks like dumping hashes, scraping credentials from memory, and even grabbing packet captures from compromised hosts.