[Git][pkg-voip-team/asterisk][buster] 6 commits: CVE-2019-15297: AST-2019-004: Crash when negotiating for T.38 with a declined stream

Bernhard Schmidt gitlab at salsa.debian.org
Wed Aug 26 23:54:56 BST 2020



Bernhard Schmidt pushed to branch buster at Debian VoIP Packaging Team / asterisk


Commits:
ea524cba by Bernhard Schmidt at 2020-08-27T00:49:28+02:00
CVE-2019-15297: AST-2019-004: Crash when negotiating for T.38 with a declined stream

Closes: #940060

- - - - -
4a139ce9 by Bernhard Schmidt at 2020-08-27T00:49:47+02:00
CVE-2019-18790: AST-2019-006: SIP request can change address of a SIP peer

Closes: #947381

- - - - -
dd6e110b by Bernhard Schmidt at 2020-08-27T00:49:59+02:00
CVE-2019-18610: AST-2019-007: AMI user could execute system commands

Closes: #947377

- - - - -
0e548729 by Bernhard Schmidt at 2020-08-27T00:51:27+02:00
Fix use-after-free with TEST_FRAMEWORK enabled

res_pjsip_session: ast_json_vpack: Invalid UTF-8 string on hangup when TEST_FRAMEWORK enabled

ASTERISK-28445

Closes: #966334

- - - - -
4d0120a0 by Bernhard Schmidt at 2020-08-27T00:52:47+02:00
Fix segfault in pjsip show history with IPv6 peers

ASTERISK-28854

Closes: #882145

- - - - -
5561ecdd by Bernhard Schmidt at 2020-08-27T00:54:48+02:00
Changelog for 1:16.2.1~dfsg-1+deb10u2

- - - - -


7 changed files:

