Hijacking other user’s TCP tunnels

Posted on

If you are a frequent SSH user, then you’ll be familiar with local port forwarding:

Local forwarding is used to forward a port from the client machine to the server machine. Basically, the SSH client listens for connections on a configured port, and when it receives a connection, it tunnels the connection to an SSH server. The server connects to a configurated destination port, possibly on a different machine than the SSH server.

Local port forwarding is not only a commonly used SSH feature, it’s also a technique used by AWS Session Manager, Google Cloud IAP TCP forwarding, and other tools

Risks

Creating TCP tunnels by using local port forwarding is not without risks however. One aspect in particular deserves some scrutiny, and that is:

[...] the SSH client listens for connections on a configured port [..]

If the SSH client opens a port, then any client can potentially connect to that port. How do we make sure that malicious users cannot take advantage of this to hijack a tunnel and gain access to the remote machine?

Like SSH, gcloud compute start-iap-tunnel and IAP Desktop bind to 127.0.0.1 when creating IAP TCP forwarding tunnels. That automatically protects the tunnel from being accessed by remote clients. But what about other local clients, particularly when you are in a Remote Desktop Services, Citrix, or other kind of multi-user environment where you have no idea who else is logged in?

Let us consider the example below: Alice has logged on to multiuser-box (it does not matter whether that is a Linux or Windows machine) and opens an SSH tunnel to secure-box. The tunnel forwards connections from 127.0.0.1:8080 (on multiuser-box) over jump-box to secure-box:80. The tunnel lets Alice access nginx by pointing her browser to http://127.0.0.1:8080/

What if Mallory logs in to multiuser-box and also connects to 127.0.0.1:8080?

SSH port forwarding example

SSH will not stop Mallory and will in fact happily let him use Alice’s tunnel. Mallory could even go one step further and set up a remote forwarding tunnel to expose Alice’s tunnel to others:

SSH hijacking example

Mitigations

Trying to mitigate the risks of local port forwarding in multi-user environments is surprisingly difficult. SSH provides a number of configuration options that control how users can use port forwarding – but these options apply to the server side, not to the client.

For gcloud, the story is similar. IAP gives you fine grained control over who is allowed to create tunnels, which VMs they can target, and which additional conditions need to be met. But once you’ve successfully created a tunnel by using gcloud compute start-iap-tunnel, none of these policies prevents a hijacking scenario as illustrated by the preceding example.

If SSH and gcloud do not provide any good protections themselves, how about using firewall rules to restrict who can connect to a TCP tunnel?

One interesting feature of Windows Defender Firewall is that it lets you create user-specific and program-specific rules. In theory, you could use that to ensure that only Alice can access the port used by the tunnel, and you could even dictate that she is only allowed to use mstsc.exe to connect to it.

In practice however, using firewall rules to restrict access to tunnels seems like a non-starter: Tunnels are typically short-lived, they often use random local ports, and a user might use multiple tunnels at the same time. Trying to come up with firewall rules that account for all possible variations seems impractical.

How IAP Desktop protects tunnels

When you connect to a remote desktop in IAP Desktop, the app creates an IAP TCP tunnel in the background. The tunnel is necessary because the Microsoft RDP ActiveX control requires an IP address and port to connect to. In an ideal world, the control would accept an IStream interface (or something similar) so that the hosting application could manage the connection – but that is not the case.

You can see these tunnels and their ports in the Active IAP tunnels window:

IAP Desktop active tunnels

But when you try to connect to any of these tunnels by using mstsc, the connection fails!

Connection failure

This connection failure is not a bug or coincidence – unlike SSH or gcloud, IAP Desktop can detect and reject connection attempts from what it considers unauthorized clients. If you have enabled logging (Tools > Enable logging), you can find evidence for that behavior in the log file:

Warning: 0 : Connection from 127.0.0.1:59941 rejected by policy

In the next post, we will take a closer look at how this mechanism works

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.
« Back to home