diff mbox series

wget: fix CVE-2026-15146

Message ID 20260925103010.3001030-1-Ghanshyam.BanaitSanjay@windriver.com
State New
Headers show
Series wget: fix CVE-2026-15146 | expand

Commit Message

Ghanshyam Banait Sept. 25, 2026, 10:30 a.m. UTC
GNU Wget does not validate the IP address provided by an FTP PASV response while operating in FTP passive mode.
A malicious FTP server, or an HTTP server that redirects to an FTP URL, can exploit this behavior to redirect
Wget’s data connection to an arbitrary IP address and port.This allows an attacker to forge server-side requests
(SSRF) from the machine running Wget, potentially accessing localhost services or internal network resources.

Backport patch to fix CVE-2026-15146.
https://cgit.git.savannah.gnu.org/cgit/wget.git/commit/?id=4f85853f641863d5915786a8413e1a213726a62b

Ptest Result
DURATION: 17
END: /usr/lib/wget/ptest
2026-09-25T10:26
STOP: ptest-runner
TOTAL: 1 FAIL: 0

References:
  https://nvd.nist.gov/vuln/detail/CVE-2026-15146
  https://www.cve.org/CVERecord?id=CVE-2026-15146
  https://security-tracker.debian.org/tracker/CVE-2026-15146
  https://ubuntu.com/security/CVE-2026-15146

Signed-off-by: Ghanshyam Banait <Ghanshyam.BanaitSanjay@windriver.com>
---
 .../wget/wget/CVE-2026-15146.patch            | 126 ++++++++++++++++++
 meta/recipes-extended/wget/wget_1.25.0.bb     |   1 +
 2 files changed, 127 insertions(+)
 create mode 100644 meta/recipes-extended/wget/wget/CVE-2026-15146.patch
diff mbox series

Patch

