Full Report
RenderDoc is a graphics debugger that allows for quick and easy introspection of graphics applications. It supports many different types such as Vulkan, D3D11, OpenGL and more. This is a write up on 3 vulnerabilities and the full exploits on them within RenderDoc. librenderdoc.so is LD_PRELOADed into the application using a library load function. This works by creating a directory with /tmp/Renderdoc/ and calling open on a log file in this location with append mode. However, there is no validation on who owns the file, in the case that a malicious user wins this race. The data is partially controllable by writing data to the TCP debugger server. Sadly, it has a major string header at the top that makes traditional configuration files not viable for escalation. How did they get around this? There's a call to fgets() within the systemd processing that only get 512 bytes at a time. By sending a very long string, we can use only our data on a given line. An additional way to escalate privileges is to write to , using the truncation mentioned above they write to .config/user-dirs.defaults with SYSTEMD=.config/systemd to create a systemd directory in a user controlled location. By writing to a configuration file in this directory, code execution is trivial to achieve. To bypass the head issue again, the authors abuse a different in deliminators (\r) to add their own lines. The second vulnerability is a heap based buffer overflow that occurs from unexpected sizes in processing the client name. This overflow does not seem very useful to start with but these people are wizards! When a thread of renderdoc starts up, glibc malloc allocates a new heap for the thread within an mmaped section of memory. This is always 64MB, aligned in 64MB groups and is mprotected for more security. This section is close to the libraries but there is a gap in memory. The authors decided to use a technique that I've documented here. In glibc malloc, the mmap chunks have a special bit. By calling free() on an mmap chunk, the chunk isn't put into a free list; it's literally unmapped with munmap(). Arbitrarily mapping and unmapping memory is an incredibly powerful primitive. The munmap and mmap calls are the attack method but there is very crazy strategy to it. They have a text picture explaining the setup. By using the vulnerability from before in the 64KB buffer, they are able to corrupt another mmap chunk directly ahead of it. Once the chunk ahead of it is updated to be extremely large. This is because we want the munmap() call to succeed. The goal is to punch a hole of exactly 8MB+4KB, which is the size of a threat stack and its guard page. With the gap ready to go, we can allocate our data into that location that we want. This is done by simply connecting to the server, which creates a new thread in this gap, then disconnecting for this to be reused. After this, a large allocation of the client name (without triggering the vulnerability) will overlap with this section. I don't fully understand why this is the case but I'm assuming it's weirdness with munmapping memory. With a long lived connection with our client name data being readable and overlapping with the stale client stack, we create a great primitive for reading and writing data. First, they force a new stack into this area. By doing this, a bunch of libc, stack addresses and much else can be leaked. After this, they use it to write to the RIP on the thread stack to hijack control flow with a large amount of ROP gadgets. It's weird that this works because of stack canaries though. The final vulnerability is a fairly straight forward integer overflow that leads to a large amount of data being written to a small buffer. Overall, an amazing and innovative post. The shout out to me was appreciated and made my day!
Analysis Summary
As a vulnerability research specialist, here is the summary of the identified security flaws in RenderDoc.
---
# Vulnerability: Multiple Vulnerabilities in RenderDoc (LPE & RCE)
## CVE Details
- **CVE ID:** CVE-2023-33865 (Symlink/LPE), CVE-2023-33864 (RCE), CVE-2023-33863 (RCE)
- **CVSS Score:** Not explicitly provided in the text, but implications suggest High to Critical severity.
- CVE-2023-33865: Local Privilege Escalation (LPE) implies high severity.
- CVE-2023-33864/33863: Remote Code Execution (RCE) implies critical severity.
- **CWE:** Symlink vulnerability (CWE-59), Heap-based Buffer Overflow (CWE-122), Integer Overflow/Underflow (CWE-190/191).
## Affected Systems
- **Products:** RenderDoc (graphics debugger)
- **Versions:** Versions prior to the fix deployed on May 19, 2023.
- **Configurations:** Affects Linux environments where `librenderdoc.so` is **LD\_PRELOAD**ed, exposing the TCP debugger server (default port 38920) to remote or local attackers.
## Vulnerability Description
Three distinct vulnerabilities were found in the RenderDoc TCP server implementation running when debugging applications via `LD_PRELOAD`:
1. **CVE-2023-33865 (Symlink/LPE):** Occurs during log file creation in `/tmp/RenderDoc/`. The lack of ownership validation on the log file allows a local, unprivileged attacker to win a race condition, potentially linking the log file to a sensitive system path. This vulnerability was chained with flaws in systemd configuration processing (`fgets()` line limitation and abuse of `\r` delimiters) to write to user configuration files (e.g., `.config/user-dirs.defaults`), enabling subsequent code execution via configuration changes (e.g., setting `SYSTEMD=...`).
2. **CVE-2023-33864 (Integer Underflow to RCE):** A heap-based buffer overflow stemming from processing the client name. An **integer underflow** leads to an unexpectedly large size being used during heap allocation for a client buffer. This was exploited by maliciously sizing the client name input. The exploit leveraged complex glibc `malloc` behavior involving `mmap` chunks, using `munmap()` to punch a hole (exactly 8MB+4KB) in memory, allowing controlled allocation (thread stack placement) in that gap. This leaked libc/stack addresses and enabled RIP hijacking via ROP gadgets on the displaced thread stack.
3. **CVE-2023-33863 (Integer Overflow to RCE):** A straightforward **integer overflow** (where a requested size exceeds `UINT32_MAX` leading to a small value being used) resulting in a large write to a small buffer, potentially leading to RCE. The researchers did not attempt to fully exploit this one.
## Exploitation
- **Status:**
- **CVE-2023-33865 (PoC available):** Successful exploitation demonstrated for LPE via configuration file manipulation.
- **CVE-2023-33864 (PoC available):** Successful exploitation demonstrated for RCE using advanced heap grooming (`munmap`/`mmap` manipulation) despite modern mitigations (ASLR, PIE, Canaries).
- **CVE-2023-33863 (PoC available):** Proof of concept code sent to demonstrate the buffer overflow condition (but not full RCE chain).
- **Complexity:** High (Especially for CVE-2023-33864 due to advanced heap spraying/grooming techniques required).
- **Attack Vector:**
- CVE-2023-33865: Local/Adjacent (depends on race condition setup).
- CVE-2023-33864/33863: Network (Remote attacker connecting to TCP port 38920).
## Impact
- **Confidentiality:** High (RCE allows data exfiltration and configuration leakage).
- **Integrity:** Critical (Full remote code execution or privilege escalation).
- **Availability:** High (Crash/Denial of Service possible via exploitation attempt or memory corruption).
## Remediation
### Patches
- All three vulnerabilities were fixed on **May 19, 2023**. Specific commits are referenced in the advisory, addressing buffer checks, size validation, and file handling.
### Workarounds
- Block or restrict external network access to the RenderDoc debug server port (default TCP 38920).
- Do not run applications under `LD_PRELOAD` with RenderDoc if the environment is hostile.
## Detection
- **Indicators of Compromise (IoC):**
- Unusual file creation/modification in the `/tmp/RenderDoc/` directory just before sensitive system files are modified (for LPE).
- Abnormal network connections to port **38920** using unusual, non-standard RenderDoc protocol traffic, particularly large inputs intended to trigger buffer overflows.
- Application crashes due to `SIGABRT` related to `malloc` assertions or corrupted top size (as seen in PoC traces).
- **Detection Methods and Tools:** Network monitoring for unauthorized traffic on port 38920. Integrity monitoring on critical system configuration files (for LPE chain). Runtime analysis tools detecting unusual memory allocation/deallocation patterns (especially calls to `munmap` on mmap chunks).
## References
- Vendor advisories confirmed by the fix committed on May 19, 2023.
- Relevant links: `https://seclists.org/fulldisclosure/2023/Jun/` (Context URL)