A RetroSearch Logo

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

Search Query:

Showing content from https://github.com/python/cpython/commit/4134f154ae2f621f25c5d698cc0f1748035a1b88 below:

[3.6] bpo-43285 Make ftplib not trust the PASV response. (GH-24838) (… · python/cpython@4134f15 · 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

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

2472 2472

functions internally. For more details, please see their respective

2473 2473

documentation.

2474 2474

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

2475 + 2476 +

Notable changes in Python 3.6.14

2477 +

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

2478 + 2479 +

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

2480 +

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

2481 +

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

2482 +

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

2483 +

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()

@@ -694,6 +699,26 @@ def test_makepasv(self):

694 699

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

695 700

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

696 701 702 +

def test_makepasv_issue43285_security_disabled(self):

703 +

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

704 +

self.client.trust_server_pasv_ipv4_address = True

705 +

bad_host, port = self.client.makepasv()

706 +

self.assertEqual(

707 +

bad_host, self.server.handler_instance.fake_pasv_server_ip)

708 +

# Opening and closing a connection keeps the dummy server happy

709 +

# instead of timing out on accept.

710 +

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

711 +

timeout=TIMEOUT).close()

712 + 713 +

def test_makepasv_issue43285_security_enabled_default(self):

714 +

self.assertFalse(self.client.trust_server_pasv_ipv4_address)

715 +

trusted_host, port = self.client.makepasv()

716 +

self.assertNotEqual(

717 +

trusted_host, self.server.handler_instance.fake_pasv_server_ip)

718 +

# Opening and closing a connection keeps the dummy server happy

719 +

# instead of timing out on accept.

720 +

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

721 + 697 722

def test_with_statement(self):

698 723

self.client.quit()

699 724 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