+43
-3
lines changedFilter options
+43
-3
lines changed Original file line number Diff line number Diff line change
@@ -102,7 +102,9 @@ class FTP:
102
102
sock = None
103
103
file = None
104
104
welcome = None
105
-
passiveserver = 1
105
+
passiveserver = True
106
+
# Disables https://bugs.python.org/issue43285 security if set to True.
107
+
trust_server_pasv_ipv4_address = False
106
108
107
109
def __init__(self, host='', user='', passwd='', acct='',
108
110
timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None, *,
@@ -320,8 +322,13 @@ def makeport(self):
320
322
return sock
321
323
322
324
def makepasv(self):
325
+
"""Internal: Does the PASV or EPSV handshake -> (address, port)"""
323
326
if self.af == socket.AF_INET:
324
-
host, port = parse227(self.sendcmd('PASV'))
327
+
untrusted_host, port = parse227(self.sendcmd('PASV'))
328
+
if self.trust_server_pasv_ipv4_address:
329
+
host = untrusted_host
330
+
else:
331
+
host = self.sock.getpeername()[0]
325
332
else:
326
333
host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
327
334
return host, port
Original file line number Diff line number Diff line change
@@ -103,6 +103,10 @@ def __init__(self, conn, encoding=DEFAULT_ENCODING):
103
103
self.next_retr_data = RETR_DATA
104
104
self.push('220 welcome')
105
105
self.encoding = encoding
106
+
# We use this as the string IPv4 address to direct the client
107
+
# to in response to a PASV command. To test security behavior.
108
+
# https://bugs.python.org/issue43285/.
109
+
self.fake_pasv_server_ip = '252.253.254.255'
106
110
107
111
def collect_incoming_data(self, data):
108
112
self.in_buffer.append(data)
@@ -143,7 +147,8 @@ def cmd_port(self, arg):
143
147
def cmd_pasv(self, arg):
144
148
with socket.create_server((self.socket.getsockname()[0], 0)) as sock:
145
149
sock.settimeout(TIMEOUT)
146
-
ip, port = sock.getsockname()[:2]
150
+
port = sock.getsockname()[1]
151
+
ip = self.fake_pasv_server_ip
147
152
ip = ip.replace('.', ','); p1 = port / 256; p2 = port % 256
148
153
self.push('227 entering passive mode (%s,%d,%d)' %(ip, p1, p2))
149
154
conn, addr = sock.accept()
@@ -707,6 +712,26 @@ def test_makepasv(self):
707
712
# IPv4 is in use, just make sure send_epsv has not been used
708
713
self.assertEqual(self.server.handler_instance.last_received_cmd, 'pasv')
709
714
715
+
def test_makepasv_issue43285_security_disabled(self):
716
+
"""Test the opt-in to the old vulnerable behavior."""
717
+
self.client.trust_server_pasv_ipv4_address = True
718
+
bad_host, port = self.client.makepasv()
719
+
self.assertEqual(
720
+
bad_host, self.server.handler_instance.fake_pasv_server_ip)
721
+
# Opening and closing a connection keeps the dummy server happy
722
+
# instead of timing out on accept.
723
+
socket.create_connection((self.client.sock.getpeername()[0], port),
724
+
timeout=TIMEOUT).close()
725
+
726
+
def test_makepasv_issue43285_security_enabled_default(self):
727
+
self.assertFalse(self.client.trust_server_pasv_ipv4_address)
728
+
trusted_host, port = self.client.makepasv()
729
+
self.assertNotEqual(
730
+
trusted_host, self.server.handler_instance.fake_pasv_server_ip)
731
+
# Opening and closing a connection keeps the dummy server happy
732
+
# instead of timing out on accept.
733
+
socket.create_connection((trusted_host, port), timeout=TIMEOUT).close()
734
+
710
735
def test_with_statement(self):
711
736
self.client.quit()
712
737
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
1
+
:mod:`ftplib` no longer trusts the IP address value returned from the server
2
+
in response to the PASV command by default. This prevents a malicious FTP
3
+
server from using the response to probe IPv4 address and port combinations
4
+
on the client network.
5
+
6
+
Code that requires the former vulnerable behavior may set a
7
+
``trust_server_pasv_ipv4_address`` attribute on their
8
+
:class:`ftplib.FTP` instances to ``True`` to re-enable it.
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4