- debian/changelog
- + debian/patches/AST-2019-004.patch
- + debian/patches/AST-2019-006.patch
- + debian/patches/AST-2019-007.patch
- + debian/patches/fix-error-building-json.patch
- + debian/patches/fix-sigsegv-pjsip-history.patch
- debian/patches/series


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,16 @@
+asterisk (1:16.2.1~dfsg-1+deb10u2) buster; urgency=medium
+
+  * CVE-2019-15297: AST-2019-004
+    Crash when negotiating for T.38 with a declined stream (Closes: #940060)
+  * CVE-2019-18790: AST-2019-006
+    SIP request can change address of a SIP peer (Closes: #947381)
+  * CVE-2019-18610: AST-2019-007
+    AMI user could execute system commands (Closes: #947377)
+  * Fix use-after-free with TEST_FRAMEWORK enabled (Closes: #966334)
+  * Fix segfault in pjsip show history with IPv6 peers (Closes: #882145)
+
+ -- Bernhard Schmidt <berni at debian.org>  Thu, 27 Aug 2020 00:53:40 +0200
+
 asterisk (1:16.2.1~dfsg-1+deb10u1) buster; urgency=medium
 
   * AST-2019-002 / CVE-2019-12827


=====================================
debian/patches/AST-2019-004.patch
=====================================
@@ -0,0 +1,171 @@
+From 965df3c228d49bcde3503e0482f3c831dcbf6c77 Mon Sep 17 00:00:00 2001
+From: Kevin Harwell <kharwell at digium.com>
+Date: Tue, 20 Aug 2019 15:05:45 -0500
+Subject: [PATCH] AST-2019-004 - res_pjsip_t38.c: Add NULL checks before using session media
+
+After receiving a 200 OK with a declined stream in response to a T.38
+initiated re-invite Asterisk would crash when attempting to dereference
+a NULL session media object.
+
+This patch checks to make sure the session media object is not NULL before
+attempting to use it.
+
+ASTERISK-28495
+patches:
+  ast-2019-004.patch submitted by Alexei Gradinari (license 5691)
+
+Change-Id: I168f45f4da29cfe739acf87e597baa2aae7aa572
+---
+
+diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
+index 11804e2..e5c6090 100644
+--- a/res/res_pjsip_t38.c
++++ b/res/res_pjsip_t38.c
+@@ -203,7 +203,6 @@
+ {
+ 	RAII_VAR(struct ast_sip_session *, session, obj, ao2_cleanup);
+ 	RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "t38"), ao2_cleanup);
+-	struct ast_sip_session_media *session_media;
+ 
+ 	if (!datastore) {
+ 		return 0;
+@@ -212,8 +211,7 @@
+ 	ast_debug(2, "Automatically rejecting T.38 request on channel '%s'\n",
+ 		session->channel ? ast_channel_name(session->channel) : "<gone>");
+ 
+-	session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
+-	t38_change_state(session, session_media, datastore->data, T38_REJECTED);
++	t38_change_state(session, NULL, datastore->data, T38_REJECTED);
+ 	ast_sip_session_resume_reinvite(session);
+ 
+ 	return 0;
+@@ -322,28 +320,37 @@
+ 		int index;
+ 
+ 		session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
+-		t38_change_state(session, session_media, state, T38_ENABLED);
++		if (!session_media) {
++			ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but no active session media\n",
++					status.code, session->channel ? ast_channel_name(session->channel) : "unknown channel");
++		} else {
++			t38_change_state(session, session_media, state, T38_ENABLED);
+ 
+-		/* Stop all the streams in the stored away active state, they'll go back to being active once
+-		 * we reinvite back.
+-		 */
+-		for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
+-			struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
++			/* Stop all the streams in the stored away active state, they'll go back to being active once
++			 * we reinvite back.
++			 */
++			for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
++				struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
+ 
+-			if (session_media && session_media->handler && session_media->handler->stream_stop) {
+-				session_media->handler->stream_stop(session_media);
++				if (session_media && session_media->handler && session_media->handler->stream_stop) {
++					session_media->handler->stream_stop(session_media);
++				}
+ 			}
++
++			return 0;
+ 		}
+ 	} else {
+ 		session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
+-		t38_change_state(session, session_media, state, T38_REJECTED);
+-
+-		/* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
+-		ast_sip_session_media_state_free(state->media_state);
+-		state->media_state = NULL;
+-		ast_sip_session_media_state_reset(session->pending_media_state);
+ 	}
+ 
++	/* If no session_media then response contained a declined stream, so disable */
++	t38_change_state(session, NULL, state, session_media ? T38_REJECTED : T38_DISABLED);
++
++	/* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
++	ast_sip_session_media_state_free(state->media_state);
++	state->media_state = NULL;
++	ast_sip_session_media_state_reset(session->pending_media_state);
++
+ 	return 0;
+ }
+ 
+@@ -426,12 +433,10 @@
+ 		/* Negotiation can not take place without a valid max_ifp value. */
+ 		if (!parameters->max_ifp) {
+ 			if (data->session->t38state == T38_PEER_REINVITE) {
+-				session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
+-				t38_change_state(data->session, session_media, state, T38_REJECTED);
++				t38_change_state(data->session, NULL, state, T38_REJECTED);
+ 				ast_sip_session_resume_reinvite(data->session);
+ 			} else if (data->session->t38state == T38_ENABLED) {
+-				session_media = data->session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
+-				t38_change_state(data->session, session_media, state, T38_DISABLED);
++				t38_change_state(data->session, NULL, state, T38_DISABLED);
+ 				ast_sip_session_refresh(data->session, NULL, NULL, NULL,
+ 					AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, state->media_state);
+ 				state->media_state = NULL;
+@@ -454,6 +459,11 @@
+ 			state->our_parms.version = MIN(state->our_parms.version, state->their_parms.version);
+ 			state->our_parms.rate_management = state->their_parms.rate_management;
+ 			session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
++			if (!session_media) {
++				ast_log(LOG_ERROR, "Failed to negotiate parameters for reinvite on channel '%s' (No pending session media).\n",
++					data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
++				break;
++			}
+ 			ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
+ 			t38_change_state(data->session, session_media, state, T38_ENABLED);
+ 			ast_sip_session_resume_reinvite(data->session);
+@@ -468,8 +478,13 @@
+ 			}
+ 			state->our_parms = *parameters;
+ 			session_media = media_state->default_session[AST_MEDIA_TYPE_IMAGE];
++			if (!session_media) {
++				ast_log(LOG_ERROR, "Failed to negotiate parameters on channel '%s' (No default session media).\n",
++					data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
++				break;
++			}
+ 			ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
+-			t38_change_state(data->session, session_media, state, T38_LOCAL_REINVITE);
++			t38_change_state(data->session, NULL, state, T38_LOCAL_REINVITE);
+ 			ast_sip_session_refresh(data->session, NULL, t38_reinvite_sdp_cb, t38_reinvite_response_cb,
+ 				AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, media_state);
+ 		}
+@@ -478,12 +493,10 @@
+ 	case AST_T38_REFUSED:
+ 	case AST_T38_REQUEST_TERMINATE:         /* Shutdown T38 */
+ 		if (data->session->t38state == T38_PEER_REINVITE) {
+-			session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
+-			t38_change_state(data->session, session_media, state, T38_REJECTED);
++			t38_change_state(data->session, NULL, state, T38_REJECTED);
+ 			ast_sip_session_resume_reinvite(data->session);
+ 		} else if (data->session->t38state == T38_ENABLED) {
+-			session_media = data->session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
+-			t38_change_state(data->session, session_media, state, T38_DISABLED);
++			t38_change_state(data->session, NULL, state, T38_DISABLED);
+ 			ast_sip_session_refresh(data->session, NULL, NULL, NULL, AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, state->media_state);
+ 			state->media_state = NULL;
+ 		}
+@@ -493,6 +506,11 @@
+ 
+ 		if (data->session->t38state == T38_PEER_REINVITE) {
+ 			session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
++			if (!session_media) {
++				ast_log(LOG_ERROR, "Failed to request parameters for reinvite on channel '%s' (No pending session media).\n",
++					data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
++				break;
++			}
+ 			parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
+ 			parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
+ 			ast_queue_control_data(data->session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
+@@ -788,7 +806,7 @@
+ 
+ 	if ((session->t38state == T38_REJECTED) || (session->t38state == T38_DISABLED)) {
+ 		ast_debug(3, "Declining; T.38 state is rejected or declined\n");
+-		t38_change_state(session, session_media, state, T38_DISABLED);
++		t38_change_state(session, NULL, state, T38_DISABLED);
+ 		return 0;
+ 	}
+ 


=====================================
debian/patches/AST-2019-006.patch
=====================================
@@ -0,0 +1,73 @@
+From 8cdaa93e658a46e7baf6b606468b5e2c88a0133b Mon Sep 17 00:00:00 2001
+From: Ben Ford <bford at digium.com>
+Date: Mon, 21 Oct 2019 14:55:06 -0500
+Subject: [PATCH] chan_sip.c: Prevent address change on unauthenticated SIP request.
+
+If the name of a peer is known and a SIP request is sent using that
+peer's name, the address of the peer will change even if the request
+fails the authentication challenge. This means that an endpoint can
+be altered and even rendered unusuable, even if it was in a working
+state previously. This can only occur when the nat option is set to the
+default, or auto_force_rport.
+
+This change checks the result of authentication first to ensure it is
+successful before setting the address and the nat option.
+
+ASTERISK-28589 #close
+
+Change-Id: I581c5ed1da60ca89f590bd70872de2b660de02df
+---
+
+diff --git a/channels/chan_sip.c b/channels/chan_sip.c
+index 6ac2e61..4d79a47 100644
+--- a/channels/chan_sip.c
++++ b/channels/chan_sip.c
+@@ -19245,18 +19245,6 @@
+ 		bogus_peer = NULL;
+ 	}
+ 
+-	/*  build_peer, called through sip_find_peer, is not able to check the
+-	 *  sip_pvt->natdetected flag in order to determine if the peer is behind
+-	 *  NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
+-	 *  are set on the peer.  So we check for that here and set the peer's
+-	 *  address accordingly.
+-	 */
+-	set_peer_nat(p, peer);
+-
+-	if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
+-		ast_sockaddr_copy(&peer->addr, &p->recv);
+-	}
+-
+ 	if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) {
+ 		ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
+ 		sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED");
+@@ -19325,6 +19313,21 @@
+ 		ast_string_field_set(p, peermd5secret, NULL);
+ 	}
+ 	if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable))) {
++
++		/* build_peer, called through sip_find_peer, is not able to check the
++		 * sip_pvt->natdetected flag in order to determine if the peer is behind
++		 * NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
++		 * are set on the peer. So we check for that here and set the peer's
++		 * address accordingly. The address should ONLY be set once we are sure
++		 * authentication was a success. If, for example, an INVITE was sent that
++		 * matched the peer name but failed the authentication check, the address
++		 * would be updated, which is bad.
++		 */
++		set_peer_nat(p, peer);
++		if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
++			ast_sockaddr_copy(&peer->addr, &p->recv);
++		}
++
+ 		/* If we have a call limit, set flag */
+ 		if (peer->call_limit)
+ 			ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
+@@ -19424,6 +19427,7 @@
+ 		}
+ 	}
+ 	sip_unref_peer(peer, "check_peer_ok: sip_unref_peer: tossing temp ptr to peer from sip_find_peer");
++
+ 	return res;
+ }
+ 


