CVE-2022-45909: Out-of-bounds Read (CWE-125)
value: drachtio-server before 0.8.19 has a heap-based buffer over-read via a long Request-URI in an INVITE request.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 9.1
Published: 2022-11-26T03:15Z
Repository: https://github.com/drachtio/drachtio-server
Language: C++
Files changed: src/drachtio.cpp, src/sip-dialog-controller.cpp
Commit date: 2022-11-06 11:27:55 -0500
Commit message: sending an invite with a request-uri longer than 255 characters can cause a crash (#238)


Diff: diff --git a/src/drachtio.cpp b/src/drachtio.cpp
index e9175b08d0..68216aeb3d 100644
--- a/src/drachtio.cpp
+++ b/src/drachtio.cpp
@@ -52,10 +52,12 @@ THE SOFTWARE.
 #include <sofia-sip/su_addrinfo.h>
 
 
 #define MAX_LINELEN 2047
 
+#define MAX_SIP_URI_LEN (1024)
+
 #define BOOST_UUID (1)
 
 using namespace std ;
  
 namespace {
@@ -334,21 +336,21 @@ namespace drachtio {
     }
 
     bool normalizeSipUri( std::string& uri, int brackets ) {
         su_home_t* home = theOneAndOnlyController->getHome() ;
         char *s ;
-        char buf[255];
-        char obuf[255] ;
+        char buf[MAX_SIP_URI_LEN];
+        char obuf[MAX_SIP_URI_LEN] ;
         char hp[64] ;
         char const *display = NULL;
         url_t url[1];
         msg_param_t const *params = NULL;
         char const *comment = NULL;
         int rc ;
 
         // buf gets passed into sip_name_addr_d which puts NULs in various locations so the url_t members can point to their bits
-        s = strncpy( buf, uri.c_str(), 255 ) ;
+        s = strncpy( buf, uri.c_str(), MAX_SIP_URI_LEN ) ;
 
         // first we decode the string
         rc = sip_name_addr_d(home, &s, &display, url, &params, &comment) ;
         if( rc < 0 ) {  
             // no go: if we can't decode it then we have an invalid input
@@ -372,18 +374,18 @@ namespace drachtio {
 
         if( nChars <= 0 ) {
             return false ;
         }
         uri.assign( obuf ) ;
-        return true ;
+        return uri.length() < MAX_SIP_URI_LEN ;
     }
 
     bool replaceHostInUri( std::string& uri, const char* szHost, const char* szPort ) {
         su_home_t* home = theOneAndOnlyController->getHome() ;
         char *s ;
-        char buf[255];
-        char obuf[255] ;
+        char buf[MAX_SIP_URI_LEN];
+        char obuf[MAX_SIP_URI_LEN] ;
         char hp[64] ;
         char const *display = NULL;
         url_t url[1];
         msg_param_t const *params = NULL;
         char const *comment = NULL;
@@ -402,11 +404,11 @@ namespace drachtio {
         // now we repoint host and port
         url->url_host = szHost ;
         url->url_port = szPort ;
 
         // now we re-encode it
-        int nChars = sip_name_addr_e(obuf, 255, 0, display, 1, url, params, comment) ;
+        int nChars = sip_name_addr_e(obuf, MAX_SIP_URI_LEN, 0, display, 1, url, params, comment) ;
 
         // cleanup: free the msg_params if any were allocated        
         if( params ) {
             su_free(home, (void *) params) ;
         }
diff --git a/src/sip-dialog-controller.cpp b/src/sip-dialog-controller.cpp
index 26cbd7b28c..6544a46788 100644
--- a/src/sip-dialog-controller.cpp
+++ b/src/sip-dialog-controller.cpp
@@ -527,11 +527,13 @@ namespace drachtio {
                     throw std::runtime_error("missing content-type") ;                   
                 }
              }
 
             //prevent looping messages
-            normalizeSipUri( requestUri, 0 ) ;
+            if (!normalizeSipUri( requestUri, 0 )) {
+                throw std::runtime_error(string("invalid request-uri: ") + requestUri ) ;
+            }
             if( isLocalSipUri( requestUri ) ) {
                 throw std::runtime_error("can not send request to myself") ;
             }
 
             if( !(leg = nta_leg_tcreate( m_pController->getAgent(),

Vulnerable code:         char buf[255];
        char obuf[255] ;
        s = strncpy( buf, uri.c_str(), 255 ) ;
        return true ;
        char buf[255];
        char obuf[255] ;
        int nChars = sip_name_addr_e(obuf, 255, 0, display, 1, url, params, comment) ;
            normalizeSipUri( requestUri, 0 ) ;
Fixed code: #define MAX_SIP_URI_LEN (1024)

        char buf[MAX_SIP_URI_LEN];
        char obuf[MAX_SIP_URI_LEN] ;
        s = strncpy( buf, uri.c_str(), MAX_SIP_URI_LEN ) ;
        return uri.length() < MAX_SIP_URI_LEN ;
        char buf[MAX_SIP_URI_LEN];
        char obuf[MAX_SIP_URI_LEN] ;
        int nChars = sip_name_addr_e(obuf, MAX_SIP_URI_LEN, 0, display, 1, url, params, comment) ;
            if (!normalizeSipUri( requestUri, 0 )) {
                throw std::runtime_error(string("invalid request-uri: ") + requestUri ) ;
            }