Linux Privilege Escalation - Port Forwarding for CTF Creators
Port Forwarding
When there’s a service listening on localhost and not externally, it doesn’t mean that we cannot access this service. Port forwarding as it name implies it allow us to foward a port to another socket. If this particular service is vulnerable to anything related an elevation of privilege, then it can be used as an elevation path.
Apache2 Scenario
Install apache2 with apt:
|
|
Configure the apache2 listening ports:
|
|
Enable the service, restart the service, and check its status:
|
|
Check if port 80 is listening on the loopback interface:
|
|
The options above are the following:
- -t: Display TCP sockets.
- -n: Do not try to resolve service names.
- -l: Display only listening sockets
- -p: Show process using socket.
Verify if it’s working by going to the browser and opening the localhost URL http://localhost:80
.
Do a nmap scan from an attacker host to prove that’s listening only on localhost:
|
|
As you can see the port is closed externally.
Privilege Escalation via Local Port Forwarding
Local Port Forwarding means forwarding the port that’s listening on the target host loopback interface to our host. This is done by connecting to the target host.
- Local: Connect to the target host from your adversary host.
This technique involves forwarding the port that’s listening on the loopback interface in the target/victim host to our remote host:
|
|
After authenticating successfully to the target host. We can see that our adversary host now has established a socket:
|
|
In our adversary host, we can enumerate the response headers to see if the Server
header indicates that is running Apache2 in Ubuntu:
|
|
As we can see from the output above we have successfully forwarded port 80 from the target machine (Ubuntu) to our adversary host on port 9898 (ParrotOS/Kali Linux).
When we’re done we can close this connection by exiting the SSH session.
Privilege Escalation via Remote Port Forwarding
Remote Port Forwarding means forwarding the port that’s listening on the target host loopback interface to our host. This is done by connecting to our host from the target host.
- Remote: Connect to your adversary host from the target host.
This technique involves forwarding the port that’s listening on the loopback interface in the target/victim host to our remote host:
|
|
Now go to your adversary host and verify that port 9999 is listening on your localhost:
|
|
When we exit
the ssh connection that’s in the victim machine then the port will stop being forwarded.
Privilege Escalation via Dynamic Port Forwarding
Dynamic port forwarding means that it’ll forward all the ports from the remote host to our SOCKS port.
SOCKS works on the OSI Layer 5 (Session Layer), so don’t expect things like ICMP, ARP or the half-open reset that SYN scan on Nmap to work. To scan via proxy with Nmap we need to do a TCP connect scan with the option -sT
and we should ignore ICMP with -Pn
.
There are different tools to help we out when Dynamic port forwarding is being used. The most common one is proxychains
which are available for Linux and Mac but also for Windows.
Dynamic port forwarding allows we to create a socket on the local (ssh client) machine, which acts as a SOCKS proxy server. When a client connects to this port, the connection is forwarded to the remote (ssh server) machine, which is then forwarded to a dynamic port on the destination machine.
This way, all the applications using the SOCKS proxy will connect to the SSH server, and the server will forward all the traffic to its actual destination.
Install the proxychains
package:
|
|
Alternatively, we can build it from the source code from GitHub.
Let’s configure the proxychains:
|
|
Add the following configuration:
|
|
In Linux, macOS, and other Unix systems to create a dynamic port forwarding (SOCKS) pass the -D
option to the ssh
client:
|
|
The options used are as follows:
[LOCAL_IP:]LOCAL_PORT
- The local machine IP address and port number. WhenLOCAL_IP
is omitted, the ssh client binds on localhost.[USER@]SERVER_IP
- The remote SSH user and server IP address.
The following command will create a SOCKS tunnel on port 9090
and connect to the target machine, we’re gonna execute this command from our adversary host:
|
|
The options used are as follows:
- -N: Do not execute a remote command. This is useful for just forwarding ports.
- -f: Requests ssh to go to the background just before command execution. This is useful if ssh is going to ask for passwords or passphrases, but the user wants it in the background.
Verify that the socket has been established, and execute this command in your adversary host:
|
|
Once the tunneling is established, we can configure your application to use it. This article explains how to configure Firefox and Google Chrome browsers to use the SOCKS proxy.
The port forwarding has to be separately configured for each application that we want to tunnel the traffic through it.
In the victim host, I have these ports open:
|
|
We can do port scans and service scans with nmap:
|
|
Noticed how I used the options:
- -sT = TCP connect scan, rather than the default
-sS
SYN scan. The SYN won’t work because the proxy doesn’t pass the TCP handshake packets back to our adversary host, an SYN scan, which sends the SYN packet, sees the ACK, and then ends the connection, this won’t be passed back over the proxy, therefore, SYN scans don’t work with proxies. - -Pn = Ignore ICMP request/response because ICMP doesn’t go through the proxy.
Without these options the scan will fail because the proxy will drop any SYN scans, we need the full TCP handshake to know if the port is open or not.
We can try to run Firefox with proxychains
:
|
|
Now we can access port 80 from the target host with the SOCKS port that is defined in our proxychains
configuration file so we can navigate to http://localhost:80
in our adversary host browser and we will see the apache2 default page.
This can be seen by using curl with proxychains and enumerating the response headers:
|
|
The advantage of using proxychains
with dynamic port forwarding is that we can access all the ports in the target dynamically. Let’s try to log in to SSH using the proxychains
to prove this:
|
|
As we can see from the output above we’re able to log in to SSH via proxychains
. This is almost the same as executing ssh user@localhost
in the victim machine.
We can close this connection by killing its PID, first finding the PID of the process:
|
|
The PID is the one in the second field from the output above, in this case, is (500777). Now kill the process:
|
|