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

ftp-bounce-attack.md (7869B)


      1 ---
      2 title: "FTP Bounce attack - Scan"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-ftp/ftp-bounce-attack.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-ftp/ftp-bounce-attack.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # FTP Bounce attack - Scan
     14 
     15 ## FTP Bounce - Scanning
     16 
     17 ### Manual
     18 
     19 1. Connect to the vulnerable FTP server.
     20 2. Use **`PORT`** (classic IPv4 active mode) or **`EPRT`** (extended syntax, supports IPv4/IPv6) to make it establish a connection with the _\<IP:Port>_ you want to scan:<sup>[[2]](#references)</sup>
     21 
     22    ```text
     23    PORT 172,32,80,80,31,144      # 31*256 + 144 = 8080
     24    EPRT |1|172.32.80.80|8080|    # IPv4
     25    EPRT |2|2001:db8::80|8080|    # IPv6
     26    ```
     27 
     28 3. Trigger the data connection with **`LIST`**, **`NLST`** or **`RETR /file/in/ftp`** and read the **whole reply sequence**, not only the first line:
     29    - **`125`** means a data connection is already open; **`150`** is only preliminary (the server is about to open it). Treat either as a candidate result.
     30    - A terminal **`226`** is the strongest open-port indication because the transfer/data connection completed.
     31    - **`425`** means the data connection could not be opened (closed, filtered, unroutable or blocked by egress policy). A **`426`** after `125`/`150` is inconclusive: a listening application may accept the TCP connection and then abort when it receives FTP listing data.
     32    - **`450`** / **`550`** can instead indicate a filesystem or authorization failure. Retry with a known-readable file and compare a known-open and known-closed destination from the relay's network position.<sup>[[6]](#references)</sup>
     33 
     34 Example using **`PORT`** (port 8080 of 172.32.80.80 is open and port 7777 is closed):
     35 
     36 ![FTP Bounce - Scanning - Manual: Example using PORT (port 8080 of 172.32.80.80 is open and port 7777 is closed)](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28241%29.png)
     37 
     38 Same example using **`EPRT`** (authentication omitted in the image):
     39 
     40 ![FTP Bounce - Scanning - Manual: Same example using EPRT (authentication omitted in the image)](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28539%29.png)
     41 
     42 Open port using **`EPRT`** instead of **`LIST`** (different env):
     43 
     44 ![FTP Bounce - Scanning - Manual: Open port using EPRT instead of LIST (different env)](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28875%29.png)
     45 
     46 > For **`EPRT`**, use **`|1|`** with IPv4 addresses and **`|2|`** with IPv6 addresses.
     47 
     48 ### Practical notes
     49 
     50 - **`PORT`** encodes the destination port as two bytes: **`p1 = port // 256`** and **`p2 = port % 256`**.
     51 - A `2xx` response to `PORT`/`EPRT` proves only that the server accepted the endpoint syntax. The outbound TCP connection normally happens after the transfer command, so always follow it with `LIST`/`NLST`/`RETR`.
     52 - Many daemons only block **privileged ports** **`<1024`**. Even when low ports are protected, high-value internal services such as **`3306`**, **`5000`**, **`6379`**, **`8080`**, **`8443`** or **`9000`** may still be reachable.<sup>[[7]](#references)</sup>
     53 - You are testing **reachability from the FTP server**, not from your own host. DNS resolution, routing, egress ACLs and timeouts can differ from your position; use numeric target addresses and repeat ambiguous probes against control ports.
     54 
     55 ### **nmap**
     56 
     57 ```bash
     58 nmap -Pn -n -b <name>:<pass>@<ftp_server> <victim_ip>
     59 nmap -Pn -n -v -p 21,80 -b ftp:ftp@10.2.1.5 127.0.0.1 # Scan ports 21,80 of the FTP server itself
     60 nmap -Pn -n -v -p 21,22,445,80,443 -b ftp:ftp@10.2.1.5 192.168.0.1/24 # Scan the internal network reachable from the FTP server
     61 ```
     62 
     63 ### nmap NSE pre-check
     64 
     65 ```bash
     66 nmap -p21 --script ftp-bounce <ftp_server>
     67 nmap -p21 --script ftp-bounce \
     68   --script-args 'ftp-bounce.username=<user>,ftp-bounce.password=<pass>,ftp-bounce.checkhost=<target>' \
     69   <ftp_server>
     70 ```
     71 
     72 This NSE script is only a **configuration pre-check**: it sends IPv4 `PORT` commands for a high port (`20560`) and TCP/80 at `checkhost`, but it does **not** issue `LIST` or otherwise trigger the data connection. Therefore, `bounce working!` means the arguments were accepted, not that the relay reached `checkhost`. By default it authenticates as **anonymous / `IEUser@`**, resolves **`scanme.nmap.org`** from the Nmap host, and uses that IPv4 address; override `checkhost` with an authorized address and follow with a real bounce scan.<sup>[[1]](#references)</sup>
     73 
     74 ### Metasploit
     75 
     76 ```bash
     77 msfconsole
     78 use auxiliary/scanner/portscan/ftpbounce
     79 set BOUNCEHOST <ftp_server>
     80 set RHOSTS <victim>
     81 set PORTS 22,80,443,445,8080,8443
     82 set FTPUSER <user>
     83 set FTPPASS <pass>
     84 run
     85 ```
     86 
     87 The Metasploit module is handy for quick IPv4 sweeps, but it currently does **not** support IPv6, so keep the manual **`EPRT`** workflow for IPv6-capable daemons.
     88 
     89 ### Common vulnerable patterns
     90 
     91 You are more likely to still find FTP bounce in:
     92 
     93 - **Legacy/embedded appliances** such as printers, MFPs, NAS boxes and older internal file workflow services.
     94 - Servers intentionally configured to allow **FXP / site-to-site transfers**.
     95 - Custom Python FTP services or lab daemons that re-enable foreign-address data connections for convenience.
     96 
     97 If you have shell/config access, the following settings are especially suspicious and worth validating immediately:
     98 
     99 - **ProFTPD:** **`AllowForeignAddress on`**, or an overly broad class supplied to `AllowForeignAddress`.<sup>[[3]](#references)</sup>
    100 - **vsftpd:** **`port_promiscuous=YES`** (and often **`pasv_promiscuous=YES`** when FXP was enabled).<sup>[[4]](#references)</sup>
    101 - **pyftpdlib:** **`permit_foreign_addresses = True`** or **`--permit-foreign-addresses`**. **`permit_privileged_ports = True`** additionally permits active connections to ports below 1024.<sup>[[5]](#references)</sup>
    102 
    103 ### Mitigation and detection
    104 
    105 The primary fix is to require the `PORT`/`EPRT` address to match the control connection's peer. If active mode is unnecessary, disable it and offer passive mode only. Rejecting destinations below TCP/1024 is useful defense-in-depth but leaves every higher port bounceable, so it is not a complete fix.<sup>[[7]](#references)</sup>
    106 
    107 Keep **`AllowForeignAddress`**, **`port_promiscuous`**, **`permit_foreign_addresses`** and **`permit_privileged_ports`** disabled unless tightly scoped FXP is required. Also restrict the FTP service account/container's outbound network access and alert on address-mismatch/bounce log entries or bursts of `PORT`/`EPRT` followed by transfer commands.<sup>[[3]](#references)[[4]](#references)[[5]](#references)</sup>
    108 
    109 If the server is writable and you want to pivot beyond simple port-scanning, check [FTP Bounce - Download 2ºFTP file](/hacktricks/network-services-pentesting/pentesting-ftp/ftp-bounce-download-2oftp-file).
    110 
    111 
    112 ## References
    113 
    114 - [1] [Nmap NSE `ftp-bounce` script](https://nmap.org/nsedoc/scripts/ftp-bounce.html)
    115 - [2] [RFC 2428 - FTP Extensions for IPv6 and NATs](https://datatracker.ietf.org/doc/html/rfc2428)
    116 - [3] [ProFTPD `mod_core` — `AllowForeignAddress`](https://www.proftpd.org/docs/modules/mod_core.html#AllowForeignAddress)
    117 - [4] [vsftpd configuration manual](https://security.appspot.com/vsftpd/vsftpd_conf.html)
    118 - [5] [pyftpdlib API — foreign-address controls](https://pyftpdlib.readthedocs.io/en/latest/api.html)
    119 - [6] [RFC 959 — File Transfer Protocol](https://www.rfc-editor.org/rfc/rfc959.html)
    120 - [7] [RFC 2577 — FTP Security Considerations](https://www.rfc-editor.org/rfc/rfc2577.html)