CVE-2020-27507 (published 2023-03-15T20:15Z)

The Kamailio SIP before 5.5.0 server mishandles INVITE requests with duplicated fields and overlength tag, leading to a buffer overflow that crashes the server or possibly have unspecified other impact.

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

Weakness information:
cwe_id: CWE-120
cwe_name: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
description: The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
extended_description: A buffer overflow condition exists when a product attempts to put more data in a buffer than it can hold, or when it attempts to put data in a memory area outside of the boundaries of a buffer. The simplest type of error, and the most common cause of buffer overflows, is the "classic" case in which the product copies the buffer without restricting how much is copied. Other variants exist, but the existence of a classic overflow strongly suggests that the programmer is not considering even the most basic of security protections.
         

Fix information:
repo_url: https://github.com/kamailio/kamailio
commit_details: repo_url: https://github.com/kamailio/kamailio
author: Daniel-Constantin Mierla
author_date: 2020-10-09 22:15:12+02:00
msg: tm: do not add duplicate headers in local requests
repository: repo_url: https://github.com/kamailio/kamailio
repo_name: kamailio/kamailio
description: Kamailio - The Open Source SIP Server for large VoIP and real-time communication platforms -
repo_language: C
owner: kamailio
file_changes: filename: t_msgbuilder.c
change_type: ModificationType.MODIFY
diff: @@ -268,6 +268,7 @@ char *build_local_reparse(tm_cell_t *Trans,unsigned int branch,
 	struct hdr_field *reas1, *reas_last, *hdr;
 	int hadded = 0;
 	sr_cfgenv_t *cenv = NULL;
+	hdr_flags_t hdr_flags = 0;
 
 	invite_buf = Trans->uac[branch].request.buffer;
 	invite_len = Trans->uac[branch].request.buffer_len;
@@ -361,6 +362,11 @@ char *build_local_reparse(tm_cell_t *Trans,unsigned int branch,
 		switch(hf_type) {
 			case HDR_CSEQ_T:
 				/* find the method name and replace it */
+				if(hdr_flags &  HDR_CSEQ_F) {
+					LM_DBG("duplicate CSeq header\n");
+					goto errorhdr;
+				}
+				hdr_flags |=  HDR_CSEQ_F;
 				while ((s < invite_buf_end)
 					&& ((*s == ':') || (*s == ' ') || (*s == '\t') ||
 						((*s >= '0') && (*s <= '9')))
@@ -381,6 +387,12 @@ char *build_local_reparse(tm_cell_t *Trans,unsigned int branch,
 				break;
 
 			case HDR_TO_T:
+				if(hdr_flags &  HDR_TO_F) {
+					LM_DBG("duplicate To header\n");
+					goto errorhdr;
+				}
+				hdr_flags |=  HDR_TO_F;
+
 				if (to_len == 0) {
 					/* there is no To tag required, just copy paste
 					 * the header */
@@ -395,7 +407,25 @@ char *build_local_reparse(tm_cell_t *Trans,unsigned int branch,
 				break;
 
 			case HDR_FROM_T:
+				/* copy hf */
+				if(hdr_flags &  HDR_FROM_F) {
+					LM_DBG("duplicate From header\n");
+					goto errorhdr;
+				}
+				hdr_flags |=  HDR_FROM_F;
+				s = lw_next_line(s, invite_buf_end);
+				append_str(d, s1, s - s1);
+				break;
 			case HDR_CALLID_T:
+				/* copy hf */
+				if(hdr_flags &  HDR_CALLID_F) {
+					LM_DBG("duplicate Call-Id header\n");
+					goto errorhdr;
+				}
+				hdr_flags |=  HDR_CALLID_F;
+				s = lw_next_line(s, invite_buf_end);
+				append_str(d, s1, s - s1);
+				break;
 			case HDR_ROUTE_T:
 			case HDR_MAXFORWARDS_T:
 				/* copy hf */
@@ -495,6 +525,7 @@ char *build_local_reparse(tm_cell_t *Trans,unsigned int branch,
 	/* HDR_EOH_T was not found in the buffer, the message is corrupt */
 	LM_ERR("HDR_EOH_T was not found\n");
 
+errorhdr:
 	shm_free(cancel_buf);
 error:
 	LM_ERR("cannot build %.*s request\n", method_len, method);

programming_language: C