Announcement

Collapse
No announcement yet.

Ports in "stealth" mode are not a security feature

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Ports in "stealth" mode are not a security feature

    (Origin thread: How secure is Linux?)

    Gibson's fixation on ports is just one example of how he demonstrates a skewed understanding of security and risk. His notion of "stealthed" ports has created a lot of confusion but really solved nothing. Furthermore, since so many products decided that they needed to implement stealth, TCP/IP has been broken.

    Here's an experiment. Most of you probably are running CUPS, if you have a default Kubuntu install. The CUPS service runs a deamon that creates a listening socket on port 631/tcp. You can even talk to it. Watch:
    Code:
    steve@t520:~$ [B]telnet localhost 631[/B]
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Here's the conversation:
    Code:
    steve@t520:~$ [B]sudo tcpdump -ti lo[/B]
    1. IP localhost.50721 > localhost.ipp: Flags [S], seq 719613933, win 32792, options [...], length 0
    2. IP localhost.ipp > localhost.50721: Flags [S.], seq 3311305689, ack 719613934, win 32768, options [...], length 0
    3. IP localhost.50721 > localhost.ipp: Flags [.], ack 1, win 257, options [...], length 0
    I've added line numbers to facilitate discussion, and omitted the options so that the lines don't wrap.

    1. TCP SYN-flag from the client to the service listening on 631/tcp.
    2. TCP ACK and TCP SYN-flag from the service to the client.
    3. TCP ACK from the client to the service. This completes the TCP three-way handshake.

    Now I'll close the connection:
    Code:
    [B]^][/B]
    telnet> [B]quit[/B]
    Connection closed.
    steve@t520:~$
    And here's the conversation:
    Code:
    4. IP localhost.50721 > localhost.ipp: Flags [F.], seq 1, ack 1, win 257, options [...], length 0
    5. IP localhost.ipp > localhost.50721: Flags [F.], seq 1, ack 2, win 256, options [...], length 0
    6. IP localhost.50721 > localhost.ipp: Flags [.], ack 2, win 257, options [...], length 0
    4. TCP FIN-flag from the client to the service.
    5. TCP ACK and FIN-flag from the service to the client.
    6. TCP ACK from the client to the service. This completes the TCP four-way teardown.


    Now I'm going to try to connect to some random port that has no listening socket:
    Code:
    steve@t520:~$ [B]telnet localhost 9999[/B]
    Trying 127.0.0.1...
    telnet: Unable to connect to remote host: Connection refused
    steve@t520:~$
    And the conversation:
    Code:
    steve@t520:~$ [B]sudo tcpdump -ti lo[/B]
    1. IP localhost.54943 > localhost.9999: Flags [S], seq 2300475951, win 32792, options [...], length 0
    2. IP localhost.9999 > localhost.54943: Flags [R.], seq 0, ack 2300475952, win 0, length 0
    1. TCP SYN-flag from the client to the service listening on 631/tcp.
    2. TCP RST-flag from the service to the client. The server resets the connection because nothing is listening on the specified port.

    Gibson would call this a "closed" port. But this is a foreign concept to TCP/IP: ports are not "open" or "closed." On a host, ports are either in use or not. A connection request to a port not in use results in the computer's IP stack telling you so: "nothing here, sorry."

    Once upon a time, firewalls behaved the same way. However, firewalls can also silently drop invalid incoming connection requests rather than replying with a reset. Here's an example, where I connect to the external interface of my firewall and specify a port that's not publishing anything:
    Code:
    steve@t520:~$ [B]telnet rileyz.net 9999[/B]
    Trying 174.61.253.106...
    [B]^C[/B]
    Nothing happens, and I press Ctrl+C to kill telnet.

    Here's the conversation:
    Code:
    steve@t520:~$ [B]sudo tcpdump -ti eth0[/B]
    [B]^C[/B]
    Is it really nothing? No. My computer sends SYN-flag datagrams, but since my firewall isn't publishing anything on port 9999/tcp, and my firewall doesn't send RST-flag replies, my computer receives nothing in response. So TCPdump displays nothing. The connection remains in a half-open state until I press Ctrl+C.

    This is what Gibson calls a "stealthed" port. But is there really such a thing? No. Keep reading.

    Only in the context of a firewall does it make sense to use "open" or "closed" to describe a port state. A port is open if there exists a rule that allows inbound connections to pass through the firewall to something behind it. A port is closed if no such rule exists. But whereas hosts respond with "nothing here, sorry" when incoming connections fail, firewalls nowadays simply drop the connection requests on the floor.

    Why silently drop? Some time ago, it became fashionable to worry about whether that "nothing here, sorry" error might reveal tantalizing clues to an attacker. Gibson latched onto this, and decided that it was somehow more secure if a computer could act like a firewall when it receives incoming requests to ports that have no services. He invented the term "stealth" to describe the behavior, on a host, of a "closed" port on a firewall. So then he had to redefine "closed" -- which, remember, means nothing from the perspective of a host -- to reflect the "not in use" meaning on a host.

    But a host can't act like a firewall: TCP/IP doesn't behave this way. A non-response to an incoming connection is a very early form of security theater that every firewall manufacturer decided it needed. Host-based firewalls adopted this feature very quickly. Zone Alarm was one of the first to do so, and Gibson made a lot of money shilling for it. To make a host act like a firewall requires installing additional software.

    But this behavior breaks TCP/IP. The protocol was not designed to maintain lots of half-open connections. I can exhaust the resources of a firewall by sending a bunch of SYN-flags to ports that are open, cause the firewall to reply with its ACK/SYN-flags, and never send the final ACKs. The firewall will maintain each half-open connection for four minutes (two times the MSL, or maximum segment lifetime of two minutes). Similarly, I can exhaust the resources of a client by getting malware on the box that creates half-open connections on every usable port.

    Why has a non-response been considered more secure than "nothing here, sorry"? It's based on the flawed assumption that hiding is useful or even possible. For actual servers that you actually want to receive connections, hiding is useless. Trying to maintain "stealth" when you want to have even one "open" port is just silly. Imagine you have a Windows HTTP server behind a firewall. The firewall has a single rule that allows connections to the server's port 80/tcp. If someone now tries to connect to port 139/tcp, who cares whether the firewall drops the requests or replies with an RST-flag? In both cases the connection is refused, which is the goal. "Stealth" is not more secure, and "closed" is not less secure. They're equivalent.

    Hiding might make sense only when the computer has no need to listen for anything incoming. However, your computer is obviously still making outbound connections, and the moment you do that, your computer's presence -- its public IP address -- becomes known. Really, then, it's impossible to hide on the Internet. Given this, attempts to achieve "stealth" even on client PCs is just security theater.

    Wow, this post got really long. If you've slogged your way through all of it, thanks much. Unfortunately, it takes much time and many words to explain why seemingly good and simple ideas like "stealth" actually make no sense at all.
Working...
X