SSH Local Port Forwarding
Let’s recall the first port forwarding example from the Socat scenario.
We set up Socat to listen on TCP port 2345 on the WAN interface of CONFLUENCE01.
Packets it received on that port were forwarded to TCP port 5432
on PGDATABASE01.
We used this to connect from our Kali machine, through CONFLUENCE01,
to the PostgreSQL service on PGDATABASE01.
The crucial thing to notice in this case is that listening and forwarding
were both done from the same host, CONFLUENCE01.
SSH local port forwarding adds a small twist to this.
With SSH local port forwarding, packets are not forwarded by the same host
that listens for packets.
Instead, an SSH connection is made between two hosts,
an SSH client and an SSH server,
a listening port is opened by the SSH client,
and all packets received on this port
are tunneled through the SSH connection to the SSH server.
The packets are then forwarded by the SSH server to the socket we specify.
This concept might seem a bit abstract at the moment.
We can understand it better by getting some experience setting up
a local port forward.
Let’s reconsider the previous scenario with a slight modification:
Socat is no longer available on CONFLUENCE01.
We still have all the credentials we previously cracked
from the Confluence database, and there is still no firewall preventing us
from connecting to the ports we bind on CONFLUENCE01.
With the database_admin credentials, we’ll log in to PGDATABASE01
and find that it’s attached to another internal subnet.
We find a host with an Server Message Block (SMB) server
open on TCP port 445 in that subnet.
We want to be able to connect to that server and download what we find
to our Kali machine.
The following diagram illustrates our setup:
In this type of scenario, we’ll plan to create an SSH local port forward
as part of our SSH connection from CONFLUENCE01 to PGDATABASE01.
We will bind a listening port on the WAN interface of CONFLUENCE01.
All packets sent to that port will be forwarded through the SSH tunnel.
PGDATABASE01 will then forward these packets toward the SMB port
on the new host we found.
We will listen on TCP port 4455 on CONFLUENCE01.
Packets sent to that port are pushed by the SSH client software on CONFLUENCE01
through the SSH tunnel.
At the other end of the tunnel, the SSH server software on PGDATABASE01
forwards them to TCP port 445 on the newly-found host.
As before, we can get a shell on CONFLUENCE01 using
the cURL one-liner exploit for CVE-2022-26134.
We can no longer use Socat to create a port forward that allows us
to SSH into PGDATABASE01 from our Kali machine.
However, in this case, we can SSH directly from CONFLUENCE01 to PGDATABASE01.
We can’t create the SSH local port forward just yet, though.
When setting up an SSH local port forward, we need to know exactly which IP address
and port we want the packets forwarded to.
So before we create the port forward SSH connection,
let’s SSH into PGDATABASE01 to start enumerating.
In our shell from CONFLUENCE01, we’ll make sure we have TTY functionality
by using Python 3’s pty module.
We can then SSH into PGDATABASE01 with the database_admin credentials.
Now that we have an SSH connection to PGDATABASE01 from CONFLUENCE01,
we can start enumerating.
We’ll run ip addr to query available network interfaces.
We’ll then run ip route to discover what subnets are already in the routing table.
We find that PGDATABASE01 is attached to another subnet,
this time in the 172.16.50.0/24 range.
We don’t find a port scanner installed on PGDATABASE01;
however, we can still do some initial reconnaissance with the tools
that are available.
Let’s write a Bash for loop to sweep for hosts with an open port 445
on the /24 subnet.
We can use Netcat to make the connections, passing the -z flag to check
for a listening port without sending data, -v for verbosity,
and -w set to 1 to ensure a lower timeout threshold.
Most of the connections time out, suggesting that there’s nothing there.
In contrast, we’ll notice that PGDATABASE01 (at 172.16.50.215)
actively refused the connection.
We also find that there is a host on the subnet,
which has TCP port 445 open: 172.16.50.217!
We want to be able to enumerate the SMB service on this host.
If we find anything, we want to download it directly to our Kali machine
for inspection.
There are at least two ways we could do this.
One way is to use whatever built-in tools we find on PGDATABASE01.
However, if we did find anything, we would have to download it to PGDATABASE01,
then transfer it back to CONFLUENCE01, then back to our Kali machine.
This would create quite a tedious manual data transfer process.
The alternative is to use SSH local port forwarding.
We could create an SSH connection from CONFLUENCE01 to PGDATABASE01.
As part of that connection, we could create an SSH local port forward.
This would listen on port 4455 on the WAN interface of CONFLUENCE01,
forwarding packets through the SSH tunnel out of PGDATABASE01
and directly to the SMB share we found.
We could then connect to the listening port on CONFLUENCE01
directly from our Kali machine.
For now, we should kill our existing SSH connection to PGDATABASE01.
We will then set up a new connection with new arguments to establish
the SSH local port forward.
A local port forward can be set up using OpenSSH’s -L option,
which takes two sockets separated with a colon as an argument.
The first socket is the listening socket that will be bound to the
SSH client machine.
The second socket is where we want to forward the packets to.
The rest of the SSH command is as usual -
pointed at the SSH server and user we wish to connect as.
In this case, we will instruct SSH to listen on all interfaces on port 4455
on CONFLUENCE01, then forward all packets, through the SSH tunnel to PGDATABASE01,
to port 445 on the newly-found host (172.16.50.217).
Let’s create the SSH connection from CONFLUENCE01 to PGDATABASE01 using ssh,
logging in as database_admin.
We’ll pass the local port forwarding argument we just put together to -L,
and use -N to prevent a shell from being opened.
Once we’ve entered the password, we don’t receive any output.
When running SSH with the -N flag, this is normal.
The -N flag prevents SSH from executing any remote commands,
meaning we will only receive output related to our port forward.
Since this reverse shell from CONFLUENCE01 is now occupied with an open SSH session,
we need to catch another reverse shell from CONFLUENCE01.
We can do this by listening on another port and modifying our CVE-2022-26134
payload to return a shell to that port.
Once we have another reverse shell from CONFLUENCE01,
we can confirm that the ssh process we just started from our other shell
is listening on 4455 using ss.
This is great!
Connecting to port 4455 on CONFLUENCE01 will now be just like connecting directly
to port 445 on 172.16.50.217.
We can review the connection flow in the following diagram.
We can now interact with port 4455 on CONFLUENCE01 from our Kali machine.
Let’s start by listing the available shares with smbclient’s -L option,
passing 4455 to the custom port -p option,
along with the username to the -U option…
and the password to the --password option.
We’ll try the credentials we cracked for the hr_admin user
from the Confluence database.
We find a share called scripts, which we will likely be able to access.
Let’s try to list what’s inside it and download what we find.
We can now inspect this file directly on our Kali machine.
In this section, by creating an SSH local port forward,
we’ve been able to download a file stored from a share on a host deeper inside the
corporate network.