[Pkg-voip-commits] r7002 - in /asterisk/branches/lenny/debian: changelog patches/AST-2009-003 patches/series

tzafrir-guest at alioth.debian.org tzafrir-guest at alioth.debian.org
Wed Apr 15 09:52:40 UTC 2009


Author: tzafrir-guest
Date: Wed Apr 15 09:52:40 2009
New Revision: 7002

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=7002
Log:
Patch AST-2009-003 (CVE-2008-3903) - SIP responses expose valid usernames
(Closes: #522528).

Added:
    asterisk/branches/lenny/debian/patches/AST-2009-003
Modified:
    asterisk/branches/lenny/debian/changelog
    asterisk/branches/lenny/debian/patches/series

Modified: asterisk/branches/lenny/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny/debian/changelog?rev=7002&op=diff
==============================================================================
--- asterisk/branches/lenny/debian/changelog (original)
+++ asterisk/branches/lenny/debian/changelog Wed Apr 15 09:52:40 2009
@@ -6,8 +6,10 @@
   * Patch fix_fxo_alarm: Fix Zaptel FXO alarm detection on startup 
    (Closes: #516838).
   * Properly clean h323, as disclean doesn't.
-
- -- Tzafrir Cohen <tzafrir.cohen at xorcom.com>  Sat, 21 Feb 2009 16:08:59 +0200
+  * Patch AST-2009-003 (CVE-2008-3903) - SIP responses expose valid usernames
+    (Closes: #522528).
+
+ -- Tzafrir Cohen <tzafrir.cohen at xorcom.com>  Sun, 05 Apr 2009 00:38:53 +0300
 
 asterisk (1:1.4.21.2~dfsg-3) unstable; urgency=medium
 

Added: asterisk/branches/lenny/debian/patches/AST-2009-003
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny/debian/patches/AST-2009-003?rev=7002&op=file
==============================================================================
--- asterisk/branches/lenny/debian/patches/AST-2009-003 (added)
+++ asterisk/branches/lenny/debian/patches/AST-2009-003 Wed Apr 15 09:52:40 2009
@@ -1,0 +1,182 @@
+Fix for AST-2009-003 (CVE-2008-3903) - SIP responses expose valid usernames
+
+From: http://downloads.digium.com/pub/security/AST-2009-003-1.4.diff
+
+--- a/channels/chan_sip.c
++++ b/channels/chan_sip.c
+@@ -1247,7 +1247,7 @@ static int transmit_response_with_sdp(st
+ static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);
+ static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
+ static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
+-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, int reliable);
++static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, int reliable);
+ static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
+ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);
+ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init);
+@@ -8642,10 +8642,96 @@ static int cb_extensionstate(char *conte
+ /*! \brief Send a fake 401 Unauthorized response when the administrator
+   wants to hide the names of local users/peers from fishers
+  */
+-static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, int reliable)
++static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, int reliable)
+ {
+-	ast_string_field_build(p, randdata, "%08lx", ast_random());	/* Create nonce for challenge */
+-	transmit_response_with_auth(p, "401 Unauthorized", req, p->randdata, reliable, "WWW-Authenticate", 0);
++	/* We have to emulate EXACTLY what we'd get with a good peer
++	 * and a bad password, or else we leak information. */
++	const char *response = "407 Proxy Authentication Required";
++	const char *reqheader = "Proxy-Authorization";
++	const char *respheader = "Proxy-Authenticate";
++	const char *authtoken;
++	struct ast_dynamic_str *buf;
++	char *c;
++
++	/* table of recognised keywords, and their value in the digest */
++	enum keys { K_NONCE, K_LAST };
++	struct x {
++		const char *key;
++		const char *s;
++	} *i, keys[] = {
++		[K_NONCE] = { "nonce=", "" },
++		[K_LAST] = { NULL, NULL}
++	};
++
++	if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) {
++		response = "401 Unauthorized";
++		reqheader = "Authorization";
++		respheader = "WWW-Authenticate";
++	}
++	authtoken = get_header(req, reqheader);
++	if (ast_test_flag(req, SIP_PKT_IGNORE) && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) {
++		/* This is a retransmitted invite/register/etc, don't reconstruct authentication
++		 * information */
++		transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0);
++		/* Schedule auto destroy in 32 seconds (according to RFC 3261) */
++		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++		return;
++	} else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) {
++		/* We have no auth, so issue challenge and request authentication */
++		ast_string_field_build(p, randdata, "%08lx", ast_random());	/* Create nonce for challenge */
++		transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0);
++		/* Schedule auto destroy in 32 seconds */
++		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++		return;
++	}
++
++	if (!(buf = ast_dynamic_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) {
++		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
++		return;
++	}
++
++	/* Make a copy of the response and parse it */
++	if (ast_dynamic_str_thread_set(&buf, 0, &check_auth_buf, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) {
++		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
++		return;
++	}
++
++	c = buf->str;
++
++	while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */
++		for (i = keys; i->key != NULL; i++) {
++			const char *separator = ",";	/* default */
++
++			if (strncasecmp(c, i->key, strlen(i->key)) != 0) {
++				continue;
++			}
++			/* Found. Skip keyword, take text in quotes or up to the separator. */
++			c += strlen(i->key);
++			if (*c == '"') { /* in quotes. Skip first and look for last */
++				c++;
++				separator = "\"";
++			}
++			i->s = c;
++			strsep(&c, separator);
++			break;
++		}
++		if (i->key == NULL) { /* not found, jump after space or comma */
++			strsep(&c, " ,");
++		}
++	}
++
++	/* Verify nonce from request matches our nonce.  If not, send 401 with new nonce */
++	if (strcasecmp(p->randdata, keys[K_NONCE].s)) {
++		if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
++			ast_string_field_build(p, randdata, "%08lx", ast_random());
++		}
++		transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE);
++
++		/* Schedule auto destroy in 32 seconds */
++		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++	} else {
++		transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
++	}
+ }
+ 
+ /*! \brief Verify registration of user 
+@@ -8779,6 +8865,14 @@ static enum check_auth_result register_v
+ 			}
+ 		}
+ 	}
++	if (!peer && global_alwaysauthreject) {
++		/* If we found a peer, we transmit a 100 Trying.  Therefore, if we're
++		 * trying to avoid leaking information, we MUST also transmit the same
++		 * response when we DON'T find a peer. */
++		transmit_response(p, "100 Trying", req);
++		/* Insert a fake delay between the 100 and the subsequent failure. */
++		sched_yield();
++	}
+ 	if (!res) {
+ 		ast_device_state_changed("SIP/%s", peer->name);
+ 	}
+@@ -8789,7 +8883,7 @@ static enum check_auth_result register_v
+ 			transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
+ 			break;
+ 		case AUTH_USERNAME_MISMATCH:
+-			/* Username and digest username does not match. 
++			/* Username and digest username does not match.
+ 			   Asterisk uses the From: username for authentication. We need the
+ 			   users to use the same authentication user name until we support
+ 			   proper authentication by digest auth name */
+@@ -8799,7 +8893,7 @@ static enum check_auth_result register_v
+ 		case AUTH_PEER_NOT_DYNAMIC:
+ 		case AUTH_ACL_FAILED:
+ 			if (global_alwaysauthreject) {
+-				transmit_fake_auth_response(p, &p->initreq, 1);
++				transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, 1);
+ 			} else {
+ 				/* URI not found */
+ 				if (res == AUTH_PEER_NOT_DYNAMIC)
+@@ -13966,7 +14060,7 @@ static int handle_request_invite(struct 
+ 		if (res < 0) { /* Something failed in authentication */
+ 			if (res == AUTH_FAKE_AUTH) {
+ 				ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
+-				transmit_fake_auth_response(p, req, 1);
++				transmit_fake_auth_response(p, SIP_INVITE, req, 1);
+ 			} else {
+   				ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
+ 				transmit_response_reliable(p, "403 Forbidden", req);
+@@ -14992,7 +15086,7 @@ static int handle_request_subscribe(stru
+ 	if (res < 0) {
+ 		if (res == AUTH_FAKE_AUTH) {
+ 			ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
+-			transmit_fake_auth_response(p, req, 1);
++			transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, 1);
+ 		} else {
+ 			ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
+ 			transmit_response_reliable(p, "403 Forbidden", req);
+--- a/configs/sip.conf.sample
++++ b/configs/sip.conf.sample
+@@ -126,9 +126,11 @@ srvlookup=yes			; Enable DNS SRV lookups
+ ;callevents=no			; generate manager events when sip ua 
+ 				; performs events (e.g. hold)
+ ;alwaysauthreject = yes		; When an incoming INVITE or REGISTER is to be rejected,
+- 		    		; for any reason, always reject with '401 Unauthorized'
++ 				; for any reason, always reject with an identical response
++ 				; equivalent to valid username and invalid password/hash
+  				; instead of letting the requester know whether there was
+- 				; a matching user or peer for their request
++ 				; a matching user or peer for their request.  This reduces
++ 				; the ability of an attacker to scan for valid SIP usernames.
+ 
+ ;g726nonstandard = yes		; If the peer negotiates G726-32 audio, use AAL2 packing
+ 				; order instead of RFC3551 packing order (this is required

Modified: asterisk/branches/lenny/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/lenny/debian/patches/series?rev=7002&op=diff
==============================================================================
--- asterisk/branches/lenny/debian/patches/series (original)
+++ asterisk/branches/lenny/debian/patches/series Wed Apr 15 09:52:40 2009
@@ -1,5 +1,6 @@
 # Some simple security fixes:
 AST-2009-001
+AST-2009-003
 
 ### upstream fixes
 allow-tilde-destdir




More information about the Pkg-voip-commits mailing list