Designing For Insecurity

Kjell Wooding | 1998-03-13

Though originally written in 1998, this paper is still one of our most popular. Sadly, it's still pretty accurate, which means they still haven’t gotten things right.

Recently, I was asked to write a paper on getting a Microsoft NetMeeting session safely through a firewall. After a few minutes research, I came to the conclusion that I was in for a rough ride. It would appear to me that, when it comes to security, some of the protocol designers out there just don't get it. H.323 looks like it was designed for insecurity.

Haven't we learned anything about protocol design and firewalls in the past 20 years?

Let's flash back: FTP

FTP is a difficult protocol to firewall, as it uses arbitrary ports for the data connection. Worse yet, the server initates the data connection back to the client based on a port number negotiated over the control connection.

PASV mode fixes part of this problem, by allowing the client to initiate the data channel connection, but still requires a proxy to analyze packet data to find negotiated port numbers. (I won't go into much technical detail here, because Chris did an excellent job of that a while back).

We can partially forgive the inventors of the FTP protocol for our troubles, as FTP predates the concept of a firewall by quite a number of years. Still, FTP remains as a thorn in the side to firewall designers and security-conscious system administrators. More modern protocols are much better behaved, and tend to restrict their behaviors to one or two well known ports, and client-initiated requests, making packet filtering a viable option. Modern protocol designers are used to the idea that they are going to have to deal with firewalls in the IP world, and design their protocols accordingly.

RTFM

From the Microsoft NetMeeting Resource Kit, Chapter 4

“You should consider carefully the relative security risks of enabling different parts of a NetMeeting call in your firewall product. Especially, you should consider very carefully the security risks involved when modifying your firewall configuration to accept any component of an inbound NetMeeting call.”

(You have been warned.)

Modern designers, that is, other than the H.323 ones.

Rather than relying on well-known ports for incoming requests, the H.323 designers have chosen to use arbitrary UDP ports for the audio and video portions of the conference. To make matters worse, the arbitrary UDP ports are negotiated over an arbitrary TCP Call Control channel, and all these requests are encoded using a variety of communications standards, such as Q.931 and ASN.1. To summarize, that is an encoded request over an arbitrary port to create another set of arbitrary connections.

Why is this an issue for firewalls? Let's take a quick look at how most packet filters work.

Packet Filtering H.323

The most basic type of firewall is the venerable packet filter. A packet filter is a beast with no concept of what has been. It filters TCP/IP packets based on the information contained in the packet header: protocol type, source address, source port, destination address, destination port, and flag information. Packet filters use a few simple rules about the way TCP/IP connections are initiated to perform their filtering.

TCP/IP connections are typically made from ephemeral to well-known ports. An ephemeral port is a port in the range 1025 - 65535 (often with a hole from 5000 - 9999). Well known ports are often 1024 and below, (although this is increasingly not the case—a topic for yet another rant).

TCP connections have some additional information associated with them, owing to their stateful nature. The most important information for a filter to know is whether a packet is part of an existing communications (has the ACK flag set) or is the start of a new connection (No ACK).

A client-initiated connection to a WWWM server, for instance, will typically look like this:

TCP/IP Connection Diagram

Client-initiated connection to a WWWM server

Initially, the client sends a packet from an ephemeral port to the well-known port 80. This packet has the SYN flag turned on. The server responds with a reply packet having the source and destination ports reversed, and the SYN and ACK flags turned on. Finally, the client acknowledges with a bare ACK, and data flow proceeds. Each side sends data, and ACKs the most recently received packet. When the communication is done, the connection is torn down with the FIN flag on both sides.

Clearly then, if we deny all incoming traffic that does not have the ACK flag set, we can effectively deny server-initiated TCP/IP connections.

To allow this kind of traffic through a packet filter, we would typically use a ruleset like this:

Source Port

Source Host

Dest Port

Dest Host

Flags

Action

>1024

[inside]

80

*

*

Allow

80

*

>1024

[inside]

ACK

Allow

*

*

*

*

*

Deny

This says that any ephemeral outbound connection to port 80 is permitted, and anything looking like a reply packet (source port 80, destination port ephemeral, and ACK flag turned on) is let back in. All other traffic is denied. This isn't the ideal case (really, traffic should only be allowed back to the ephemeral port that the connection was initiated on, but this isn't possible without some concept of statefulness), but it is good enough for now.

In the case of H.323, client and server ports are negotiated inside the packets themselves. Since a packet filter only knows about what is contained in the packet header, it is forced to treat things in the general case. To allow outgoing requests to the H.323 Call Control channel, for instance, we must allow TCP traffic originated from an ephemeral port, destined for an ephemeral port. Our ruleset will look like the following:

Source Port

Source Host

Dest Port

Dest Host

Flags

Action

>1024

[inside]

>1024

*

*

Allow

>1024

*

>1024

[inside]

ACK

Allow

*

*

*

*

*

Deny

In other words, the remote party can send packets to any port above 1024, so long as the ACK flag is set. This isn't entirely bad, is it?

Not yet, but let's take a look at the case where I want to accept incoming H.323 calls. For incoming, the situation is the reverse:

Source Port

Source Host

Dest Port

Dest Host

Flags

Action

>1024

*

>1024

[inside]

*

Allow

>1024

[inside]

>1024

*

ACK

Allow

*

*

*

*

*

Deny

And if I combine incoming and outgoing (and eliminate the overlap):

Source Port

Source Host

Dest Port

Dest Host

Flags

Action

>1024

*

>1024

[inside]

*

Allow

>1024

[inside]

>1024

*

*

Allow

*

*

*

*

*

Deny

Doing it right

In case you were wondering, CU-SeeMe was one of the original IP-based videoconferencing packages. Although newer versions do support H.323 as well, it also does things its own way. From the FAQ:

“If you are using CU-SeeMe through a firewall, you will need to open the following ports:

To use Chat, and receive grayscale video and audio (other than G.723), ports 7648 and 7649 must be open for TCP and UDP. To receive M-JPEG video, H.263 video, and G.723 audio, port 24032 must be open for UDP.”

Three ports. I like it.

In other words, I have to allow packets from any ephemeral port to any other ephemeral port in both directions. That is, I have to let the remote machine initiate TCP connections to any of my high-numbered ports. Actually, it gets a bit worse than that. Since the audio and video components are transmitted via UDP, we have to allow all TCP and UDP traffic between ephemeral ports in both directions. Suddenly, if I have any services running on high-numbered ports, they are wide open to attack.

So Much for the Packet Filter

Okay, so most people don't use traditional packet filters anymore. Generally, today's packet filters have some concept of state. Statefulness, however, doesn't help us in this scenario. We need to decipher the packet payload as it goes by to determine which ephemeral ports are being used. Since the traffic is encoded using the ASN.1 standard, we can't even expect to find this information in a fixed location within the packet. This means implementing a full-fledged application proxy: one that implements at least a partial H.323 interpreter stack. This also means modifying the H.323 client software to talk to the proxy.

So, H.323 can be used through a firewall, as long as someone is willing to write an H.323 interpreting proxy application, the vendors are willing to add proxy capability to their clients, and your firewall is capable of using proxies. A long string of ifs to accomplish what should have otherwise been a simple task. Had the protocol been designed with even a modicum of security in mind, this exercise would have been a lot less painful.

I'll leave you with a sidebar, entitled Doing it right. The sidebar contains a quote from the CU-Seeme FAQ. Apparently, somebody does get it.

H.323 References

Other Related Information

pintday.org » Fresh every Tuesday.