Skip to Content

The short story of curl CVE-2024-7264

It started when Daniel Stenberg, the curl project maintainer, announced the curl 8.9.0 release:

I was curious about CVE-2024-6197: it was a call to free(buf) where buf is a variable on the stack. Since this doesn’t depend on specific content of buf, and should happen every time this code is reached, why wasn’t it caught earlier during CI tests?

The answer is that it’s a bit hard to get to that area of the code (parsing of certificate ASN.1 format), and that entire file is not used for most TLS engines that curl supports. Daniel wrote last year about the difficulty of measuring coverage for curl, but the bottom line remains: the coverage of that particular source file is not perfect.

My friend who used to work on hardware verification told me about a rule of thumb in the verification field: if a bug is discovered in some module, it’s a good heuristic to keep poking the same module. I went and did exactly that: I compiled curl with the gnutls backend (which means the certificate parsing code is included) and with LLVM libFuzzer support. I wrote a small fuzzing harness for the internal Curl_extract_certinfo() function (which parses a certificate):

extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
  CURLcode result;
  struct Curl_easy *curldata;
  const char *beg = Data;
  const char *end = Data + Size;

  if (Size == 0) {
    return 0;
  }
  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
    return 2; // ? not sure what we should do here ?
  }
  curldata = curl_easy_init();
  if (curldata) {
    result = Curl_extract_certinfo(curldata, 0, beg, end);
    curl_easy_cleanup(curldata);
  }
  curl_global_cleanup();
  return 0;  // Values other than 0 and -1 are reserved for future use.
}

As an initial fuzzing corpus I used one file which is available as part of curl’s unit tests.

After a few minutes of fuzzing… a crash! Heap memory overread. I reported it on July 29 at the end of my day. By the time I woke up on July 30, Daniel and co-maintainer Stefan Icing already had a suggested fix. A couple of iterations later the final fix was merged. Daniel wrote the vulnerability advisory, which ended up as CVE-2024-7264 (low severity). Curl 8.9.1, which includes this fix, was released on July 31st 2024, and the advisory was made public at the same time.

It was a fun quick find, and I had a super nice and professional interaction with the curl project maintainers Daniel and Stefan.