From 787cabd8da11ca988e01f61482c97dc9c3033385 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Wed, 7 Jul 2021 12:05:44 +0900 Subject: [PATCH] [PATCH] Ignore IP addresses in PASV responses by default, and add new option use_pasv_ip This fixes CVE-2021-81810. Reported by Alexandr Savca. Re-adapted-By: Utkarsh Gupta Gbp-Pq: Name CVE-2021-31810.patch --- lib/net/ftp.rb | 12 +++++++++++- test/net/ftp/test_ftp.rb | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb index 0437e95..cd6b422 100644 --- a/lib/net/ftp.rb +++ b/lib/net/ftp.rb @@ -89,6 +89,10 @@ module Net # When +true+, the connection is in passive mode. Default: +true+. attr_accessor :passive + # When +true+, use the IP address in PASV responses. Otherwise, it uses + # the same IP address for the control connection. Default: +false+. + attr_accessor :use_pasv_ip + # When +true+, all traffic to and from the server is written # to +$stdout+. Default: +false+. attr_accessor :debug_mode @@ -171,6 +175,7 @@ module Net @logged_in = false @open_timeout = nil @read_timeout = 60 + @use_pasv_ip = false if host connect(host) if user @@ -1196,7 +1201,12 @@ module Net raise FTPReplyError, resp end if m = /\((?\d+(,\d+){3}),(?\d+,\d+)\)/.match(resp) - return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"]) + if @use_pasv_ip + host = parse_pasv_ipv4_host(m["host"]) + else + host = @sock.peeraddr[3] + end + return host, parse_pasv_port(m["port"]) else raise FTPProtoError, resp end diff --git a/test/net/ftp/test_ftp.rb b/test/net/ftp/test_ftp.rb index fbb3bf2..f8218ff 100644 --- a/test/net/ftp/test_ftp.rb +++ b/test/net/ftp/test_ftp.rb @@ -53,6 +53,7 @@ class FTPTest < Test::Unit::TestCase def test_parse227 ftp = Net::FTP.new + ftp.use_pasv_ip = true host, port = ftp.send(:parse227, "227 Entering Passive Mode (192,168,0,1,12,34)") assert_equal("192.168.0.1", host) assert_equal(3106, port) @@ -71,6 +72,13 @@ class FTPTest < Test::Unit::TestCase assert_raise(Net::FTPProtoError) do ftp.send(:parse227, "227 ) foo bar (") end + + ftp = Net::FTP.new + sock = OpenStruct.new + sock.peeraddr = [nil, nil, nil, "10.0.0.1"] + ftp.instance_variable_set(:@sock, sock) + host, port = ftp.send(:parse227, "227 Entering Passive Mode (192,168,0,1,12,34)") + assert_equal("10.0.0.1", host) end def test_parse228 -- 2.30.2