Module Name:    src
Committed By:   lukem
Date:           Thu Aug 26 06:16:29 UTC 2021

Modified Files:
        src/usr.bin/ftp: ftp.c

Log Message:
ftp: validate address from PASV and LPSV response

Fail if the server's response to PASV or LPSV contains an IP address
that doesn't match that of the control connection.
(EPSV already only uses the port portion of the server's response,
per RFC 2428).

Previously a hostile server could cause ftp to open a data connection elsewhere.

Many other ftp implementations have had a similar change for many years,
including those in popular browsers (before they deprecated FTP ...)

Thanks to Simon Josefsson notifying me about
  https://lists.gnu.org/archive/html/bug-inetutils/2021-06/msg00002.html


To generate a diff of this commit:
cvs rdiff -u -r1.172 -r1.173 src/usr.bin/ftp/ftp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/ftp/ftp.c
diff -u src/usr.bin/ftp/ftp.c:1.172 src/usr.bin/ftp/ftp.c:1.173
--- src/usr.bin/ftp/ftp.c:1.172	Thu Jun  3 10:11:00 2021
+++ src/usr.bin/ftp/ftp.c	Thu Aug 26 06:16:29 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ftp.c,v 1.172 2021/06/03 10:11:00 lukem Exp $	*/
+/*	$NetBSD: ftp.c,v 1.173 2021/08/26 06:16:29 lukem Exp $	*/
 
 /*-
  * Copyright (c) 1996-2021 The NetBSD Foundation, Inc.
@@ -92,7 +92,7 @@
 #if 0
 static char sccsid[] = "@(#)ftp.c	8.6 (Berkeley) 10/27/94";
 #else
-__RCSID("$NetBSD: ftp.c,v 1.172 2021/06/03 10:11:00 lukem Exp $");
+__RCSID("$NetBSD: ftp.c,v 1.173 2021/08/26 06:16:29 lukem Exp $");
 #endif
 #endif /* not lint */
 
@@ -1406,6 +1406,12 @@ initconn(void)
 			data_addr.si_su.su_sin.sin_addr.s_addr =
 			    htonl(pack4(addr, 0));
 			data_addr.su_port = htons(pack2(port, 0));
+			if (data_addr.si_su.su_sin.sin_addr.s_addr !=
+			    hisctladdr.si_su.su_sin.sin_addr.s_addr) {
+				fputs("Passive mode address mismatch.\n",
+				    ttyout);
+				goto bad;
+			}
 		} else if (strcmp(pasvcmd, "LPSV") == 0) {
 			if (code / 10 == 22 && code != 228) {
 				fputs("wrong server: return code must be 228\n",
@@ -1440,6 +1446,12 @@ initconn(void)
 				data_addr.si_su.su_sin.sin_addr.s_addr =
 				    htonl(pack4(addr, 0));
 				data_addr.su_port = htons(pack2(port, 0));
+				if (data_addr.si_su.su_sin.sin_addr.s_addr !=
+				    hisctladdr.si_su.su_sin.sin_addr.s_addr) {
+					fputs("Passive mode address mismatch.\n",
+					    ttyout);
+					goto bad;
+				}
 				break;
 #ifdef INET6
 			case AF_INET6:
@@ -1477,6 +1489,14 @@ initconn(void)
 				}
 			    }
 				data_addr.su_port = htons(pack2(port, 0));
+				if (memcmp(
+				    &data_addr.si_su.su_sin6.sin6_addr,
+				    &hisctladdr.si_su.su_sin6.sin6_addr,
+				    sizeof(data_addr.si_su.su_sin6.sin6_addr))) {
+					fputs("Passive mode address mismatch.\n",
+					    ttyout);
+					goto bad;
+				}
 				break;
 #endif
 			default:

Reply via email to