[Home]

Summary:ASTERISK-26433: chan_sip: Allows To-tag checks to be bypassed, setting up new calls
Reporter:Walter Doekes (wdoekes)Labels:Security
Date Opened:2016-10-03 09:52:28Date Closed:2016-12-08 09:54:53.000-0600
Priority:MajorRegression?No
Status:Closed/CompleteComponents:Channels/chan_sip/Interoperability
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:( 0) ASTERISK-26433_hcolon_skip_only_sp_htab-master.patch
( 1) ASTERISK-26433_hcolon_skip_only_sp_htab-v11.patch
( 2) ASTERISK-26433_hcolon_skip_only_sp_htab-v13.patch
( 3) ASTERISK-26433_hcolon_skip_only_sp_htab-v14.patch
Description:(Sorry for yet another chan_sip issue. Along with a pesky retransmit issue
it's probably time to start moving some stuff towards pjsip. This is
basically a rerun of ASTERISK-4991 and a good reason why pedantic
was switched to yes by default in 2787a1400.)

h2. Issue

chan_sip treats some control characters as blanks, while many proxies
treat non-space control characters as regular tokens.

In certain setups with an authenticating proxy in front of Asterisk,
this discrepancy can allow an attacker to bypass the authentication.

Requirements:

* A dialog unaware authenticating proxy in front of Asterisk.
* Trust between the proxy and Asterisk that the proxy has handled the
 authentication.
* Inside information of IP-addresses and valid account names; can be
 obtained by looking at a single authenticated call.

h2. Steps to reproduce

*Step #1:*

* Install Kamailio or any other proxy.
* kamailio.cfg -- this is a minimal script which conveys the general idea:
 authenticate new dialogs, pass in-dialog requests along without auth.

{noformat}
mpath="/usr/local/lib/kamailio/modules_k/:/usr/lib/x86_64-linux-gnu/kamailio/modules/"

loadmodule "tm.so"  # must be loaded first

loadmodule "auth.so"
loadmodule "pv.so"
loadmodule "rr.so"
loadmodule "siputils.so"
loadmodule "sl.so"
loadmodule "xlog.so"

# Main route block
route {
route(WITHINDLG);
route(NEWDLG);
}

# Handle new SIP dialogs
route[NEWDLG] {
# username must be: myuser or myser2
if ($fU == "myuser" || $fU == "myuser2") {
# password must be: mypassword
$avp(password) = "mypassword";
if (!pv_proxy_authenticate("$fd", "$avp(password)", "0")) {
proxy_challenge("$fd", "1");
exit;
}
consume_credentials();
# pass it along
$du = "sip:127.0.0.1:5070";
record_route();
route(RELAY);
}
# or deny
sl_send_reply("403", "Nope");
}

# Handle requests within SIP dialogs
route[WITHINDLG] {
if (has_totag()) {
# sequential request withing a dialog should
# take the path determined by record-routing
if (loose_route()) {
route(RELAY);
} else if ($rm == "ACK") {
if (t_check_trans()) {
route(RELAY);
}
exit;
} else {
sl_send_reply("404", "Not here");
}
exit;
}
}

# Pass it along
route[RELAY] {
xlog("$rm $fU -> $du/$ru\n");
t_relay();
exit;
}
{noformat}

* Two users are defined in the script (myuser and myuser2) and a
 password (mypassword).

*Step #2:*

* Install Asterisk
* sip.conf

{noformat}
[general]
udpbindaddr=127.0.0.1:5070

[proxyuser](!)
host=127.0.0.1
port=5070
type=user

[myuser](proxyuser)
callerid=Alice

[myuser2](proxyuser)
callerid=Bob
{noformat}

* extensions.conf

{noformat}
[default]
exten => 123,1,NoOp(Call from ${CHANNEL(peername)} (${CALLERID(name)}) to ${EXTEN})
same => n,Answer()
same => n,Wait(1)
same => n,Hangup()
{noformat}

*Step #3:*

* Test that our calls are authenticated, for example using
 https://github.com/ossobv/sipp-scenarios/blob/master/out-in/oinv-i200-ibye.xml
 and this SIPp command:
 {{sipp -sf oinv-i200-ibye.xml -m 1 -s myuser2 -ap mypassword localhost -key tel 123}}
{noformat}
   -- Executing [123@default:1] NoOp("SIP/myuser2-00000003", "Call from myuser2 (Bob) to 123") in new stack
   -- Executing [123@default:2] Answer("SIP/myuser2-00000003", "") in new stack
   -- Executing [123@default:3] Wait("SIP/myuser2-00000003", "1") in new stack
   -- Executing [123@default:4] Hangup("SIP/myuser2-00000003", "") in new stack
{noformat}

_Sounds safe, right?_

* The proxy does the authentication so that Asterisk does not have to.
* For new dialogs (no to-tag) the proxy authenticates.
* For existing dialogs (a to-tag and Route headers) the proxy passes
 all SIP along to Asterisk.
* For a new dialog, if you send a to-tag and the right Route headers,
 the proxy would pass it along, but Asterisk will return a 481 because
 it is an unknown dialog *with* a to-tag.

However, if you abuse the different treatment of "blanks" between the
proxy and Asterisk, you can let a To-header without a to-tag slip
through, causing the proxy to think that it's an existing
(authenticated) call while Asterisk thinks it's a new call -- which now
has bypassed authentication.

Something like this:

{noformat}
INVITE sip:[tel]@[ua_ip] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
Route: <sip:[remote_ip];lr;ftag=4035SIPpTag001>
Record-Route: <sip:[remote_ip];lr;ftag=4035SIPpTag001>
...
To\x01: sip:[tel]@[remote_ip]:[remote_port]
To: sip:[tel]@[remote_ip]:[remote_port];tag=TAG_SO_WE_ARE_FORWARDED
{noformat}

