Reputation: 28345
If I use this solution:
new ServerSocket(9090, 0, InetAddress.getByName("localhost"))
...and the user changes it's system hosts file to access my website as "localhost", will this fail to prevent access from non-local client?
Upvotes: 0
Views: 610
Reputation: 3425
(in response to the bounty call)
As always in computer security, guarantee depens on attacker capabilities.
The attacker is lame and knows nothing. Then yes, localhost
guarantees the locality of the client.
The attacker has login access to the system and can run SSH to the outer world. Then no guarantees - SSH can forward internal ports through tunnels:
ssh -R *:8080:localhost:9090 some.external.server
Executing this command on the box with your java server will result in establishing a tunnel. All requests addressed to some.external.server:8080
will be delivered to localhost:9090
of the target box.
VPS nowdays costs almost nothing, so the attacker can easily rent such external box and use it as the proxy between your localhost and the whole world.
Host
header is not localhost
. It could be easily countermeasured by including a header-rewriting proxy, such as nginx, to the forwarding chain. As you can see, guarantee means that users in the target box must be severely limited: no forwarding software. It implies denying users access to system utilities like ssh
or installing and/or running them with user privileges. This is highly unlikely unless the box is a set-top box without any user login or software reconfiguration.
The first comment to the question suggests a trick with localhost
name resolution:
the user could probably override localhost to that it's no longer 127.0.0.1
The idea is to place a record to /etc/hosts
or c:\Windows\System32\Drivers\etc\hosts
that binds localhost
name to another IP address.
If your box has an Ethernet connection with, say, address 1.2.3.4, then the line
1.2.3.4 localhost
might cause change of localhost
address. If this happens, then the line
new ServerSocket(9090, 0, InetAddress.getByName("localhost"))
will bind the port 9090 on the external network interface, that is accessible from the outside of the box.
I tried this on Ubuntu 18.04, and it worked. I successfully connected to the app running on localhost
in the box on the other side of Pasific.
BUT
Once upon a time MS Windows developers hardcoded localhost
to be 127.0.0.1
. Here is the Medium post about that.
I checked with my Windows 10 box. Confirmed: localhost
resolves to 127.0.0.1
. The test program
package org.example;
import java.net.*;
import java.io.*;
public class TryLocalhost {
public static void main(String[] args) throws IOException {
System.out.println("localhost: " + InetAddress.getByName("localhost"));
}
}
produces
localhost: localhost/127.0.0.1
while hosts
file tried to bind localhost
to the link-local address
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
192.168.0.198 localhost
The comment is original, from Microsoft.
Upvotes: 1