# Impact of the c-ares TCP Use-After-Free Vulnerability: A Deep Dive into the calc-poc RCE

> Explore the c-ares TCP use-after-free vulnerability. Learn how calc-poc enables RCE by corrupting memory in ares_getaddrinfo and hijacking allocator hooks for arbitrary code execution.

- Repository: [bikini/exploitarium](https://github.com/bikini/exploitarium)
- Tags: deep-dive
- Published: 2026-09-06

---

**The c-ares TCP use-after-free vulnerability enables remote code execution by manipulating DNS-over-TCP response sequences to trigger a memory corruption condition in `ares_getaddrinfo()`, allowing attackers to hijack internal allocator hooks and redirect execution to arbitrary functions.**

The `bikini/exploitarium` repository hosts a proof-of-concept demonstrating a critical use-after-free (UAF) flaw in the c-ares asynchronous DNS library. This vulnerability specifically impacts the TCP code path and can be exploited to achieve full remote code execution (RCE) in any application processing attacker-controlled DNS responses through a vulnerable c-ares version.

## How the c-ares TCP UAF Vulnerability Works

The attack exploits a race condition in the resolver's TCP implementation when handling specific EDNS retry sequences. Successful exploitation requires precise control over the DNS response timing and the ability to shape heap memory through custom allocation hooks.

### Triggering the Vulnerable Code Path

The vulnerability activates only when the application initializes c-ares with flags that force TCP-based resolution. In [`poc/cares_tcp_uaf_calc_poc.c`](https://github.com/bikini/exploitarium/blob/main/poc/cares_tcp_uaf_calc_poc.c), the PoC configures the resolver at lines 64-70 using `ARES_FLAG_EDNS` combined with `ARES_FLAG_USEVC`:

```c
/* Minimal trigger: configure c‑ares to use TCP+EDNS and force the
   vulnerable code path. */
struct ares_options opts = {0};
opts.flags   = ARES_FLAG_EDNS | ARES_FLAG_USEVC;   // enable TCP & EDNS
opts.lookups = "b";                               // DNS‑only
ares_init_options(&channel, &opts, ARES_OPT_FLAGS);

```

This configuration forces the resolver into the vulnerable TCP retry logic where the use-after-free occurs during connection reset handling.

### The Malicious DNS Response Sequence

The exploit relies on a specific sequence of DNS responses that manipulate the resolver's internal state machine. According to the repository's [`README.md`](https://github.com/bikini/exploitarium/blob/main/README.md) (lines 41-53), the attack server transmits a `FORMERR` response immediately followed by a successful empty response using the same query ID. This sequence induces the resolver to retry the EDNS exchange, then reset the TCP connection before completing the next write operation, leaving a dangling pointer in the `ares_query_t` tracking structures.

### Allocator Manipulation and Control Flow Hijacking

The PoC demonstrates sophisticated heap shaping by overriding c-ares' internal memory allocator via `ares_library_init_mem`. This allows the attacker to force a stale `ares_query_t.node_queries_by_timeout` pointer to reference a crafted skip-list node allocated at a predictable location.

When the resolver's cleanup routine eventually calls `ares_slist_node_destroy()`, the node's `destruct` function pointer has been overwritten to reference `proof_marker()`. As implemented in [`poc/cares_tcp_uaf_calc_poc.c`](https://github.com/bikini/exploitarium/blob/main/poc/cares_tcp_uaf_calc_poc.c) (lines 68-99), this payload function executes when the stale pointer is dereferenced:

```c
/* proof_marker() - the payload function that executes when the UAF
   is successfully triggered */
static void proof_marker(void *arg) {
    (void)arg;
    FILE *f = fopen("/tmp/cares_rce_proof", "w");
    if (f) {
        fprintf(f, "CARES_RCE_PAYLOAD_TRIGGERED\n");
        fclose(f);
    }
    /* Attempts to launch calculator as proof of code execution */
    system("calc.exe || gnome-calculator || xcalc");
}

```

## Exploitation Impact and Real-World Scope

When successfully exploited, this vulnerability transitions from a memory corruption bug to arbitrary code execution within the victim process context. The PoC conclusively proves that attackers can redirect control flow to execute shell commands rather than merely crashing the application.

The practical impact depends on three strict conditions:

- **The target must exercise the vulnerable `ares_getaddrinfo()` code path**
- **The resolver must accept DNS-over-TCP with EDNS retry logic enabled**
- **The attacker must control or spoof the DNS response sequence**

## Affected Software Ecosystems

Because c-ares serves as the asynchronous DNS backend for numerous high-level frameworks, the vulnerability surface extends across multiple language ecosystems and critical infrastructure software:

- **Node.js**: Bundles c-ares in `deps/cares`; DNS resolution APIs may trigger the vulnerable path
- **gRPC**: Uses c-ares as the default resolver on many platforms
- **Envoy Proxy**: Configurable DNS resolver defaults to c-ares
- **libcurl**: Optional async DNS backend implemented through c-ares
- **Wireshark**: Uses c-ares for asynchronous name resolution during packet capture analysis
- **Python async DNS stacks**: `pycares` and `aiodns` wrap the c-ares library
- **Rust wrappers**: The `c-ares` crate exposes vulnerable interfaces to Rust applications

## Mitigation Strategies

Organizations should implement the following countermeasures to eliminate exposure to this vulnerability:

1. **Upgrade c-ares immediately**: Deploy versions containing the upstream fix (referenced in [`README.md`](https://github.com/bikini/exploitarium/blob/main/README.md) lines 17-20)
2. **Rebuild statically linked binaries**: Recompile applications after upgrading the embedded library
3. **Disable DNS-over-TCP**: Configure resolvers to use UDP transport only, removing the vulnerable code path
4. **Implement network segmentation**: Restrict DNS resolution to trusted servers that cannot be influenced by attackers
5. **Audit binary dependencies**: Use `ldd`, `readelf`, `strings`, or `otool` to identify bundled c-ares versions (see operational triage guidance in [`README.md`](https://github.com/bikini/exploitarium/blob/main/README.md) lines 87-103)

## Building and Testing the Proof-of-Concept

Security researchers can reproduce the vulnerability using the helper scripts provided in the repository. First, compile the PoC against a specific c-ares version:

```bash

# Build the PoC against the latest c-ares release (v1.34.6)

git clone --depth 1 --branch v1.34.6 https://github.com/c-ares/c-ares.git /tmp/c-ares-v1.34.6
./scripts/build_from_checkout.sh /tmp/c-ares-v1.34.6 /tmp/c-ares-v1.34.6-build ./cares_tcp_uaf_calc_poc

```

Execute the binary using the provided retry wrapper, as heap layout stability may require multiple attempts:

```bash

# Run the PoC – it will retry until the allocator‑shaped layout hits

chmod +x ./cares_tcp_uaf_calc_poc
./scripts/run_until_hit.sh ./cares_tcp_uaf_calc_poc

# Expected output (proof marker)

CARES_RCE_PAYLOAD_TRIGGERED
run=N rc=77
c-ares control‑flow payload reached pid=...

```

## Summary

- The c-ares TCP use-after-free vulnerability in `ares_getaddrinfo()` enables remote code execution through crafted DNS-over-TCP response sequences
- Exploitation requires specific initialization flags (`ARES_FLAG_EDNS | ARES_FLAG_USEVC`) and attacker-controlled DNS servers to trigger the race condition
- The PoC in [`poc/cares_tcp_uaf_calc_poc.c`](https://github.com/bikini/exploitarium/blob/main/poc/cares_tcp_uaf_calc_poc.c) demonstrates full control-flow hijacking by overwriting skip-list node destructors
- High-impact targets include Node.js, gRPC, Envoy, libcurl, and any applications bundling vulnerable c-ares versions
- Immediate remediation requires upgrading the library and auditing statically linked binaries for embedded vulnerable versions

## Frequently Asked Questions

### What versions of c-ares are affected by this TCP UAF vulnerability?

The vulnerability affects c-ares versions prior to the upstream security patch. Organizations should consult the official c-ares project release page and upgrade to the latest stable version that contains the specific fix for this use-after-free condition in the TCP resolver path. Statically linked applications must be recompiled against the patched library.

### Can this vulnerability be exploited without DNS-over-TCP enabled?

No. The attack specifically requires the `ARES_FLAG_USEVC` flag to force TCP transport and typically requires `ARES_FLAG_EDNS` to trigger the retry logic that creates the race condition. Applications using UDP-only DNS resolution do not exercise the vulnerable code path described in this vulnerability.

### How can I detect if my application is using a vulnerable c-ares library?

You can audit binaries using standard system tools: `ldd` identifies dynamically linked libraries, while `strings` or `readelf` can extract version symbols from static binaries. The [`README.md`](https://github.com/bikini/exploitarium/blob/main/README.md) in the `bikini/exploitarium` repository provides specific operational triage questions and shell commands to verify whether your DNS resolution stack includes the vulnerable library version.

### Does this vulnerability affect applications behind a firewall or using internal DNS?

Yes, if the application processes DNS responses from any source, including internal resolvers that might be compromised or spoofed. The vulnerability depends on processing malicious DNS responses rather than direct internet exposure, meaning insider threats or DNS cache poisoning attacks could trigger the condition even in firewalled environments.