diff --git a/meta/recipes-extended/wget/wget/CVE-2026-15146.patch b/meta/recipes-extended/wget/wget/CVE-2026-15146.patch
new file mode 100644
index 0000000000..5d8d1a898e
--- /dev/null
+++ b/meta/recipes-extended/wget/wget/CVE-2026-15146.patch
@@ -0,0 +1,126 @@ 
+From 4f85853f641863d5915786a8413e1a213726a62b Mon Sep 17 00:00:00 2001
+From: Acts1631 <acts1631kjv@proton.me>
+Date: Sun, 5 Jul 2026 17:22:55 -0400
+Subject: ftp: validate PASV/LPSV response address against control connection
+ peer
+
+* src/ftp-basic.c (ftp_pasv): Reject if peer address doesn't match advertised
+  address,
+  (ftp_lpsv): Likewise.
+
+ftp_pasv() and ftp_lpsv() copied the IP address and port advertised in
+the server's 227 response without checking that it matched the peer
+of the control connection.  A malicious or compromised FTP server
+could therefore direct wget's data connection to an arbitrary host and
+port of its choosing (e.g. an internal service unreachable from the
+attacker directly), which is a server-side request forgery.
+
+ftp_epsv() was already safe since it only extracts a port and reuses
+the pre-filled control-connection address.
+
+Fix ftp_pasv() and ftp_lpsv() the same way: capture the control
+connection's peer address via socket_ip_address() before parsing the
+response, and reject the response (FTPINVPASV) if the parsed address
+does not match.
+
+Verified with a fake FTP server that returns a PASV response pointing
+at a different loopback address (127.0.0.2 instead of the real peer
+127.0.0.1): before the fix wget connects to the spoofed address, after
+the fix it rejects the response with "Cannot parse PASV response."
+Legitimate transfers using a correctly-addressed PASV response
+continue to work.
+
+Copyright-paperwork-exempt: Yes
+
+CVE: CVE-2026-15146
+
+Upstream-Status: Backport [https://cgit.git.savannah.gnu.org/cgit/wget.git/commit/?id=4f85853f641863d5915786a8413e1a213726a62b]
+
+Signed-off-by: Ghanshyam Banait <Ghanshyam.BanaitSanjay@windriver.com>
+---
+ src/ftp-basic.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+
+diff --git a/src/ftp-basic.c b/src/ftp-basic.c
+index 4870256a..0f4bb821 100644
+--- a/src/ftp-basic.c
++++ b/src/ftp-basic.c
+@@ -623,10 +623,19 @@ ftp_pasv (int csock, ip_address *addr, int *port)
+   int nwritten, i;
+   uerr_t err;
+   unsigned char tmp[6];
++  ip_address peer_addr;
+ 
+   assert (addr != NULL);
+   assert (port != NULL);
+ 
++  /* Remember who we are talking to on the control connection, so that
++     the address returned in the PASV response can be checked below.
++     Accepting an arbitrary server-supplied address would let a
++     malicious FTP server redirect our data connection to any host of
++     its choosing (SSRF).  */
++  if (!socket_ip_address (csock, &peer_addr, ENDPOINT_PEER))
++    return FTPINVPASV;
++
+   xzero (*addr);
+ 
+   /* Form the request.  */
+@@ -677,6 +686,16 @@ ftp_pasv (int csock, ip_address *addr, int *port)
+   memcpy (IP_INADDR_DATA (addr), tmp, 4);
+   *port = ((tmp[4] << 8) & 0xff00) + tmp[5];
+ 
++  /* Reject the response if the advertised address does not match the
++     control connection's peer.  */
++  if (peer_addr.family != AF_INET
++      || memcmp (IP_INADDR_DATA (addr), IP_INADDR_DATA (&peer_addr), 4) != 0)
++    {
++      xzero (*addr);
++      *port = 0;
++      return FTPINVPASV;
++    }
++
+   return FTPOK;
+ }
+ 
+@@ -692,10 +711,19 @@ ftp_lpsv (int csock, ip_address *addr, int *port)
+   uerr_t err;
+   unsigned char tmp[16];
+   unsigned char tmpprt[2];
++  ip_address peer_addr;
+ 
+   assert (addr != NULL);
+   assert (port != NULL);
+ 
++  /* Remember who we are talking to on the control connection, so that
++     the address returned in the LPSV response can be checked below.
++     Accepting an arbitrary server-supplied address would let a
++     malicious FTP server redirect our data connection to any host of
++     its choosing (SSRF).  */
++  if (!socket_ip_address (csock, &peer_addr, ENDPOINT_PEER))
++    return FTPINVPASV;
++
+   xzero (*addr);
+ 
+   /* Form the request.  */
+@@ -842,6 +870,18 @@ ftp_lpsv (int csock, ip_address *addr, int *port)
+       DEBUGP (("*port is: %d\n", *port));
+     }
+ 
++  /* Reject the response if the advertised address does not match the
++     control connection's peer.  */
++  if (peer_addr.family != addr->family
++      || memcmp (IP_INADDR_DATA (addr), IP_INADDR_DATA (&peer_addr),
++                 af == 4 ? 4 : 16) != 0)
++    {
++      xzero (*addr);
++      *port = 0;
++      xfree (respline);
++      return FTPINVPASV;
++    }
++
+   xfree (respline);
+   return FTPOK;
+ }
+-- 
+cgit v1.3
+
diff --git a/meta/recipes-extended/wget/wget_1.25.0.bb b/meta/recipes-extended/wget/wget_1.25.0.bb
index 51ef1d485e..91e998ea2f 100644
--- a/meta/recipes-extended/wget/wget_1.25.0.bb
+++ b/meta/recipes-extended/wget/wget_1.25.0.bb
@@ -25,6 +25,7 @@  SRC_URI = "${GNU_MIRROR}/wget/wget-${PV}.tar.gz \
            file://CVE-2026-58471.patch \
            file://CVE-2026-16599.patch \
            file://run-ptest \
+           file://CVE-2026-15146.patch \
            "
 
 SRC_URI[sha256sum] = "766e48423e79359ea31e41db9e5c289675947a7fcf2efdcedb726ac9d0da3784"