Module: Msf::Exploit::Remote::FtpServer
- Includes:
- TcpServer
- Defined in:
- lib/msf/core/exploit/remote/ftp_server.rb
Overview
This module exposes methods that may be useful to exploits that deal with clients that speak the File Transfer Protocol (FTP).
Instance Attribute Summary
Attributes included from SocketServer
Instance Method Summary collapse
- #active_data_port_for_client(c, port) ⇒ Object
-
#establish_data_connection(c) ⇒ Socket?
Create a socket for the protocol data, either PASV or PORT, depending on the client.
-
#initialize(info = {}) ⇒ Object
Creates an instance of an FTP exploit module.
- #on_client_close(c) ⇒ Object
-
#on_client_connect(c) ⇒ Object
Called when a client connects.
-
#on_client_data(c) ⇒ Object
Dispatches client requests to command handlers.
- #passive_data_port_for_client(c) ⇒ Object
-
#setup ⇒ Object
Prepares the module for exploitation, initializes any state, and starts the payload handler.
Methods included from TcpServer
#ssl, #ssl_cert, #ssl_cipher, #ssl_compression, #ssl_version, #start_service
Methods included from SocketServer
#_determine_server_comm, #bindhost, #bindport, #cleanup, #cleanup_service, #exploit, #primer, #regenerate_payload, #srvhost, #srvport, #start_service, #via_string
Instance Method Details
#active_data_port_for_client(c, port) ⇒ Object
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 189 def active_data_port_for_client(c,port) @state[c][:mode] = :active connector = Proc.new { host = c.peerhost.dup sock = Rex::Socket::Tcp.create( 'PeerHost' => host, 'PeerPort' => port, 'Context' => { 'Msf' => framework, 'MsfExploit' => self } ) add_socket(sock) sock } @state[c][:active_connector] = connector @state[c][:active_port] = port end |
#establish_data_connection(c) ⇒ Socket?
Create a socket for the protocol data, either PASV or PORT, depending on the client.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 217 def establish_data_connection(c) begin Timeout.timeout(20) do if(@state[c][:mode] == :active) return @state[c][:active_connector].call() end if(@state[c][:mode] == :passive) c = @state[c][:passive_sock].accept add_socket(c) return c end end rescue ::Exception => e print_error("Failed to establish data connection: #{e.class} #{e}") end nil end |
#initialize(info = {}) ⇒ Object
Creates an instance of an FTP exploit module.
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 18 def initialize(info = {}) super # Register the options that all FTP exploits may make use of. ( [ OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ]), OptPort.new('PASVPORT', [ false, "The local PASV data port to listen on (0 is random)", 0 ]) ], Msf::Exploit::Remote::FtpServer) end |
#on_client_close(c) ⇒ Object
165 166 167 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 165 def on_client_close(c) @state.delete(c) end |
#on_client_connect(c) ⇒ Object
Called when a client connects.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 36 def on_client_connect(c) @state[c] = { :name => "#{c.peerhost}:#{c.peerport}", :ip => c.peerhost, :port => c.peerport, :user => nil, :pass => nil, :cwd => '/' } active_data_port_for_client(c, 20) c.put "220 FTP Server Ready\r\n" end |
#on_client_data(c) ⇒ Object
Dispatches client requests to command handlers.
Handlers should be named on_client_command_*
, ending with a downcased FTP verb, e.g. on_client_command_user
. If no handler exists for the given command, returns a generic default response.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 70 def on_client_data(c) data = c.get_once return if not data cmd,arg = data.strip.split(/\s+/, 2) arg ||= "" return if not cmd # Allow per-command overrides if self.respond_to?("on_client_command_#{cmd.downcase}", true) return self.send("on_client_command_#{cmd.downcase}", c, arg) end case cmd.upcase when 'USER' @state[c][:user] = arg c.put "331 User name okay, need password...\r\n" return when 'PASS' @state[c][:pass] = arg print_status("#{@state[c][:name]} LOGIN #{@state[c][:user]} / #{@state[c][:pass]}") c.put "230 Login OK\r\n" return when 'QUIT' c.put "221 Logout\r\n" return when 'SYST' c.put "215 UNIX Type: L8\r\n" return when 'TYPE' c.put "200 Type is set\r\n" return when 'CWD' c.put "250 CWD command successful.\r\n" return when 'PWD' c.put "257 \"#{@state[c][:cwd]}\" is current directory.\r\n" return when 'SIZE' c.put "213 1\r\n" return when 'MDTM' c.put "213 #{Time.now.strftime("%Y%m%d%H%M%S")}\r\n" return when 'PORT' port = arg.split(',')[4,2] if(not port and port.length == 2) c.put("500 Illegal PORT command.\r\n") return end port = port.map{|x| x.to_i}.pack('C*').unpack('n')[0] active_data_port_for_client(c, port) c.put "200 PORT command successful.\r\n" return when 'PASV' daddr = Rex::Socket.source_address(c.peerhost) dport = passive_data_port_for_client(c) @state[c][:daddr] = daddr @state[c][:dport] = dport pasv = (daddr.split('.') + [dport].pack('n').unpack('CC')).join(',') c.put "227 Entering Passive Mode (#{pasv})\r\n" return when /^(STOR|MKD|REM|DEL|RMD)$/ c.put "500 Access denied\r\n" return else # Allow per-command overrides if(self.respond_to?("on_client_unknown_command")) return self.send("on_client_unknown_command", c, cmd.upcase, arg) end print_status("#{@state[c][:name]} UNKNOWN '#{cmd} #{arg}'") c.put("500 '#{cmd} #{arg}': command not understood.\r\n") return end return end |
#passive_data_port_for_client(c) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 169 def passive_data_port_for_client(c) @state[c][:mode] = :passive if(not @state[c][:passive_sock]) s = Rex::Socket::TcpServer.create( 'LocalHost' => '0.0.0.0', 'LocalPort' => datastore['PASVPORT'].to_i, 'Context' => { 'Msf' => framework, 'MsfExploit' => self } ) dport = s.getsockname[2] @state[c][:passive_sock] = s @state[c][:passive_port] = dport add_socket(s) end @state[c][:passive_port] end |
#setup ⇒ Object
Prepares the module for exploitation, initializes any state, and starts the payload handler.
30 31 32 33 |
# File 'lib/msf/core/exploit/remote/ftp_server.rb', line 30 def setup super @state = {} end |