[asterisk-dev] SIP, NAT, security concerns, oh my!
Kevin P. Fleming
kpfleming at digium.com
Fri Oct 21 17:52:01 CDT 2011
Sorry in advance for the length of this message... I've intentionally
included quite a lot of background information so that we can hopefully
be able to discuss this issue rapidly and reach consensus.
Recently, a potential security issue was brought to our attention: it
has existed in (probably) every version of Asterisk that included
chan_sip. It's not something we'd classify as 'critical' or even
'major', but it is a concern we want to address. Terry Wilson has spent
some time investigating it, and then he and I spent some time over the
last couple of days thinking about how (or if) it can be addressed.
The essence of the problem is this: it is possible under some
circumstances for an attacker to be able to enumerate (discover) the
names of SIP peers (and possibly users) defined on an Asterisk system.
If they can discover the valid peer names, they can then focus
password-guessing attacks on those names, which increases their chances
of being able to gain access to the system. Generally speaking we've
tried to make changes to Asterisk to remove this type of 'information
disclosure' vulnerability, in order to help Asterisk users keep their
systems as secure as possible.
Unfortunately in this case, we can't solve the problem without removing
a useful feature of chan_sip. Here's why:
According to RFC 3261, when Asterisk (acting as UAS) receives a SIP
request from another SIP entity (acting as UAC), any responses that
Asterisk generates must be sent back to the IP address that the request
was received from, but to the *port number* specified in the top-most
Via header included in the request (this is important: they are *NOT*
sent back to the port number the request was received from).
For most SIP clients, who are not sending their SIP requests across NAT
devices, this is not a problem; they'll send their requests from port
5060, and expect responses on port 5060 (and they'll either explicitly
specify port 5060 in that top-most Via header, or they'll leave it out
and let the RFC-specified default take effect). There could be some SIP
clients out there who send their requests from one port (port A), but
want to receive responses on a different port (port B). In this case,
the top-most Via header will include port B, not port A. In our
experience, this is extremely uncommon, but it is RFC compliant behavior.
When NAT devices enter the picture, though, things get more complicated
(as they always do). Going back to the 'normal' SIP clients, that send
requests from, and expect responses on, the same port... now they have a
problem. If they send their request from port 5060, and expect responses
on 5060, their top-most Via header will reflect that. However, when the
request crosses the NAT on its way to the UAS, it will appear to have
been sent from a different IP address and port number than the UAC sent
it from (by definition... network address translation). Asterisk (the
UAS) will respond back to the IP address that the NAT used to send the
request, but it will *NOT* respond to the port number the NAT assigned;
it will respond to the port number in the top-most Via header. Unless
the NAT device just happened to assign the same port number (and some
NAT devices will attempt to do that), or if the NAT administrator has
setup a static mapping for that port number, the response will be
lost... it will arrive at the NAT device, it won't match the port
mapping established when the request passed through, and the NAT device
won't forward it.
This dilemma was identified long ago (over 8 years), and an additional
RFC was published: RFC 3581. This RFC allows the 'rport' parameter to be
added to Via headers; this allows UACs who are aware that their requests
may be crossing a NAT device (or even if they aren't aware, but just
want to be as safe as possible) to indicate to the UAS that receives
their request that the UAS should respond to the port that the request
was received from, *NOT* the port listed in the top-most Via header.
Some people would say that this is how SIP should have worked from the
beginning, and that the extraction of *only* the port from the top-most
Via header never made any sense at all (I would personally agree with
those people), but history is what it is. In addition to this behavior
change, the 'rport' parameter also indicates that the UAS should report
back to the UAC the 'perceived' port number; this is useful, but is not
part of the problem being discussed here.
Asterisk supports RFC 3581, and if a UAC includes 'rport' in its
top-most Via header, Asterisk will indeed respond to both the IP address
*and* port number that the request was received from.
However (and here's where we run into trouble), there are some (maybe
many) SIP UAs out there that cannot (or just do not) include 'rport' in
the top-most Via headers of their requests. Because of this, these UAs
can be difficult to use behind a NAT device (unless the NAT is
configured specially as outlined above), because Asterisk can't deliver
responses to the UA (port number mismatch). In order to make these
devices 'work', Asterisk gained a 'nat' configuration option many, many
years ago that, if set to 'yes' (it defaults to 'no') tells chan_sip to
act *AS IF* the UAC had included 'rport' in its top-most Via header,
even if it didn't. This does in fact solve the problem; responses can
now be delivered to the UAC, and the fact that Asterisk adds 'rport' to
the Via header in the response is not harmful... the UAC just ignores it.
In later versions of Asterisk this configuration option gained some
additional behavior (enabling 'connection-oriented media' mode), but
again, that's not part of this issue. In recent versions, the value of
this option can even be specified as 'force_rport' to more clearly
indicate the desired behavior.
Now we get to the crux of the problem: this 'nat' option can be set both
at the '[general]' level in sip.conf, and also for peers. This means, of
course, that they values can differ (and frequently they will, but not
because the administrator intended for them to differ). This means there
are four possible combinations, with possible different behaviors. For
the purposes of this discussion, let's assume that a UAC is sending a
request (the request type does not matter) that does *NOT* include
'rport' in its top-most Via header. In addition, the UAC is purposely
sending its request from port A, but specifying port B in the top-most
Via header. Let's also assume there is a peer called 'alice' defined in
sip.conf.
Scenario 1: [general] nat=no, [alice] nat=no
No problem here; the behavior of Asterisk will be the same regardless of
whether the request matches the 'alice' peer or not.
Scenario 2: [general] nat=yes, [alice] nat=yes
No problem here; the behavior of Asterisk will be the same regardless of
whether the request matches the 'alice' peer or not.
Scenario 3: [general] nat=no, [alice] nat=yes
Problem here; if the request matches 'alice', Asterisk will respond to
port A. If the request does not match 'alice', Asterisk will respond to
port B.
Scenario 4: [general] nat=yes, [alice] nat=no
Problem here; if the request matches 'alice', Asterisk will respond to
port B. If the request does not match 'alice', Asterisk will respond to
port A.
As you can see, in both scenarios 3 and 4, if the attacker happens
across a peer name (or source IP address) that happens to match a peer
defined in sip.conf, and that peer's 'nat' setting differs from the
general NAT setting, the attacker will be able to notice the difference
in response pattern from when the request did not match any peer.
So now we know what the problem is, and what causes it. I'll offer up
some possible solutions below, and ask for you all to think about this
situation and help us decide on the right course of action. The eventual
goal here is to produce a security advisory document telling users about
the situation and what they can/should do to try to mitigate it; we
don't expect that there is any solution that will solve the problem for
all users.
Option 1:
Recommend that all users to switch to TCP (or TLS) for SIP
communications. If they have a version of Asterisk that supports TCP,
and devices that also support it, they can disable UDP support and avoid
this problem entirely (since TCP does not have these NAT traversal
issues to deal with).
Option 2:
Change Asterisk to always act in 'force_rport' mode, period
(non-configurable). It is possible that there may be some SIP UAs that
would break if Asterisk did not respond to the port listed in the
top-most Via header, but it seems rather unlikely at this point. Such
UAs would almost never be able to be used successfully behind a NAT
device. In addition, it is remotely possible that there are some SIP UAs
that will break if they see 'rport=<xxxx>' in the Via header returned by
Asterisk in its responses.
Option 3:
Allow 'force_rport' mode to be disabled, but change the default to
enable it, in all currently maintained branches (1.4, 1.6.2, 1.8, 10 and
trunk). This has the same caveats as Option 2, but at least if a user
*does* have one of these bizarre SIP UAs to deal with, they can set
'nat=no' for that device after carefully considering the ramifications
of the change.
There may be other options to consider, but Terry and I were unable to
come up with any.
So, questions for the assembled audience here:
Do you have any other options for us to consider?
Are you aware of any SIP UAs that actually *REQUIRE* "nat=no" to
interoperate with Asterisk?
Do you *always* set "nat=yes" on your SIP peer definitions? Do you also
set "nat=yes" in the '[general]' section? If not, why not?
--
Kevin P. Fleming
Digium, Inc. | Director of Software Technologies
Jabber: kfleming at digium.com | SIP: kpfleming at digium.com | Skype: kpfleming
445 Jan Davis Drive NW - Huntsville, AL 35806 - USA
Check us out at www.digium.com & www.asterisk.org
More information about the asterisk-dev
mailing list