Nytro Posted July 22, 2018 Report Posted July 22, 2018 Yesterday curl released a security advisory for a vulnerability reported by Alex Nichols. The vulnerable code is in lib/curl_ntlm_core.c of libcurl and specifically in Curl_ntlm_core_mk_ntlmv2_hash() function. Below you see the vulnerable function. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode * (uppercase UserName + Domain) as the data */ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, const char *domain, size_t domlen, unsigned char *ntlmhash, unsigned char *ntlmv2hash) { /* Unicode representation */ size_t identity_len = (userlen + domlen) * 2; unsigned char *identity = malloc(identity_len); CURLcode result = CURLE_OK; if(!identity) return CURLE_OUT_OF_MEMORY; ascii_uppercase_to_unicode_le(identity, user, userlen); ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), ntlmv2hash); free(identity); return result; } The “identity_len” is calculating the sum of the username and password lengths, and multiplies the result by two. Then, the result is used to allocate a heap buffer via malloc() and the subsequent calls use the newly allocated “identity” heap buffer. However, if the username and password length is larger than 2GB on architectures were “size_t” data type is 32-bit the “(userlen + domlen) * 2”, it will result in an integer overflow which will leads in a tiny buffer being allocated via malloc() and resulting in a heap based buffer overflow in the subsequent calls. Below you can see how Daniel Stenberg patched lib/curl_ntlm_core.c to fix this vulnerability. First, a new pre-processor definition was added to ensure that the appropriate (per architecture) maximum value for “size_t” data type is set to the “SIZE_T_MAX” constant. 1 2 3 4 5 6 7 8 #ifndef SIZE_T_MAX /* some limits.h headers have this defined, some don't */ #if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) #define SIZE_T_MAX 18446744073709551615U #else #define SIZE_T_MAX 4294967295U #endif #endif And as expected, this new constant is used in Curl_ntlm_core_mk_ntlmv2_hash() function to ensure that the length calculation will not result in an integer overflow. In case it exceeds this limit the code will return “CURLE_OUT_OF_MEMORY” error code. You can see the diff below. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /* Unicode representation */ - size_t identity_len = (userlen + domlen) * 2; - unsigned char *identity = malloc(identity_len); + size_t identity_len; + unsigned char *identity; CURLcode result = CURLE_OK; + /* we do the length checks below separately to avoid integer overflow risk + on extreme data lengths */ + if((userlen > SIZE_T_MAX/2) || + (domlen > SIZE_T_MAX/2) || + ((userlen + domlen) > SIZE_T_MAX/2)) + return CURLE_OUT_OF_MEMORY; + + identity_len = (userlen + domlen) * 2; + identity = malloc(identity_len); + if(!identity) Sursa: https://xorl.wordpress.com/2017/11/30/cve-2017-8816-curl-ntlm-authentication-buffer-overflow/ 1 Quote