Skip to content
Peter Samarin5 min read

How AI-generated fuzz test uncovered a severe vulnerability in wolfSSL

We are super excited to announce the discovery of a heap-based use-after-free vulnerability in wolfSSL, identified through a fuzz test automatically generated by an AI Test Agent. This marks another milestone in advancing automated security testing and demonstrates the power of AI-driven tools to improve software reliability and safety.

Discovery and Resolution

The vulnerability was identified in wolfSSL, an open-source cryptography library widely used in developing embedded devices and IoT systems, during the final week of October 2024. Remarkably, the discovery required no manual intervention—beyond setting up the project and typing "cifuzz spark" into the command line.

This fuzz test, automatically generated and executed by the AI Test Agent that we called Spark, uncovered the critical data that exposed the flaw. 

Spark, the AI Test Agent, is an enhancement to Сode Intelligence’s fuzz testing product CI Fuzz. Leveraging LLMs and advanced static analysis, it autonomously identifies the most critical functions in the codebase to fuzz, generates and runs fuzz tests, and, thus, finds bugs and vulnerabilities. 

Spark will be publicly demonstrated to the fuzz testing community on January 28, 2025. Secure your free spot here.

Spark uncovered the vulnerability in wolfSSL during its final beta testing. We reported the issue to the wolfSSL team immediately, and they responded with exceptional efficiency, resolving the vulnerability within 3 days. The fix was officially included in release 5.7.6 on 31 December 2024.

In the only manual step, we have assessed and confirmed that the vulnerability exists and is exploitable under specific conditions.

We encourage developers to update to the latest wolfSSL version to mitigate potential risks.

What Is a Heap-Based Use-After-Free?
A heap-based use-after-free vulnerability occurs when a program continues to access memory on the heap after it has been freed. In a typical scenario, a program allocates memory, uses it, and then frees it. However, if there is a mistake in memory management, such as a dangling pointer, a subsequent access attempt may interact with memory that has already been reallocated for another use.

This can lead to unexpected behavior, crashes, or—more worryingly—security exploits that allow attackers to execute arbitrary code or manipulate program behavior maliciously.

A Win for Automation in Software Security

This discovery highlights the potential of tools like AI-automated CI Fuzz to revolutionize software security. With the ability to identify complex vulnerabilities autonomously, such tools are bridging the gap between human expertise and the ever-growing scale of modern software systems.

We extend our gratitude to the wolfSSL team for their swift response.

Technical Details

The flaw involves an invalid memory read in the pem_read_bio_key() function which calls wolfssl_read_bio()and keeps the pointer mem that points to the BIO's internal data. If there is leftover data that needs to be written back to the BIO, the function uses the wolfSSL_BIO_write() function to handle this, which has the potential to reallocate the BIO internal buffer. This renders the pointer held in mem invalid as it now points to a freed memory. However, the write operation copies data from mem + ret into the newly allocated array. Since mem now points to freed memory, this operation results in a heap use-after-free vulnerability.

Relevant code in pem_read_bio_key (in src/pk.c) to explain the flaw

      C/C++
      0: static int pem_read_bio_key(WOLFSSL_BIO* bio,
         wc_pem_password_cb* cb, void* pass,
         int keyType, int* keyFormat, DerBuffer** der) {
      1:   int ret;
      2:   char* mem = NULL;
      3:   int memSz;
      4:   int alloced = 0;
      5:   ret = wolfssl_read_bio(bio, &mem, &memSz, &alloced);
      6:   ret = pem_mem_to_der(mem, memSz, cb, pass, keyType, keyFormat, der);
      7:   int res = wolfSSL_BIO_write(bio, mem + ret, memSz - ret);

Since wolfSSL is a generic library that is used in many applications, here is a sample scenario in which this vulnerability can be exploited. The example involves a multi-threaded application using WolfSSL that has two threads:

  • thread_1
    • writes some sensitive data into a BIO: wolfSSL_BIO_write(secretBio, secrets, sizeof(secrets))
    • reads a private key from the BIO using the vulnerable version of WolfSSL: wolfSSL_PEM_read_bio_PrivateKey(secretBio, NULL, 0, NULL);
    • subsequently reads some more secrets from secretBio
  • thread_2
    • is responsible for handling user connections; each connection is handled by another thread
    • writes user data into malloc-ed arrays

A possible scenario would be that during the call to wolfSSL_PEM_read_bio_PrivateKey in thread_1 with the BIO containing data from the reproducer that we shared to reproduce the vulnerability, right after reading the private key and freeing the buffer (the vulnerability found by the reproducer) during the call to wolfSSL_BIO_write(), if thread_2 happens to malloc an array in the same address range of the freed buffer, and fills the array with user data, this data will be copied back into the BIO.

If thread_1 gets preempted in step 7: in the above code snippet, right after the BIO memory is freed but before the memory at offset mem+ret is written back to the BIO, and switches the context to thread_2 that mallocs an array in the address range just freed in thread_1 and fills it with attacker payload, then when thread_1 is resumed, it will copy the payload back into the BIO.

Depending on the nature of the data in the BIO e.g., a signing key or certificate, the issue may lead to authentication bypass.

While the conditions to exploit this vulnerability don’t seem easy to meet, depending on how wolfSSL is used, the issue we found might expose any application that uses the vulnerable function to the attack outlined above. The following conditions must be possible:

  • BIO data containing secrets must have the structure provided in the reproducer that leads to the found heap-based use-after-free
  • a multithreaded environment that allows a thread to allocate and use memory in the freed address range of another thread
  • the thread calling wolfSSL_PEM_read_bio_PrivateKey has to be preempted at just the right moment
  • the thread writing payload has to run right after that and must copy user data into a freshly malloc-ed address range
  • that malloc-ed address range must include the same address range used in the BIO

Lowering Barriers to Secure Code with AI

event-2025-fuzzing-forward

The uncovered real-world vulnerability proves that AI can effectively take over manual tasks in fuzz testing, such as analyzing code, identifying the most likely attack vectors, generating and running tests, and can thereby yield great results. 

Join security and software development experts from leading companies like Continental, Mozilla, and Code Intelligence on January 28, 2025, to learn how AI shapes the future of fuzz testing and see a live demo of autonomous fuzzing.

Related Articles