Talos Vulnerability Report

TALOS-2025-2309

Tp-Link Archer AX53 v1.0 Openvpn configuration restore route_up OS command injection vulnerability

May 7, 2026
CVE Number

None

SUMMARY

An os command injection vulnerability exists in the Openvpn configuration restore route_up functionality of Tp-Link Archer AX53 v1.0 1.3.1 Build 20241120 rel.54901(5553). A specially crafted configuration value can lead to arbitrary command execution. An attacker can upload a malicious file to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Tp-Link Archer AX53 v1.0 1.3.1 Build 20241120 rel.54901(5553)

PRODUCT URLS

Archer AX53 v1.0 - https://www.tp-link.com/my/support/download/archer-ax53/

CVSSv3 SCORE

9.1 - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-77 - Improper Neutralization of Special Elements used in a Command (‘Command Injection’)

DETAILS

The TP-Link Archer AX53 AX3000 Dual Band Gigabit Wi-Fi 6 Router is currently among the most popular routers sold online, and boasts impressive gigabit speeds for the price. This router also features remote cloud access via the TP-Link HomeShield application and smart home functionality.

A long existing feature of TP-Link routers and most routers in general is the ability to backup the router configuration into a file which can then be reuploaded to the device to restore the router to a particular operational state. On the TP-Link AX3000, this functionality is accessed via the Web GUI by navigating to the ‘Advanced > System’ menu. Upon hitting the ‘Back Up’ button, the browser will download a file called ArcherAX53v120241120131n.bin. As described in a previously disclosed vulnerability on an older model of TP-Link routers https://github.com/aaronsvk/CVE-2022-30075 , this binary blob must first be decrypted with a static AES key and IV, then unpacked as a GZIP archive. After this, one must unpack the resulting tar file to get two resulting files: ori-backup-user-config.bin and ori-backup-certificate.bin with actual contents. We then unpack these two files in the same exact manner, first decrypting with the same AES key and IV and unpacking decrypted binary as a gzip file. For ori-backup-user-config.bin we end up with a config.xml file that is human readable. This configuration xml can be editied and then repacked with a reverse of the process to manually change the configuration of the device.

Among the different configuration options, there exist some that are parsed by /etc/init.d/ startup scripts, and for the purposes of this writeup we only care to look at /etc/init.d/openvpn:

start_instance() { local s=”$1”

section_enabled "$s" || return 1

[ ! -d "/var/run" ] && mkdir -p "/var/run"
[ ! -d "/var/etc" ] && mkdir -p "/var/etc"
[ -f "/var/etc/openvpn-$s.conf" ] && rm "/var/etc/openvpn-$s.conf"

// [...]

# append flags
append_bools "$s" \
    auth_nocache auth_retry auth_user_pass_optional bind ccd_exclusive client client_cert_not_required \
    client_to_client comp_noadapt disable \
    disable_occ down_pre duplicate_cn fast_io float http_proxy_retry \
    ifconfig_noexec ifconfig_nowarn ifconfig_pool_linear management_forget_disconnect management_hold \
    management_query_passwords management_signal mktun mlock mtu_test multihome mute_replay_warnings \
    nobind no_iv no_name_remapping no_replay opt_verify passtos persist_key persist_local_ip \
    persist_remote_ip persist_tun ping_timer_rem pull push_reset \
    remote_random rmtun route_noexec route_nopull single_session socks_proxy_retry \
    suppress_timestamps tcp_nodelay test_crypto tls_client tls_exit tls_server \
    tun_ipv6 up_delay up_restart username_as_common_name

# append params
append_params "$s" \
    cd askpass auth auth_user_pass auth_user_pass_verify bcast_buffers ca cert \
    chroot cipher client_config_dir client_connect client_disconnect comp_lzo connect_freq \
    connect_retry connect_timeout connect_retry_max crl_verify dev dev_node dev_type dh \
    echo engine explicit_exit_notify fragment group hand_window hash_size \
    http_proxy http_proxy_option http_proxy_timeout ifconfig ifconfig_pool \
    ifconfig_pool_persist ifconfig_push inactive ipchange iroute keepalive \
    key key_method keysize learn_address link_mtu lladdr local log log_append \
    lport management management_log_cache max_clients \
    max_routes_per_client mode mssfix mtu_disc mute nice ns_cert_type ping \
    ping_exit ping_restart pkcs12 plugin port port_share prng proto rcvbuf \
    redirect_gateway remap_usr1 remote remote_cert_eku remote_cert_ku remote_cert_tls \
    reneg_bytes reneg_pkts reneg_sec \
    replay_persist replay_window resolv_retry route route_delay route_gateway \
    route_metric route_up rport script_security secret server server_bridge setenv shaper sndbuf \
    socks_proxy status status_version syslog tcp_queue_limit tls_auth \
    tls_cipher tls_remote tls_timeout tls_verify tmp_dir topology tran_window \
    tun_mtu tun_mtu_extra txqueuelen user verb down push up

// [...]
service_start /usr/sbin/openvpn --syslog "openvpn($s)" --writepid "$SERVICE_PID_FILE" --config "/var/etc/openvpn-$s.conf"

This init script parses our uploaded configuration, searching for all of the openvpn configuration options in the above lists. As such, we can cause the openvpn server to run with almost any configuration. For those with knowledge of openvpn server configurations, this is in fact very dangerous as there are a few openvpn options listed above that directly allow commands to be run at certain times in the server’s lifetime. Take for example, the route_up option - if we include in our restored configuration the following xml line:

<route_up>"/usr/sbin/dropbear -g -w -C -B -L -p 22"</route_up>

This command will be put into the configuration of the openvpn server and run immediately after a vpn connection is established. As such, an attacker can upload this configuration and subequently connect via openvpn to start up a dropbear server that allows for remote logins using the same credentials that are used for the web GUI, resulting in a remote shell and granting of access not allowed via the web GUI. It’s also finally worth noting that because we can pass arguments to this configuration line, we do not actually need to set the <script_security> config, as we can gain shell access via a built-in binary on the device, and not a custom script.

VENDOR RESPONSE

Vendor advisory: https://www.tp-link.com/us/support/faq/5055/

TIMELINE

2026-01-12 - Vendor Disclosure
2026-04-08 - Vendor Patch Release
2026-05-07 - Public Release

Credit

Discovered by Lilith >_> of Cisco Talos.