CVE-2022-43286 - A Deep Dive Into the Heap-Use-After-Free in Nginx NJS v.7.2

In late October 2022, a heap-use-after-free vulnerability, now known as CVE-2022-43286, was publicly disclosed in Nginx’s njs scripting engine (version .7.2). This subtle yet dangerous bug roots from an illegal memory copy operation in the njs_json_parse_iterator_call function (inside njs_json.c).

In this article, we’ll break down what that means, see a simplified version of the vulnerable code, look at how the bug can be exploited, and offer practical advice for anyone running affected Nginx or njs instances.

What Is Nginx NJS?

njs is a JavaScript-like scripting language, embedded into Nginx, used for custom request processing and transformations. A memory management bug in such a core component can have a real impact, especially when running untrusted scripts or data.

The Vulnerability Explained

The issue arises from faulty memory handling inside njs_json_parse_iterator_call. Specifically, after freeing memory tied to JavaScript structures, njs would still try to use or copy that memory.

Potentially run arbitrary code (as erroneous writes could be hijacked)

Affected versions: At least njs v.7.2  
Patched in: njs .7.5 and later

Here’s a simplified excerpt (in C-style pseudocode) showing the risky sequence in njs_json.c

static njs_int_t
njs_json_parse_iterator_call(njs_vm_t *vm, ...)
{
    // ... some setup code ...

    njs_json_free(vm, value); // Frees the value

    // Mistake: still tries to copy from the freed pointer
    memcpy(destination, value->data, size);

    // ... more operations ...
}

(For educational purposes only. See GitHub diff for the real patch.)

In this example, after free()’ing the object, the code still dereferences and copies data from it. Depending on what else the process is doing, this can result in:

Trigger JSON parsing using attacker-supplied input (e.g., via API or custom handler).

2. Spray the heap to control freed memory contents (using repeated allocations/frees).
3. Force njs to execute the vulnerable code, causing a use-after-free right when their payload occupies the dangling pointer.

Here’s a high-level pseudocode for a Nginx config calling njs

js_import conf.js;

server {
    location /test {
        js_content conf.handle_request;
    }
}

And a JavaScript handler (in conf.js) deliberately triggering the bug (abstractly)

function handle_request(r) {
    // User input via query param triggers JSON parse
    let obj = JSON.parse(r.args['payload']);
    // ... further actions ...
}

A well-crafted payload could manipulate memory structures so that, when the vulnerable function executes, it uses attacker-controlled data.

References & Further Reading

- CVE-2022-43286 at NVD
- njs GitHub commit patch
- Nginx njs releases
- Heap use after free explained (Google Project Zero)

Mitigation

Upgrading njs to .7.5 or newer is the only reliable fix.  
If you deploy njs scripts, do not accept untrusted user input into JSON.parse until you patch.

To check your njs version

njs -v
# or
nginx -V 2>&1 | grep njs

Conclusion

CVE-2022-43286 is a classic but high-risk memory bug. The lesson is clear: memory safety in even the tiniest function matters, especially in web-facing environments. Always keep your dependencies up-to-date, and audit use of advanced features like njs in production.

Still running njs <.7.5? It's time to update.

Let us know if you found this breakdown helpful, or if you want to see more deep-dives into real-world security bugs!

Timeline

Published on: 10/28/2022 21:15:00 UTC
Last modified on: 10/31/2022 17:48:00 UTC