You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by co...@apache.org on 2026/09/29 08:38:27 UTC

svn commit: r1938674 - in httpd/httpd/branches/2.4.x: . modules/proxy

Author: covener
Date: Tue Sep 29 08:38:27 2026
New Revision: 1938674

Log:
Merge r1938673 from trunk:

check PASV addresses

Modified:
   httpd/httpd/branches/2.4.x/   (props changed)
   httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ftp.c

Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ftp.c
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ftp.c	Tue Sep 29 08:35:17 2026	(r1938673)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ftp.c	Tue Sep 29 08:38:27 2026	(r1938674)
@@ -1502,11 +1502,24 @@ static int proxy_ftp_handler(request_rec
                  "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) {
 
                 apr_sockaddr_t *pasv_addr;
+                apr_sockaddr_t *ctrl_addr;
+                char *ctrl_ip;
+                const char *pasv_host;
                 apr_port_t pasvport = (p1 << 8) + p0;
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01044)
                               "PASV contacting host %d.%d.%d.%d:%d",
                               h3, h2, h1, h0, pasvport);
 
+                /* Reject PASV redirects to a different host than the
+                 * control connection peer, preventing FTP bounce attacks. */
+                pasv_host = apr_psprintf(p, "%d.%d.%d.%d", h3, h2, h1, h0);
+                if (apr_socket_addr_get(&ctrl_addr, APR_REMOTE, sock) != APR_SUCCESS
+                    || apr_sockaddr_ip_get(&ctrl_ip, ctrl_addr) != APR_SUCCESS
+                    || strcmp(pasv_host, ctrl_ip) != 0) {
+                    return ftp_proxyerror(r, backend, HTTP_FORBIDDEN,
+                                         "PASV address does not match FTP server");
+                }
+
                 if ((rv = apr_socket_create(&data_sock, backend->addr->family,
                                             SOCK_STREAM, 0, r->pool)) != APR_SUCCESS) {
                     ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01045)
@@ -1530,8 +1543,7 @@ static int proxy_ftp_handler(request_rec
                 }
 
                 /* make the connection */
-                err = apr_sockaddr_info_get(&pasv_addr, apr_psprintf(p, "%d.%d.%d.%d",
-                                                                     h3, h2, h1, h0),
+                err = apr_sockaddr_info_get(&pasv_addr, pasv_host,
                                             backend->addr->family, pasvport, 0, p);
                 if (APR_SUCCESS != err) {
                     return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,