0

We're running a dev server on some IP and have our API exposed on port 5000 and nginx listening on 80. However, the entire backend will crash when one makes an HTTPS request to port 5000. Thus, I noticed a vulnerability, that when one accesses https://SERVER_IP:5000, since it can't handle the HTTPS request, the request hangs and the entire backend stalls (so the API hangs for any other requests as well). I just want that request to never reach the backend.

I have the following rules set up for UFW.

To                         Action      From
--                         ------      ----
8000                       ALLOW       Anywhere
22/tcp                     ALLOW       Anywhere
80                         ALLOW       Anywhere
5000                       ALLOW       Anywhere
443/tcp                    DENY        Anywhere
8000 (v6)                  ALLOW       Anywhere (v6)
22/tcp (v6)                ALLOW       Anywhere (v6)
80 (v6)                    ALLOW       Anywhere (v6)
5000 (v6)                  ALLOW       Anywhere (v6)
443/tcp (v6)               DENY        Anywhere (v6)

However, when one navigates to https://SERVER_IP:5000, the server still crashes. I think this is because https traffic is not necessarily coming in on port 443 but rather 5000 and that's exposed (which it needs to be only for HTTP traffic). So is there some way I can disallow HTTPS traffic on 5000 through UFW or do I have to configure something with nginx?

  • I would bind 5000 to localhost only and would proxy only http requests from nginx to it – Rui F Ribeiro Nov 30 '18 at 8:40
2

No, UFW cannot do it.

Determining whether traffic in TCP connection is valid HTTP request or not requires accepting the connection and seeing what kind of data the client is trying to send. In other words, it's content-based filtering.

UFW needs to make the decision based on the data in the initial SYN packet of the TCP connection, which contains no data. At that point you cannot tell what the client's request will be. It sounds like you'd rather need some sort of HTTP reverse proxy in front of your API, to filter out everything that is not a well-formed HTTP request for an URI applicable to your API.

Might I also suggest to you that you also have the input validation of your API improved, at least to the point that it is no longer crashable by sending in random nonsense, before you place it into production? Otherwise it really looks like your API is very likely vulnerable to a trivial denial-of-service attack, like nc your.API.server.example 5000 < /dev/urandom, or maybe nc your.API.server.example 5000 < War_and_Peace.txt, where War_and_Peace.txt is anything that is definitely larger than the input buffer of your API service.

  • Awesome, thank you! I'm using gunicorn and there's a bug that's causing the server to not respond on certain occasions, and I think I'll test with piping in random input - great idea. Maybe I can have nginx listen on 5000 also and forward that appropriately? – rb612 Nov 30 '18 at 8:33
  • That sounds like a good approach to me. – telcoM Nov 30 '18 at 8:34

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.