# CVE-2020-8231: Connect-only connections can use the wrong connection

curl connect-only easy handle kept a dangling connection pointer after timeout; a new connection reusing the same address caused data to be sent to the wrong server.

- Payout: hidden
- Severity: low
- Program: curl
- Found by: m42a
- Disclosed: 2020-11-05
- CVE: CVE-2020-8231
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/948876
- Library page: https://bugbountylibrary.com/r/h1%3A948876
- Tags: area:oss domain:oss impact:data-leak kind:bounty platform:hackerone sev:low tech:curl technique:regression technique:source-review vuln:info-disclosure

**Target:** libcurl multi interface, connect-only easy handles
**Root cause:** When a connect-only easy handle's connection times out and is closed, the handle retains a stale pointer to the freed connection struct. A newly allocated connection can land at the same address, so the handle silently uses the wrong connection.
**Steps:**
1. Compile the provided C++ PoC using curl_global_init_mem with a caching allocator to force deterministic address reuse.
2. Listen on ports 1234, 1235, 1236.
3. Create connect-only easy handle to :1234 with CURLOPT_MAXAGE_CONN=1, complete via curl_multi_socket_action.
4. Sleep 2s so the :1234 connection ages out.
5. Create connect-only handle to :1235, driving multi loop; the :1234 connection is closed as too old.
6. Create connect-only handle to :1236; its connection struct reuses the freed :1234 memory.
7. Call `curl_easy_send(easy1234, &c, 1, &n)`; byte is delivered to :1236 instead of :1234.
**How found:** Researcher reasoned that a connect-only handle not read/written could time out and be freed while the handle still referenced it; used git bisect to find commit 755083d introduced it, and wrote a caching allocator to deterministically force address reuse and prove the misrouting.
**Exploitation:** Requires an application using connect-only handles in a multi handle where a connection times out and a new connection is allocated at the same address; sensitive data intended for the original server is then written to the new server's socket.
**Insight:** When auditing connection-pool/lifecycle code, check whether handles hold raw pointers to connection objects that can be freed by timeout/age-out while the handle remains live; a custom allocator that recycles freed blocks by size is a reliable way to turn a use-after-free into a deterministic repro.