The proxies will happily pass it along as an in-dialog transaction, because
the To-header has a tag.

chan_sip will see the first broken {{To\x01:}} (in pedantic mode) as {{To:}}
and now it's suddenly an out-of-dialog transaction and sets up a new call.


h2. Suggested fix:

Replace the {{ast_skip_blanks()}} in {{__get_header()}} with something
that only skips SP/HTAB.


Cheers,
Walter Doekes
OSSO B.V.
Comments:By: Asterisk Team (asteriskteam) 2016-10-03 09:52:28.747-0500

Thanks for creating a report! The issue has entered the triage process. That means the issue will wait in this status until a Bug Marshal has an opportunity to review the issue. Once the issue has been reviewed you will receive comments regarding the next steps towards resolution.

A good first step is for you to review the [Asterisk Issue Guidelines|https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines] if you haven't already. The guidelines detail what is expected from an Asterisk issue report.

Then, if you are submitting a patch, please review the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process].

By: Walter Doekes (wdoekes) 2016-11-21 06:50:13.229-0600

Ping :)

By: Kevin Harwell (kharwell) 2016-11-21 14:33:12.627-0600

If I understand correctly this essentially occurs only when the proxy allows an unauthorized call through? If there was no proxy and Asterisk received a similar invite it would reject the call as being unauthorized, correct?

If that's true I'm not sure it is a security concern since the problem seems to originate outside of Asterisk (meaning the proxy fails to do proper authentication). The problem may occur in Asterisk on unauthenticated calls but that could just fall under the normal bug category. Thoughts?

By: Walter Doekes (wdoekes) 2016-11-21 15:50:50.487-0600

It essentially occurs because we tell the proxy to handle authentication and trust it to do so. The proxy in turn trusts Asterisk not to create new calls for transactions to "existing" dialogs (those with the to-tag).

If there was no proxy, all calls would be unauthenticated and allowed. If there is only Asterisk, this wouldn't be an issue.

But there is a proxy, and it authenticates all *new* dialogs. Existing dialogs go unchecked: the proxy trusts Asterisk to 481 these transactions if they are new (and therefore unauthenticated).

> The problem may occur in Asterisk on unauthenticated calls but that could just fall under the normal bug category.

If you look at just Asterisk, you could say that there is no problem, because you've told Asterisk to not to do any authentication. But if you look at the SIP stack with proxies in front, I would argue that this is a security hole I'm certain exists in several places, of which the administrators/designers are unaware.

(You did restrict this issue a bit more than necessary by disallowing bug marshalls too. I wouldn't mind if more people weighed in on the matter.)

By: Corey Farrell (coreyfarrell) 2016-11-26 10:06:39.352-0600

I agree that this is a security issue and not just limited to the scenario [~wdoekes] reported.  To my knowledge proxies do not scrub unknown headers so any proxy could be fooled into forwarding any malicious header to Asterisk.  This could be used to bypass a blacklist implemented by a front-end proxy server, where {{To\x01}}.would contain a forbidden number and {{To}} would contain a permitted number.  This could also be used to override any header that is cleared and set by a proxy.  chan_sip would use the header provided directly by the attacker instead of the value sanitized by Kamailio.

By: Mark Michelson (mmichelson) 2016-11-28 14:00:19.884-0600

This is one of those issues that rides the fine line of whether it's a security issue or not. On the one hand, it requires a very specific setup for your deployment, and it requires reliance on an external agent to get around authentication built into Asterisk that would prevent this from happening. On the other hand, offloading authentication to a proxy is not uncommon, and the bug in Asterisk *can* result in undesired calls being allowed to happen. So in this case, I'll go ahead and agree that this is a security issue.

By: Friendly Automation (friendly-automation) 2016-12-08 09:54:54.938-0600

Change 4586 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4586|https://gerrit.asterisk.org/4586]

By: Friendly Automation (friendly-automation) 2016-12-08 09:55:57.681-0600

Change 4587 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4587|https://gerrit.asterisk.org/4587]

By: Friendly Automation (friendly-automation) 2016-12-08 09:56:12.940-0600

Change 4582 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4582|https://gerrit.asterisk.org/4582]

By: Friendly Automation (friendly-automation) 2016-12-08 09:56:27.249-0600

Change 4584 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4584|https://gerrit.asterisk.org/4584]

By: Friendly Automation (friendly-automation) 2016-12-08 09:56:38.477-0600

Change 4585 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4585|https://gerrit.asterisk.org/4585]

By: Friendly Automation (friendly-automation) 2016-12-08 09:56:54.916-0600

Change 4583 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4583|https://gerrit.asterisk.org/4583]

By: Friendly Automation (friendly-automation) 2016-12-08 11:05:57.481-0600

Change 4591 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4591|https://gerrit.asterisk.org/4591]

By: Friendly Automation (friendly-automation) 2016-12-08 11:06:13.014-0600

Change 4592 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4592|https://gerrit.asterisk.org/4592]

By: Friendly Automation (friendly-automation) 2016-12-08 11:06:35.620-0600

Change 4590 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4590|https://gerrit.asterisk.org/4590]

By: Friendly Automation (friendly-automation) 2016-12-08 14:05:03.598-0600

Change 4599 merged by Kevin Harwell:
chan_sip: Do not allow non-SP/HTAB between header key and colon.

[https://gerrit.asterisk.org/4599|https://gerrit.asterisk.org/4599]