[PATCH] Ignore IP addresses in PASV responses by default, and add new option use_pasv_ip
authorYusuke Endoh <mame@ruby-lang.org>
Wed, 7 Jul 2021 03:05:44 +0000 (12:05 +0900)
committerUtkarsh Gupta <utkarsh@debian.org>
Sun, 19 Sep 2021 03:40:46 +0000 (04:40 +0100)
This fixes CVE-2021-81810.
Reported by Alexandr Savca.

Re-adapted-By: Utkarsh Gupta <utkarsh@debian.org>
Gbp-Pq: Name CVE-2021-31810.patch

lib/net/ftp.rb
test/net/ftp/test_ftp.rb

index 0437e9504eef61388bae952eb1d7950029a115b7..cd6b422de5f8c775a594bf3c70db03449dd205b8 100644 (file)
@@ -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 = /\((?<host>\d+(,\d+){3}),(?<port>\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
index fbb3bf246ecb26801ffb63126077663860ae0151..f8218ff93f20147eb342caf91e12f09a03c2bbc8 100644 (file)
@@ -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