Full Report
The author of this post found a really straight forward buffer overflow in the authentication API of an IP camera that could overwrite the return address on the stack. The application had NX enabled and ASLR but had no canaries, no PIE and partial RELRO. Given that they couldn't find a libc leak for a simple RET2Win attack, they needed to do this without an information disclosure. They did have the ability to call arbitrary code in the binary via ROP chains though! The technique they end up using is interesting: use the Global Offset Table (GOT) and Procedure Linkage Table (PLT) to bypass ASLR. The idea is to use the code in the PLT to jump to incorrect functions using relative offsets. At a high level, this can work by reading a GOT entry into a register, increment/decrement the register until it's at the proper value and then jump to the register. An additional path is incrementing the GOT pointer itself. After some effort, they found the function isalnum from libc that could take in user controlled input and was already loaded in the GOT. The difference between this function and system() is only 0x13230. So, the goal was to add this much to the address in the GOT entry to trigger code execution. While hunting for quick/easy gadgets, they didn't find any. All of them had side effects that made it infeasible. After searching for gadgets for a while, they found a string of gadgets that could perform what they needed to do. Notably, the gadgets sometimes needed to call other gadgets, which made this even harder to do. The list of gadgets was as follows: Dereference isalnum@got and store the results in r6. The gadget wasn't perfect but did the job before jumping into the value in r3 for the next gadget. Use the next gadget to add the offset to system back into the GOT entry stored in r6. This jumps to the value stored in r3 for the next gadget in the chain. The final gadget writes r6 back to the GOT entry that we originally read. This is because they couldn't find a way to jump to r6. Prepare function arguments for system(). Then, trigger the overwritten GOT entry for code execution. At the end of the post, they point out that this was a 32-bit binary and the offsets could have just been brute forced. In fact, their original exploit did exactly this. The creation of the exact chain required some difficult maneuvering of values in order to not have bad side effects. Overall, a great post on the end to end of exploiting the device!
Analysis Summary
# Vulnerability: Unauthenticated Remote Code Execution in INSTAR IP Cameras
## CVE Details
- **CVE ID**: CVE-2025-24326 (Referencing modzero advisory MZ-25-03)
- **CVSS Score**: 9.8 (Critical)
- **CWE**: CWE-121 (Stack-based Buffer Overflow), CWE-287 (Improper Authentication)
## Affected Systems
- **Products**: INSTAR IP Cameras (2K+ and 4K Series)
- **Versions**: All firmware versions prior to the August 2025 security update.
- **Configurations**: Devices exposed to the network/internet via the web management interface.
## Vulnerability Description
A stack-based buffer overflow exists in the authentication API of the camera's web server. The application fails to properly validate the length of user-supplied input during the authentication process, allowing an attacker to overwrite the return address on the stack.
The binary implements several security protections, including **NX (No-Execute)** and **ASLR (Address Space Layout Randomization)**. However, it lacks **Stack Canaries**, **PIE (Position Independent Executable)**, and only utilizes **Partial RELRO (Relocation Read-Only)**. These omissions allow for the redirection of execution flow using Return-Oriented Programming (ROP) without needing a memory leak to defeat ASLR.
## Exploitation
- **Status**: PoC demonstrated by researchers; exploitability confirmed.
- **Complexity**: High (Requires sophisticated ROP chain construction to bypass ASLR without an information leak).
- **Attack Vector**: Network (Unauthenticated)
### Exploitation Technique: "GOT/PLT Relative Offsets"
Since the binary is not PIE, the Procedure Linkage Table (PLT) remains at a fixed address. The researchers bypassed ASLR by:
1. Dereferencing a Global Offset Table (GOT) entry for an existing libc function (e.g., `isalnum`).
2. Using ROP gadgets to mathematically adjust the value in a register by a constant offset (0x13230) to point to the `system()` function.
3. Writing the calculated `system()` address back into the GOT.
4. Triggering the modified GOT entry to execute arbitrary commands.
## Impact
- **Confidentiality**: Critical (Full access to camera feeds and stored data)
- **Integrity**: Critical (Ability to modify firmware, settings, or system files)
- **Availability**: Critical (Ability to brick or disable the device)
## Remediation
### Patches
- INSTAR released a firmware update in **August 2025** to address this vulnerability. Users should update to the latest available firmware for the 2K+ and 4K series immediately.
### Workarounds
- Disable exposure of the camera's web interface to the public internet.
- Use a VPN for remote access to the camera network.
- Tighten firewall rules to restrict access to the authentication API to trusted IP addresses.
## Detection
- **Indicators of Compromise**: Unexpected reboots of the camera (indicative of exploitation crashes) or unauthorized changes to system configurations.
- **Detection Methods**: Monitor network traffic for unusually long strings in authentication requests. Check system logs for "Segmentation Fault" errors if UART access is available.
## References
- INSTAR Advisory: [https://modzero.com/static/MZ-25-03_modzero_INSTAR.pdf](https://modzero.com/static/MZ-25-03_modzero_INSTAR.pdf)
- Modzero Blog: [https://modzero.com/en/blog/no-leak-no-problem/](https://modzero.com/en/blog/no-leak-no-problem/)
- Technical Background on ROP: [https://ir0nstone.gitbook.io/notes/binexp/stack/aslr/plt_and_got](https://ir0nstone.gitbook.io/notes/binexp/stack/aslr/plt_and_got)