CVE-2023-49786 (published 2023-12-14T20:15Z)

Asterisk is an open source private branch exchange and telephony toolkit. In Asterisk prior to versions 18.20.1, 20.5.1, and 21.0.1; as well as certified-asterisk prior to 18.9-cert6; Asterisk is susceptible to a DoS due to a race condition in the hello handshake phase of the DTLS protocol when handling DTLS-SRTP for media setup. This attack can be done continuously, thus denying new DTLS-SRTP encrypted calls during the attack. Abuse of this vulnerability may lead to a massive Denial of Service on vulnerable Asterisk servers for calls that rely on DTLS-SRTP. Commit d7d7764cb07c8a1872804321302ef93bf62cba05 contains a fix, which is part of versions 18.20.1, 20.5.1, 21.0.1, amd 18.9-cert6.

CVSS v3 base score: 5.9, MEDIUM (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-362
cwe_name: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
description: The product contains a code sequence that can run concurrently with other code, and the code sequence requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence that is operating concurrently.
extended_description: 
            This can have security implications when the expected synchronization is in security-critical code, such as recording whether a user is authenticated or modifying important state information that should not be influenced by an outsider.
            A race condition occurs within concurrent environments, and is effectively a property of a code sequence. Depending on the context, a code sequence may be in the form of a function call, a small number of instructions, a series of program invocations, etc.
            A race condition violates these properties, which are closely related:
               
                  Exclusivity - the code sequence is given exclusive access to the shared resource, i.e., no other code sequence can modify properties of the shared resource before the original sequence has completed execution.
                  Atomicity - the code sequence is behaviorally atomic, i.e., no other thread or process can concurrently execute the same sequence of instructions (or a subset) against the same resource.
               
            A race condition exists when an "interfering code sequence" can still access the shared resource, violating exclusivity. Programmers may assume that certain code sequences execute too quickly to be affected by an interfering code sequence; when they are not, this violates atomicity. For example, the single "x++" statement may appear atomic at the code layer, but it is actually non-atomic at the instruction layer, since it involves a read (the original value of x), followed by a computation (x+1), followed by a write (save the result to x).
            The interfering code sequence could be "trusted" or "untrusted." A trusted interfering code sequence occurs within the product; it cannot be modified by the attacker, and it can only be invoked indirectly. An untrusted interfering code sequence can be authored directly by the attacker, and typically it is external to the vulnerable product.
         
         

Fix information:
repo_url: https://github.com/asterisk/asterisk
commit_details: repo_url: https://github.com/asterisk/asterisk
author: George Joseph
author_date: 2023-11-09 09:14:03-07:00
msg: res_rtp_asterisk.c: Check DTLS packets against ICE candidate list

When ICE is in use, we can prevent a possible DOS attack by allowing
DTLS protocol messages (client hello, etc) only from sources that
are in the active remote candidates list.

Resolves: GHSA-hxj9-xwr8-w8pq
repository: repo_url: https://github.com/asterisk/asterisk
repo_name: asterisk/asterisk
description: The official Asterisk Project repository.
repo_language: C
owner: asterisk
file_changes: filename: res_rtp_asterisk.c
change_type: ModificationType.MODIFY
diff: @@ -3207,6 +3207,61 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
 
 		ast_debug_dtls(3, "(%p) DTLS - __rtp_recvfrom rtp=%p - Got SSL packet '%d'\n", instance, rtp, *in);
 
+		/*
+		 * If ICE is in use, we can prevent a possible DOS attack
+		 * by allowing DTLS protocol messages (client hello, etc)
+		 * only from sources that are in the active remote
+		 * candidates list.
+		 */
+
+		if (rtp->ice) {
+			int pass_src_check = 0;
+			struct ao2_iterator i;
+			struct ast_rtp_engine_ice_candidate *candidate;
+			int cand_cnt = 0;
+
+			/*
+			 * You'd think that this check would cause a "deadlock"
+			 * because ast_rtp_ice_start_media calls dtls_perform_handshake
+			 * before it sets ice_media_started = 1 so how can we do a
+			 * handshake if we're dropping packets before we send them
+			 * to openssl.  Fortunately, dtls_perform_handshake just sets
+			 * up openssl to do the handshake and doesn't actually perform it
+			 * itself and the locking prevents __rtp_recvfrom from
+			 * running before the ice_media_started flag is set.  So only
+			 * unexpected DTLS packets can get dropped here.
+			 */
+			if (!rtp->ice_media_started) {
+				ast_log(LOG_WARNING, "%s: DTLS packet from %s dropped. ICE not completed yet.\n",
+					ast_rtp_instance_get_channel_id(instance),
+					ast_sockaddr_stringify(sa));
+				return 0;
+			}
+
+			/*
+			 * If we got this far, then ice_active_remote_candidates
+			 * can't be NULL.
+			 */
+			i = ao2_iterator_init(rtp->ice_active_remote_candidates, 0);
+			while ((candidate = ao2_iterator_next(&i)) && (cand_cnt < PJ_ICE_MAX_CAND)) {
+				res = ast_sockaddr_cmp_addr(&candidate->address, sa);
+				ao2_ref(candidate, -1);
+				if (res == 0) {
+					pass_src_check = 1;
+					break;
+				}
+				cand_cnt++;
+			}
+			ao2_iterator_destroy(&i);
+
+			if (!pass_src_check) {
+				ast_log(LOG_WARNING, "%s: DTLS packet from %s dropped. Source not in ICE active candidate list.\n",
+					ast_rtp_instance_get_channel_id(instance),
+					ast_sockaddr_stringify(sa));
+				return 0;
+			}
+		}
+
 		/*
 		 * A race condition is prevented between dtls_perform_handshake()
 		 * and this function because both functions have to get the

programming_language: C