CVE-2022-23537 (published 2022-12-20T19:15Z)

PJSIP is a free and open source multimedia communication library written in C language implementing standard based protocols such as SIP, SDP, RTP, STUN, TURN, and ICE. Buffer overread is possible when parsing a specially crafted STUN message with unknown attribute. The vulnerability affects applications that uses STUN including PJNATH and PJSUA-LIB. The patch is available as a commit in the master branch (2.13.1).

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-122
cwe_name: Heap-based Buffer Overflow
description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/pjsip/pjproject
commit_details: repo_url: https://github.com/pjsip/pjproject
author: Nanang Izzuddin
author_date: 2022-12-20 11:39:12+07:00
msg: Merge pull request from GHSA-9pfh-r8x4-w26w

* Fix buffer overread in STUN message decoder

* Updates based on comments
repository: repo_url: https://github.com/pjsip/pjproject
repo_name: pjsip/pjproject
description: PJSIP project
repo_language: C
owner: pjsip
file_changes: filename: stun_msg.h
change_type: ModificationType.MODIFY
diff: @@ -442,6 +442,7 @@ typedef enum pj_stun_status
 
    \endverbatim
  */
+#pragma pack(1)
 typedef struct pj_stun_msg_hdr
 {
     /**
@@ -473,6 +474,7 @@ typedef struct pj_stun_msg_hdr
     pj_uint8_t          tsx_id[12];
 
 } pj_stun_msg_hdr;
+#pragma pack()
 
 
 /**
@@ -490,6 +492,7 @@ typedef struct pj_stun_msg_hdr
 
    \endverbatim
  */
+#pragma pack(1)
 typedef struct pj_stun_attr_hdr
 {
     /**
@@ -506,6 +509,7 @@ typedef struct pj_stun_attr_hdr
     pj_uint16_t         length;
 
 } pj_stun_attr_hdr;
+#pragma pack()
 
 
 /**

programming_language: C
filename: stun_msg.c
change_type: ModificationType.MODIFY
diff: @@ -746,7 +746,7 @@ PJ_DEF(int) pj_stun_set_padding_char(int chr)
 
 #define INIT_ATTR(a,t,l)    (a)->hdr.type=(pj_uint16_t)(t), \
                             (a)->hdr.length=(pj_uint16_t)(l)
-#define ATTR_HDR_LEN        4
+#define ATTR_HDR_LEN        sizeof(pj_stun_attr_hdr)
 
 static pj_uint16_t GETVAL16H(const pj_uint8_t *buf, unsigned pos)
 {
@@ -2327,6 +2327,14 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
         status = pj_stun_msg_check(pdu, pdu_len, options);
         if (status != PJ_SUCCESS)
             return status;
+    } else {
+        /* For safety, verify packet length at least */
+        pj_uint32_t msg_len = GETVAL16H(pdu, 2) + 20;
+        if (msg_len > pdu_len ||
+            ((options & PJ_STUN_IS_DATAGRAM) && msg_len != pdu_len))
+        {
+            return PJNATH_EINSTUNMSGLEN;
+        }
     }
 
     /* Create the message, copy the header, and convert to host byte order */
@@ -2345,7 +2353,7 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
         p_response = NULL;
 
     /* Parse attributes */
-    while (pdu_len >= 4) {
+    while (pdu_len >= ATTR_HDR_LEN) {
         unsigned attr_type, attr_val_len;
         const struct attr_desc *adesc;
 
@@ -2357,7 +2365,7 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
         attr_val_len = (attr_val_len + 3) & (~3);
 
         /* Check length */
-        if (pdu_len < attr_val_len) {
+        if (pdu_len < attr_val_len + ATTR_HDR_LEN) {
             pj_str_t err_msg;
             char err_msg_buf[80];
 

programming_language: C