# lib/net/ftp.rb: trusting PASV responses allow client abuse

Ruby net/ftp trusts the IP:port in PASV responses, letting a malicious FTP server force the client to connect to arbitrary internal hosts for port scanning and banner grabbing.

- Payout: hidden
- Severity: low
- Program: Ruby
- Found by: sighook
- Disclosed: 2021-07-08
- CVE: CVE-2021-31810, CVE-2020-8284, CVE-2007-1562
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/1145454
- Library page: https://bugbountylibrary.com/r/h1%3A1145454
- Tags: area:oss domain:oss impact:data-leak impact:internal-access kind:bounty platform:hackerone sev:low tech:ruby technique:source-review vuln:info-disclosure vuln:ssrf

**Target:** Ruby stdlib net/ftp FTP client
**Root cause:** net/ftp connects the data channel to the IP and port supplied in the server's PASV reply instead of reusing the control-connection peer address.
**Steps:**
1. Run a malicious FTP server that replies to PASV with `227 Entering Passive Mode (127,0,0,1,31,187)` pointing at an internal target.
2. Client calls `ftp.connect(host, port); ftp.login; ftp.getbinaryfile('/whatever','whatever')`.
3. net/ftp opens a TCP connection to the attacker-chosen IP:port; open ports yield a successful data channel, closed ports yield `ERROR: unmatched reply`.
4. Read the data channel to extract service banners (e.g. `SSH-2.0-OpenSSH_7.2p2`).
**How found:** Noticed net/ftp honors the PASV-supplied address, compared to prior fixes in Chrome, curl (CVE-2020-8284) and Firefox (CVE-2007-1562), and tested with a custom FTP server.
**Exploitation:** In an SSRF context where a user-supplied URL is processed by net/ftp, the attacker hosts a malicious FTP server and returns arbitrary internal IP:port in PASV, turning the client into a reliable port scanner and banner grabber, bypassing IP/port allowlists.
**Escalation:** Chained with an existing SSRF to bypass internal IP/port filtering and enumerate private services.
**Insight:** FTP clients should ignore the PASV-supplied IP and reuse the control connection's peer address; check any protocol client that accepts server-directed connection endpoints (PASV, EPSV, redirects) for SSRF-style pivot.

