A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/python/cpython/commit/79373951b3eab585d42e0f0ab83718cbe1d0ee33 below:

[3.7] bpo-43285 Make ftplib not trust the PASV response. (GH-24838) (… · python/cpython@7937395 · GitHub

File tree Expand file treeCollapse file tree 4 files changed

+51

-2

lines changed

Filter options

Expand file treeCollapse file tree 4 files changed

+51

-2

lines changed Original file line number Diff line number Diff line change

@@ -2585,3 +2585,12 @@ separator key, with ``&`` as the default. This change also affects

2585 2585

functions internally. For more details, please see their respective

2586 2586

documentation.

2587 2587

(Contributed by Adam Goldschmidt, Senthil Kumaran and Ken Jin in :issue:`42967`.)

2588 + 2589 +

Notable changes in Python 3.7.11

2590 +

================================

2591 + 2592 +

A security fix alters the :class:`ftplib.FTP` behavior to not trust the

2593 +

IPv4 address sent from the remote server when setting up a passive data

2594 +

channel. We reuse the ftp server IP address instead. For unusual code

2595 +

requiring the old behavior, set a ``trust_server_pasv_ipv4_address``

2596 +

attribute on your FTP instance to ``True``. (See :issue:`43285`)

Original file line number Diff line number Diff line change

@@ -104,6 +104,8 @@ class FTP:

104 104

welcome = None

105 105

passiveserver = 1

106 106

encoding = "latin-1"

107 +

# Disables https://bugs.python.org/issue43285 security if set to True.

108 +

trust_server_pasv_ipv4_address = False

107 109 108 110

# Initialization method (called by class instantiation).

109 111

# Initialize host to localhost, port to standard ftp port

@@ -333,8 +335,13 @@ def makeport(self):

333 335

return sock

334 336 335 337

def makepasv(self):

338 +

"""Internal: Does the PASV or EPSV handshake -> (address, port)"""

336 339

if self.af == socket.AF_INET:

337 -

host, port = parse227(self.sendcmd('PASV'))

340 +

untrusted_host, port = parse227(self.sendcmd('PASV'))

341 +

if self.trust_server_pasv_ipv4_address:

342 +

host = untrusted_host

343 +

else:

344 +

host = self.sock.getpeername()[0]

338 345

else:

339 346

host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())

340 347

return host, port

Original file line number Diff line number Diff line change

@@ -94,6 +94,10 @@ def __init__(self, conn):

94 94

self.rest = None

95 95

self.next_retr_data = RETR_DATA

96 96

self.push('220 welcome')

97 +

# We use this as the string IPv4 address to direct the client

98 +

# to in response to a PASV command. To test security behavior.

99 +

# https://bugs.python.org/issue43285/.

100 +

self.fake_pasv_server_ip = '252.253.254.255'

97 101 98 102

def collect_incoming_data(self, data):

99 103

self.in_buffer.append(data)

@@ -136,7 +140,8 @@ def cmd_pasv(self, arg):

136 140

sock.bind((self.socket.getsockname()[0], 0))

137 141

sock.listen()

138 142

sock.settimeout(TIMEOUT)

139 -

ip, port = sock.getsockname()[:2]

143 +

port = sock.getsockname()[1]

144 +

ip = self.fake_pasv_server_ip

140 145

ip = ip.replace('.', ','); p1 = port / 256; p2 = port % 256

141 146

self.push('227 entering passive mode (%s,%d,%d)' %(ip, p1, p2))

142 147

conn, addr = sock.accept()

@@ -698,6 +703,26 @@ def test_makepasv(self):

698 703

# IPv4 is in use, just make sure send_epsv has not been used

699 704

self.assertEqual(self.server.handler_instance.last_received_cmd, 'pasv')

700 705 706 +

def test_makepasv_issue43285_security_disabled(self):

707 +

"""Test the opt-in to the old vulnerable behavior."""

708 +

self.client.trust_server_pasv_ipv4_address = True

709 +

bad_host, port = self.client.makepasv()

710 +

self.assertEqual(

711 +

bad_host, self.server.handler_instance.fake_pasv_server_ip)

712 +

# Opening and closing a connection keeps the dummy server happy

713 +

# instead of timing out on accept.

714 +

socket.create_connection((self.client.sock.getpeername()[0], port),

715 +

timeout=TIMEOUT).close()

716 + 717 +

def test_makepasv_issue43285_security_enabled_default(self):

718 +

self.assertFalse(self.client.trust_server_pasv_ipv4_address)

719 +

trusted_host, port = self.client.makepasv()

720 +

self.assertNotEqual(

721 +

trusted_host, self.server.handler_instance.fake_pasv_server_ip)

722 +

# Opening and closing a connection keeps the dummy server happy

723 +

# instead of timing out on accept.

724 +

socket.create_connection((trusted_host, port), timeout=TIMEOUT).close()

725 + 701 726

def test_with_statement(self):

702 727

self.client.quit()

703 728 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