Wing FTP Server NULL-Byte Lua Injection Unauthenticated RCE (CVE-2025-47812)
by 0xS4N4TG (this rewrite); original PoC by 4m3rr0r; vulnerability research by Julien (@MrTuxracer) · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-47812
- Category
- web
- Affected product
- Wing FTP Server, web administration/login interface (loginok.html, session mechanism)
- Affected versions
- <= 7.4.3 (fixed in 7.4.4)
- Disclosed
- 2026-07-06
- Patch status
- patched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | 0xS4N4TG (this rewrite); original PoC by 4m3rr0r; vulnerability research by Julien (@MrTuxracer) |
| CVE / Advisory | CVE-2025-47812 |
| Category | web |
| Severity | Critical |
| CVSS Score | 10.0 (per NVD) |
| Status | Weaponized |
| Tags | wingftp, ftp-server, null-byte-injection, lua-injection, unauthenticated-rce, session-file, cwe-94, cwe-158, python |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Wing FTP Server, web administration/login interface (loginok.html, session mechanism) |
| Versions Affected | <= 7.4.3 (fixed in 7.4.4) |
| Language / Platform | Python 3 (exploit); Lua session backend (target, executes as root/SYSTEM) |
| Authentication Required | No |
| Network Access Required | Yes |
Summary
Wing FTP Server’s authentication routine c_CheckUser() truncates the supplied username at the first NULL byte (%00) when validating credentials, but the code path that subsequently writes the session file persists the full, unsanitized username — including anything after the NULL byte — into a Lua session file on disk. By submitting a username such as anonymous%00]]<lua-code>--, an attacker causes the truncated value to pass authentication as anonymous while the raw string (which closes the Lua string literal, injects arbitrary Lua, then comments out the remainder) is written verbatim into the session file. When any authenticated page (e.g. dir.html) is subsequently loaded, the server reads the session file via loadfile() and executes it as Lua code, running the attacker’s injected os.execute()/io.popen() calls as root (Linux) or SYSTEM (Windows). The included PoC (exploit.py) automates the NULL-byte injection login, triggers execution via dir.html, and supports vulnerability checking, blocking command execution, detached/backgrounded command execution, and one-shot bash reverse shell delivery.
Vulnerability Details
Root Cause
Authentication validation and session-file writing disagree on how they interpret a NULL byte in the username: c_CheckUser() stops reading at %00 and thus authenticates the truncated, benign-looking prefix (e.g. anonymous), but the routine that persists the login state writes the entire raw username (including everything after the NULL byte) into a per-session Lua file. Because that content is later loadfile()’d and executed as Lua rather than treated as inert data, an attacker can smuggle a Lua string-closing sequence and injected code past the NULL byte:
| |
The injected Lua (e.g. local h=io.popen("(id) 2>&1") ... print(...)) is written into the session file and executed the moment the session is loaded by any subsequent authenticated request.
Attack Vector
- Attacker POSTs to
loginok.htmlwithusername=anonymous%00]]<CR><injected Lua code><CR>--and an empty/arbitrarypassword;c_CheckUser()authenticates the pre-NULL-byte prefix (anonymous) successfully and returns aUIDsession cookie. - The full raw username, including the injected Lua past the NULL byte, is written unsanitized into that session’s Lua session file on disk.
- Attacker requests any authenticated endpoint (the PoC uses
dir.html) while presenting the returnedUIDcookie; the server loads the session file withloadfile()and calls the resulting functionf(), executing the injected Lua. - Injected Lua uses
io.popen()(for output capture, wrapped with===START===/===END===markers for reliable extraction) oros.execute()withsetsid nohup ... &(for detached/backgrounded execution, e.g. reverse shells) to run arbitrary OS commands asroot/SYSTEM.
Impact
Unauthenticated remote code execution as root (Linux) or SYSTEM (Windows) on the Wing FTP Server host, since the session-execution mechanism runs attacker-controlled Lua with full server privileges.
Environment / Lab Setup
Target: Wing FTP Server <= 7.4.3, web UI reachable at http://<target>:5466 (HTTP) or :5467 (HTTPS)
Attacker: Python 3, `pip install requests`
Proof of Concept
PoC Script
See
exploit.pyin this folder.
| |
Detection & Indicators of Compromise
Signs of compromise:
- Login POST requests with usernames containing NULL bytes (
%00) followed by Lua syntax such as]] - Wing FTP server process spawning shell interpreters (
sh,bash,cmd.exe) ornc/reverse-shell activity - Unexpected outbound connections from the FTP server host shortly after a
dir.htmlrequest
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade Wing FTP Server to version 7.4.4 or later, which fixes the NULL-byte truncation mismatch between authentication and session-file writing |
| Interim mitigation | Restrict network access to the Wing FTP web administration interface to trusted management networks, and monitor authentication requests for NULL bytes or Lua-syntax characters in credential fields |
References
Notes
Mirrored from https://github.com/0xS4N4TG/CVE-2025-47812 on 2026-07-06. exploit.py implements the documented Wing FTP NULL-byte Lua-injection RCE with check and shell-delivery modes; this repo is an acknowledged rewrite of an earlier public PoC (4m3rr0r/CVE-2025-47812-poc), based on vulnerability research originally published by Julien (@MrTuxracer).
| |