1

I'm trying to send a request to an http server hosted on a machine. The http server is in C# and drops any packets that are not from localhost:

public void Request(HttpListenerContext context) {
    if(!IPAddress.IsLoopback(context.Request.LocalEndPoint.Address))
        this.ConnectionRefused()
    ...
}

I had the idea of using scapy and spoofing the TCP src IP for 127.0.0.1, and the machine receives the packet (confirmed in wireshark), but the request doesn't seem to be triggered. I am wondering if anyone knows how I can make an http request to this port bypassing the Loopback check.

  • Well if you are Spoofing as 127.0.0.1 how are you expecting to get a response back it will be sending that to 127.0.0.1 – McMatty Oct 1 '18 at 22:45
  • I don't need a response, I need the server to just interpret the request. I don't need any sort of response from the server. – Rob Gates Oct 1 '18 at 22:54
  • You are assuming that you failed in your task. Maybe you passed the check. Perhaps the problem is with what you sent? – schroeder Oct 1 '18 at 22:57
  • @schroeder the reason I believe I failed is because I've read that it might not be possible. Furthermore, I'm thinking about the check. See, it looks at the request and local end point. Is the local end point the tcp source IP or destination IP, cause maybe I need to somehow spoof the dest ip to be 127.0.0.1. – Rob Gates Oct 1 '18 at 23:01
  • See, when I hover over "LocalEndPoint" it says "Gets the server IP address and port number to which the request is directed.". Perhaps it's checking the destination ip instead of local? Is there anyway I can send a packet to another computer but have the destination ip be something else? – Rob Gates Oct 1 '18 at 23:05
3

You "pass" a localhost check by sending the request to localhost (or 127.* or ::1). For example, you can make a web browser do this by navigating to http://localhost/ or http://[::1]/. The C# code snippet you posted for the server is checking the local IP address, so for a server that's the IP address the server received the connection request at, and from a client's perspective it's the IP address that the client is trying to connect to (the destination).

If you try sending such a request from any machine other than the one you're attempting to connect to, you'll route the request to your own machine, which is not what you want (but is the point of the loopback address). If you try crafting raw Ethernet packets that just happen to contain TCP/IP traffic, and set the IP destination to 127.0.0.1 but try to transmit the packet to another machine (via MAC address), one of these things will happen:

  • You'll get an error from your network stack, because the packet was recognized to be IP traffic and is being transmitted wrong. Most network drivers probably won't do this, though, and if they do you can (in theory) edit that behavior out.
  • Your packet will go out on the network, but be rejected by the first node it arrives at (probably a switch or router, unless you have a direct connection to the other machine) because, again, it is invalid; it's bound for the loopback network but comes from an external network. This might be what you're seeing in Wireshark.
  • Your packet will be accepted by a router or switch, but passed to that router/switch's loopback network (after all, that's the destination IP address) rather than passing it on to any other host (it doesn't know where next to send the packet). This would be a security bug in the device and well worth reporting to the manufacturer if found.
  • Your packet will go to the destination computer (if directly connected, or possibly if broadcast through a network hub), and be initially accepted by the network stack as a TCP SYN packet. However, when the server tries to respond with SYN/ACK, it will fail because it is trying to send an invalid packet (originating with localhost but bound for an outside host). This is still probably a security bug in the network driver / IP stack, because UDP packets don't require a handshake like that. Very much worth reporting.
  • Your packet reaches the destination host and is accepted (as above), and you get a TCP SYN/ACK from the server, inviting you to complete the handshake with a final ACK and start transmitting data. You'd probably need a raw socket listener for this, because the OS network stack isn't going to recognize the incoming packet as part of a TCP handshake it was working on (though you could, theoretically, patch it to do so). This indicates a serious security bug in the server's network stack.

Note that in none of these cases, except the last one, is there any chance of the C# web server ever seeing the request come in. HTTP is transmitted over TCP, and TCP servers aren't even notified that somebody is connecting to them until the handshake completes. So, unless you've got a really serious bug in your network stack and are connected pretty directly, this is never going to happen.

Now, if you want to know how to reach a server listening only on loopback from outside the machine, the solution to that is to find some program on the same host as the target server that does listen to outside traffic, and will either relay requests to specified destinations (a proxy), or that can be used to create new web requests (this is a Server-Side Request Forgery (SSRF) attack, and one common way to create them is through an XML eXternal Entity (XXE) attack).

  • Thanks for this, do you think this code would work: "spoofed_packet = Ether(src="ab:cd:ef:ab:cd:ef", dst="ff:ff:ff:ff:ff:ff")/scapy.all.IP(src=A, dst=B) / scapy.all.TCP(sport=C, dport=D) / payload send(spoofed_packet)"? – Rob Gates Oct 2 '18 at 1:56
  • @RobGates to summarize from CBHacking's excellent answer: no, that will not work. The server isn't listening on an IP address. It is listening on the loopback interface - it's own special network interface that it uses for itself and which only it can talk on. What you are doing is akin to trying to whisper in someones ear and trick them into thinking that they are hearing their own thoughts. The only way you can get requests to this C# server is by tricking another process on the machine into making the request for you. – Conor Mancone Oct 2 '18 at 2:01
  • @ConorMancone Actually Conor, I was able to get it to "receive" my request when I just send a request directly to the IP and PORT, the issue was that it was rejecting it when it saw it wasn't from 127.0.0.1. So actually, I can "interact" with the server, just the issue was the localhost filter. – Rob Gates Oct 2 '18 at 2:13
  • @RobGates in the question you said that Wireshark confirmed the machine received the request. Per CBHacking's answer here, that is much different than having a transaction created or having the server receive the request. Perhaps I have misunderstood the facts as stated in your question, but my expectation is that the C# server is not even receiving your requests and no amount of spoofing can change that – Conor Mancone Oct 2 '18 at 2:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.