Class: Msf::RPC::RPC_Auth

Inherits:
RPC_Base show all
Defined in:
lib/msf/core/rpc/v10/rpc_auth.rb

Constant Summary collapse

@@loaded_sha2 =

Dynamic load test for SHA2 (needed for SHA512)

false

Instance Attribute Summary

Attributes inherited from RPC_Base

#framework, #job_status_tracker, #service, #tokens, #users

Instance Method Summary collapse

Methods inherited from RPC_Base

#error, #initialize

Constructor Details

This class inherits a constructor from Msf::RPC::RPC_Base

Instance Method Details

#rpc_login_noauth(user, pass) ⇒ Hash

Handles client authentication. The authentication token will expire 5 minutes after the last request was made.

Examples:

Here's how you would use this from the client:

# This returns something like the following:
# {"result"=>"success", "token"=>"TEMPyp1N40NK8GM0Tx7A87E6Neak2tVJ"}
rpc.call('auth.login_noauth', 'username', 'password')

Parameters:

  • user (String)

    The username.

  • pass (String)

    The password.

Returns:

  • (Hash)

    A hash indicating a successful login, it contains the following keys:

    • 'result' [String] A successful message: 'success'.

    • 'token' [String] A token for the authentication.

Raises:

  • (Msf::RPC::Exception)

    Something is wrong while authenticating, you can possibly get:

    • 401 Failed authentication.


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/msf/core/rpc/v10/rpc_auth.rb', line 28

def (user,pass)
  if not (user.kind_of?(::String) and pass.kind_of?(::String))
    error(401, "Login Failed")
  end

  # handle authentication here
  fail = true
  self.users.each do |u|
    if(u[0] == user and u[1] == pass)
      fail = false
      break
    end
  end

  fail = db_validate_auth(user,pass) if fail

  if fail
    # Introduce a random delay in the response to annoy brute forcers
    delay = [ ( rand(3000) / 1000.0 ), 0.50 ].max
    ::IO.select(nil, nil, nil, delay)

    # Send back a 401 denied error
    error(401, "Login Failed")
  end

  token = "TEMP" + Rex::Text.rand_text_alphanumeric(28)
  self.service.tokens[token] = [user, Time.now.to_i, Time.now.to_i]
  { "result" => "success", "token" => token }
end

#rpc_logout(token) ⇒ Hash

Handles client deauthentication.

Examples:

Here's how you would use this from the client:

# This returns something like:
# {"result"=>"success"}
rpc.call('auth.logout', 'TEMPyp1N40NK8GM0Tx7A87E6Neak2tVJ')

Parameters:

  • token (String)

    The user's token to log off.

Returns:

  • (Hash)

    A hash indiciating the action was successful. It contains the following key:

    • 'result' [String] The successful message: 'success'

Raises:

  • (Msf::RPC::Exception)

    An error indicating a failed deauthentication, including:

    • 500 Invalid authentication token.

    • 500 Permanent authentication token.


71
72
73
74
75
76
77
78
79
80
# File 'lib/msf/core/rpc/v10/rpc_auth.rb', line 71

def rpc_logout(token)
  found = self.service.tokens[token]
  error("500", "Invalid Authentication Token") if not found
  error("500", "Permanent Authentication Token") if found[3] == true

  # Delete the token if its not marked as permanent
  self.service.tokens.delete(token)

  { "result" => "success" }
end

#rpc_token_add(token) ⇒ Hash

Adds a new token to the database.

Examples:

Here's how you would use this from the client:

rpc.call('auth.token_add', 'UNIQUE_TOKEN')

Parameters:

  • token (String)

    A unique token.

Returns:

  • (Hash)

    A hash indicating the action was successful. It contains the following key:

    • 'result' [String] The successful message: 'success'


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/msf/core/rpc/v10/rpc_auth.rb', line 113

def rpc_token_add(token)
  db = false
  begin
    if framework.db and framework.db.active
      t = ::Mdm::ApiKey.new
      t.token = token
      t.save!
      db = true
    end
  rescue ::Exception
  end

  if not db
    self.service.tokens[token] = [nil, nil, nil, true]
  end

  { "result" => "success" }
end

#rpc_token_generateHash

Generates a random 32-byte authentication token. The token is added to the database as a side-effect.

Examples:

Here's how you would use this from the client:

rpc.call('auth.token_generate')

Returns:

  • (Hash)

    A hash indicating the action was successful, also the new token. It contains the following keys:

    • 'result' [String] The successful message: 'success'

    • 'token' [String] A new token.


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/msf/core/rpc/v10/rpc_auth.rb', line 142

def rpc_token_generate
  token = Rex::Text.rand_text_alphanumeric(32)
  db = false
  begin
    if framework.db and framework.db.active
      t = ::Mdm::ApiKey.new
      t.token = token
      t.save!
      db = true
    end
  rescue ::Exception
  end

  if not db
    token = "TEMP" + Rex::Text.rand_text_numeric(28)
    self.service.tokens[token] = [nil, nil, nil, true]
  end

  { "result" => "success", "token" => token }
end

#rpc_token_listHash

Returns a list of authentication tokens, including the ones that are temporary, permanent, or stored in the backend.

Examples:

Here's how you would use this from the client:

# This returns something like:
# {"tokens"=>["TEMPf5I4Ec8cBEKVD8D7xtIbTXWoKapP", "TEMPtcVmMld8w74zo0CYeosM3iXW0nJz"]}
rpc.call('auth.token_list')

Returns:

  • (Hash)

    A hash that contains a list of authentication tokens. It contains the following key:

    • 'tokens' [Array<string>] An array of tokens.


92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/msf/core/rpc/v10/rpc_auth.rb', line 92

def rpc_token_list
  res = self.service.tokens.keys
  begin
    if framework.db and framework.db.active
      ::Mdm::ApiKey.all.each do |k|
        res << k.token
      end
    end
  rescue ::Exception
  end
  { "tokens" => res }
end

#rpc_token_remove(token) ⇒ Hash

Removes a token from the database. Similar to what #rpc_logout does internally, except this can remove tokens stored in the database backend (Mdm).

Examples:

Here's how you would use this from the client:

rpc.call('auth.token_remove', 'TEMPtcVmMld8w74zo0CYeosM3iXW0nJz')

Parameters:

  • token (String)

    The token to delete.

Returns:

  • (Hash)

    A hash indicating the action was successful. It contains the following key:

    • 'result' [String] The successful message: 'success'

See Also:


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/msf/core/rpc/v10/rpc_auth.rb', line 173

def rpc_token_remove(token)
  db = false
  begin
    if framework.db and framework.db.active
      t = ::Mdm::ApiKey.find_by_token(token)
      t.destroy if t
      db = true
    end
  rescue ::Exception
  end

  self.service.tokens.delete(token)

  { "result" => "success" }
end