Class: Metasploit::Framework::LoginScanner::Redis

Inherits:
Object
  • Object
show all
Includes:
Base, RexSocket, Tcp::Client
Defined in:
lib/metasploit/framework/login_scanner/redis.rb

Overview

This is the LoginScanner class for dealing with REDIS. It is responsible for taking a single target, and a list of credentials and attempting them. It then saves the results.

Constant Summary collapse

DEFAULT_PORT =
6379
LIKELY_PORTS =
[ DEFAULT_PORT ]
LIKELY_SERVICE_NAMES =
[ 'redis' ]
PRIVATE_TYPES =
[ :password ]
REALM_KEY =
nil

Instance Attribute Summary

Attributes included from Tcp::Client

#max_send_size, #send_delay, #sock

Instance Method Summary collapse

Methods included from Tcp::Client

#chost, #connect, #cport, #disconnect, #proxies, #rhost, #rport, #set_tcp_evasions, #ssl, #ssl_version

Instance Method Details

#attempt_login(credential) ⇒ Metasploit::Framework::LoginScanner::Result

This method attempts a single login with a single credential against the target

Parameters:

  • credential (Credential)

    The credential object to attempt to login with

Returns:



66
67
68
69
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
# File 'lib/metasploit/framework/login_scanner/redis.rb', line 66

def (credential)
  result_options = {
    credential: credential,
    status: Metasploit::Model::Login::Status::INCORRECT,
    host: host,
    port: port,
    protocol: 'tcp',
    service_name: 'redis'
  }

  disconnect if sock

  begin
    connect
    select([sock], nil, nil, 0.4)

    # Skip this call if we're dealing with an older redis version.
    response = authenticate(credential.public.to_s, credential.private.to_s) unless @older_redis

    # If we're dealing with an older redis version or the previous call failed,
    # try the backwards compatibility call instead.
    # We also set the @older_redis to true if we haven't as we might be entering this
    # block from the match response.
    if @older_redis || (response && response.match(::Rex::Proto::Redis::Base::Constants::WRONG_ARGUMENTS_FOR_AUTH))
      @older_redis ||= true
      response = authenticate_pre_v6(credential.private.to_s)
    end

    result_options[:proof] = response
    result_options[:status] = (result_options[:proof])
  rescue Rex::ConnectionError, EOFError, Timeout::Error, Errno::EPIPE => e
    result_options.merge!(
      proof: e,
      status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
    )
  end

  disconnect if sock

  ::Metasploit::Framework::LoginScanner::Result.new(result_options)
end

#parent_scan!Object

Required to be able to invoke the scan! method from the included Base module. We do not use inheritance, so overwriting a method and relying on super does not work in this case.



21
# File 'lib/metasploit/framework/login_scanner/redis.rb', line 21

alias parent_scan! scan!

#redis_proto(command_parts) ⇒ Object

This method can create redis command which can be read by redis server



53
54
55
56
57
58
59
60
61
# File 'lib/metasploit/framework/login_scanner/redis.rb', line 53

def redis_proto(command_parts)
  return if command_parts.blank?

  command = "*#{command_parts.length}\r\n"
  command_parts.each do |p|
    command << "$#{p.length}\r\n#{p}\r\n"
  end
  command
end

#scan! {|result| ... } ⇒ void

This method returns an undefined value.

Attempt to login with every credential in #cred_details, by calling #attempt_login once for each.

If a successful login is found for a user, no more attempts will be made for that user. If the scanner detects that no authentication is required, no further attempts will be made at all.

Yield Parameters:

Yield Returns:

  • (void)


40
41
42
43
44
45
46
47
48
49
50
# File 'lib/metasploit/framework/login_scanner/redis.rb', line 40

def scan!(&block)
  first_credential = to_enum(:each_credential).first
  result = (first_credential)
  result.freeze

  if result.status == Metasploit::Model::Login::Status::NO_AUTH_REQUIRED
    yield result if block_given?
  else
    parent_scan!(&block)
  end
end