=====================================
debian/patches/AST-2019-007.patch
=====================================
@@ -0,0 +1,46 @@
+From 7574be5110e049a44b8c8ead52cd1c2a5d442afa Mon Sep 17 00:00:00 2001
+From: George Joseph <gjoseph at digium.com>
+Date: Thu, 24 Oct 2019 11:41:23 -0600
+Subject: [PATCH] manager.c:  Prevent the Originate action from running the Originate app
+
+If an AMI user without the "system" authorization calls the
+Originate AMI command with the Originate application,
+the second Originate could run the "System" command.
+
+Action: Originate
+Channel: Local/1111
+Application: Originate
+Data: Local/2222,app,System,touch /tmp/owned
+
+If the "system" authorization isn't set, we now block the
+Originate app as well as the System, Exec, etc. apps.
+
+ASTERISK-28580
+Reported by: Eliel SardaƱons
+
+Change-Id: Ic4c9dedc34c426f03c8c14fce334a71386d8a5fa
+---
+
+diff --git a/doc/UPGRADE-staging/AMI-Originate.txt b/doc/UPGRADE-staging/AMI-Originate.txt
+new file mode 100644
+index 0000000..f2d3133
+--- /dev/null
++++ b/doc/UPGRADE-staging/AMI-Originate.txt
+@@ -0,0 +1,5 @@
++Subject: AMI
++
++The AMI Originate action, which optionally takes a dialplan application as
++an argument, no longer accepts "Originate" as the application due to
++security concerns.
+diff --git a/main/manager.c b/main/manager.c
+index f138801..1963151 100644
+--- a/main/manager.c
++++ b/main/manager.c
+@@ -5744,6 +5744,7 @@
+ 				                                     EAGI(/bin/rm,-rf /)       */
+ 				strcasestr(app, "mixmonitor") ||  /* MixMonitor(blah,,rm -rf)  */
+ 				strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf)       */
++				strcasestr(app, "originate") ||   /* Originate(Local/1234,app,System,rm -rf) */
+ 				(strstr(appdata, "SHELL") && (bad_appdata = 1)) ||       /* NoOp(${SHELL(rm -rf /)})  */
+ 				(strstr(appdata, "EVAL") && (bad_appdata = 1))           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
+ 				)) {


=====================================
debian/patches/fix-error-building-json.patch
=====================================
@@ -0,0 +1,30 @@
+From 4d56adf8fbbbaa6c05c547eb482f1d154ec006d4 Mon Sep 17 00:00:00 2001
+From: Sean Bright <sean.bright at gmail.com>
+Date: Tue, 03 Dec 2019 16:42:00 -0500
+Subject: [PATCH] res_pjsip_session.c: Prevent use-after-free with TEST_FRAMEWORK enabled
+
+We need to copy the endpoint name before we call ao2_cleanup() on it,
+otherwise we might try to access memory that has been reclaimed.
+
+ASTERISK-28445 #close
+Reported by: Bernhard Schmidt
+
+Change-Id: I404b952608aa606e0babd3c4108346721fb726b3
+---
+
+diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
+index 7373c19..bc01548 100644
+--- a/res/res_pjsip_session.c
++++ b/res/res_pjsip_session.c
+@@ -2150,8 +2150,10 @@
+ {
+ 	struct ast_sip_session *session = obj;
+ 	struct ast_sip_session_delayed_request *delay;
++
++	/* We dup the endpoint ID in case the endpoint gets freed out from under us */
+ 	const char *endpoint_name = session->endpoint ?
+-		ast_sorcery_object_get_id(session->endpoint) : "<none>";
++		ast_strdupa(ast_sorcery_object_get_id(session->endpoint)) : "<none>";
+ 
+ 	ast_debug(3, "Destroying SIP session with endpoint %s\n", endpoint_name);
+ 


=====================================
debian/patches/fix-sigsegv-pjsip-history.patch
=====================================
@@ -0,0 +1,30 @@
+From 29910aa451e8b815fdf21d997bffbb662653d261 Mon Sep 17 00:00:00 2001
+From: Roger James <roger at beardandsandals.co.uk>
+Date: Sat, 09 May 2020 08:46:51 +0100
+Subject: [PATCH] res_pjsip_history.c: Fix to stop SIGSEGV when IPv6 addresses are encountered.
+
+Changed source and destination address fields in struct
+pjsip_history_entry so that they are long enough to hold an IPv6
+address.
+
+ASTERISK-28854
+
+Change-Id: Id65bb9aa961e9ecbcb500815e18170f774e34d3e
+---
+
+diff --git a/res/res_pjsip_history.c b/res/res_pjsip_history.c
+index 10bcd96..e4b784d 100644
+--- a/res/res_pjsip_history.c
++++ b/res/res_pjsip_history.c
+@@ -64,9 +64,9 @@
+ 	/*! \brief Time the packet was transmitted/received */
+ 	struct timeval timestamp;
+ 	/*! \brief Source address */
+-	pj_sockaddr_in src;
++	pj_sockaddr src;
+ 	/*! \brief Destination address */
+-	pj_sockaddr_in dst;
++	pj_sockaddr dst;
+ 	/*! \brief Memory pool used to allocate \c msg */
+ 	pj_pool_t *pool;
+ 	/*! \brief The actual SIP message */


=====================================
debian/patches/series
=====================================
@@ -37,3 +37,12 @@ autoreconf-pjproject
 AST-2019-002.patch
 # AST-2019-003 / CVE-2019-13161
 AST-2019-003.patch
+# AST-2019-004 / CVE-2019-15297
+AST-2019-004.patch
+# AST-2019-006 / CVE-2019-18790
+AST-2019-006.patch
+# AST-2019-007 / CVE-2019-18610
+AST-2019-007.patch
+
+fix-error-building-json.patch
+fix-sigsegv-pjsip-history.patch



View it on GitLab: https://salsa.debian.org/pkg-voip-team/asterisk/-/compare/17ecfeb346601b9565bea83dd94413e18039167f...5561ecdd6410edafa9411bc597bc7d7c8df2f36e

-- 
View it on GitLab: https://salsa.debian.org/pkg-voip-team/asterisk/-/compare/17ecfeb346601b9565bea83dd94413e18039167f...5561ecdd6410edafa9411bc597bc7d7c8df2f36e
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-voip-maintainers/attachments/20200826/c35c8459/attachment-0001.html>


More information about the Pkg-voip-maintainers mailing list