1

A similar question has be answered here already, but I have a very specific scenario in which it didn't fulfil my requirements.

I am setting up an environment which includes a web-service running on an intranet domain. Certain partitions are available to the public through port forwarding which impose higher security requirements in exchange. For instance, if someone accesses the application through the public domain, he will be required to solve multi-factor authentication on every login and is not allowed to have his login or browser to be remembered through cookies whose lifetime exceeds the session scope. The idea was to simply suppress the availability of things such as the the "Remember me" functionality through evaluating the Host header. For example:

  • Intranet app is running on 198.168.0.1:45000;
  • there's a port-forwarded public domain to this host named business.someservice.com;
  • if the detected host-name does not equal 198.168.0.1:45000 said features are omitted and each request has to be authenticated through MFA.

Above question's answer states that it can not be trusted, but functionality might blunder through the false host claim.

I am wondering:

  1. What can I do to make this approach safe? Would it suffice to do an additional check whether the client possesses an IP address within private range? And how is that not as easy to manipulate as the host?
  2. What damage could an attacker possibly do? If he acquired a pair of log-in credentials and tries accessing from the outside by changing the Host header to the intranet server, he could be able to be issued a cookie that has a longer lifespan. But he would still have to complete the initial MFA at least once unless he happens to get his hands on a valid MFA remembrance cookie for that specific user, which I assume to be very unlikely. I could only see a particularly witty employee who can authenticate in the intranet to abuse this to gain full-feature access from the outside.
user3840170
  • 172
  • 7
Beltway
  • 316
  • 1
  • 11
  • 1
    Mti2935 is the right answer - check the source IP. The source IP is needed for the network traffic to go to the right place. An attacker could spoof (fake) the source IP, and your server would try to respond to the fake IP, but the response wouldn’t get back to the attacker and fail the tcp handshake - your userspace web server wouldn’t even see the attempt. But - The host header is only used by your web server and an attacker could set it to anything. if you don’t check it at the web server, it would have no effect. But an attacker could set the host to 192.xxx so you can’t trust it. – Jonathan Jul 20 '21 at 21:30

1 Answers1

1

You might want to consider basing your logic on the source address of the TCP connection to your web server.

Port forwarding changes the destination address of the TCP connection, but does not change the source address. Therefore, if the connection originates from another host on your LAN, then the source address will be 192.168.x.x. Otherwise, if the connection originates from outside your LAN (and is port-forwarded by your router to your web server), then the source address will be some publicly-routable address.

In PHP, you can access the source address of the TCP connection via the $_SERVER['REMOTE_ADDR']. Note that is the actual address that the client is connecting from, it is not taken from the HTTP headers as is the case with some other server variables. For more information, see Is $_SERVER[ ] a safe source of data in PHP? and Changing $_SERVER['REMOTE_ADDR'] remotely.

mti2935
  • 19,868
  • 2
  • 45
  • 64
  • So I really am good if I just check whether it is a private one? Unfortunately, I am on .NET 5 and can't seem find a way to get the actual remote address from the handshake that is used to establish the TCP/HTTP connection (which is eventually replaced by a Web-socket). I am only left with a method that "Gets [...] the IP address of the remote target. Can be null." which is likely just the entry on the HTTP header. But I presume this will suffice since even though an attacker could manipulate it , that would be to no avail, as @Jonathan pointed out? – Beltway Jul 21 '21 at 08:33
  • I'm not familiar with .NET, but most web programming tools have an environment variable that contains REMOTE_ADDR, which is the remote IP address that made the TCP connection with your web server. Does this help: https://stackoverflow.com/questions/33999011/accessing-client-ip-address-remote-addr-in-asp-net-5 – mti2935 Jul 21 '21 at 10:10
  • That should be the framework predecessor's equivalent, the property `ConnectionInfo.RemoteIpAddress` of `HttpContext.Connection`, which should include "Information about the underlying connection for this request". Sounds about right but I was a bit irritated that it can actually be null (not for me though yet). – Beltway Jul 21 '21 at 12:19
  • Turns out the official docs use that property for IP Whitelisting, so it should be safe: https://docs.microsoft.com/en-us/aspnet/core/security/ip-safelist?view=aspnetcore-5.0 – Beltway Jul 21 '21 at 12:50