Class: Metasploit::Credential::Importer::Core

Inherits:
Object
  • Object
show all
Includes:
Creation, Base
Defined in:
lib/metasploit/credential/importer/core.rb

Overview

Creates Core objects and their associated Public, Private, and Realm objects from a CSV file.

Successful import will also create a Origin::Import

Constant Summary collapse

VALID_LONG_CSV_HEADERS =

Valid headers for a CSV containing heterogenous Private types and values for Realm

[:username, :private_type, :private_data, :realm_key, :realm_value, :host_address, :service_port, :service_name, :service_protocol]
VALID_SHORT_CSV_HEADERS =

Valid headers for a “short” CSV containing only data for Public and Private objects

[:username,  :private_data]

Constants included from Base

Base::LONG_FORM_ALLOWED_PRIVATE_TYPE_NAMES, Base::SHORT_FORM_ALLOWED_PRIVATE_TYPE_NAMES

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Creation

#active_db?, #create_cracked_credential, #create_credential, #create_credential_core, #create_credential_login, #create_credential_origin, #create_credential_origin_cracked_password, #create_credential_origin_import, #create_credential_origin_manual, #create_credential_origin_service, #create_credential_origin_session, #create_credential_private, #create_credential_public, #create_credential_realm, #create_credential_service, #invalidate_login

Methods included from Base

#initialize

Instance Attribute Details

#csv_objectCSV

An instance of ‘CSV` from whence cometh the sweet sweet credential input

Returns:

  • (CSV)


33
34
35
# File 'lib/metasploit/credential/importer/core.rb', line 33

def csv_object
  @csv_object
end

#private_credential_typeString

The name of one of the subclasses of Private. This will be the same for all the Private objects created during the import.

Returns:

  • (String)


41
42
43
# File 'lib/metasploit/credential/importer/core.rb', line 41

def private_credential_type
  @private_credential_type
end

Instance Method Details

#import!void

This method returns an undefined value.

If no #private_credential_type is set, assumes that the CSV contains a mixture of private types and realms. Otherwise, assume that this is a short form import and process accordingly.



76
77
78
79
80
81
82
# File 'lib/metasploit/credential/importer/core.rb', line 76

def import!
  if private_credential_type.present?
    import_short_form
  else
    import_long_form
  end
end

#import_long_formvoid

This method returns an undefined value.

Performs an import of a “long” CSV - one that that contains realms and heterogenous private types Performs a pretty naive import from the data in #csv_object, allowing the import to have different private types per row, and attempting to reduce database lookups by storing found or created Realm objects in a lookup Hash that gets updated with every new Realm found, and then consulted in analysis of subsequent rows.



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
# File 'lib/metasploit/credential/importer/core.rb', line 91

def import_long_form
  realms = Hash.new
  Metasploit::Credential::Core.transaction do
    csv_object.each do |row|
      next if row.header_row?
      next unless row['username'].present? || row['private_data'].present?

      username      = row['username'].present? ? row['username'] : ''

      realm_key     = row['realm_key']
      realm_value   = row['realm_value']  # Use the name of the Realm as a lookup for getting the object

      private_class = row['private_type'].present? ? row['private_type'].constantize : ''
      private_data  = row['private_data'].present? ? row['private_data'] : ''

      # Host and Service information for Logins
      host_address     = row['host_address']
      service_port     = row['service_port']
      service_protocol = row['service_protocol']
      service_name     = row['service_name']


      if realms[realm_value].nil?
        realms[realm_value]  = Metasploit::Credential::Realm.where(key: realm_key, value: realm_value).first_or_create
      end

      realm_object_for_row   = realms[realm_value]
      public_object_for_row  = Metasploit::Credential::Public.where(username: username).first_or_create

      if private_class.present? &&  LONG_FORM_ALLOWED_PRIVATE_TYPE_NAMES.include?(private_class.name)
        if private_class == Metasploit::Credential::SSHKey
          private_object_for_row = Metasploit::Credential::SSHKey.where(data: key_data_from_file(private_data)).first_or_create
        else
          private_object_for_row = private_class.where(data: private_data).first_or_create
        end
      end

      core = create_credential_core(origin:origin, workspace_id: workspace.id,
                                                   public: public_object_for_row,
                                                   private: private_object_for_row,
                                                   realm: realm_object_for_row )

      # Make Logins with attendant Host/Service information if we are doing that
      if host_address.present? && service_port.present? && service_protocol.present?
         = {
          core: core,
          status: Metasploit::Model::Login::Status::UNTRIED,  # don't trust creds on import
          address: host_address,
          port: service_port,
          protocol: service_protocol,
          workspace_id: workspace.id,
          service_name: service_name.present? ? service_name : ""
        }
        ()
      end
    end
  end
end

#import_short_formvoid

This method returns an undefined value.

Performs an import of a “short” form of CSV - one that contains only one type of Private and no Realm data



154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/metasploit/credential/importer/core.rb', line 154

def import_short_form
  Metasploit::Credential::Core.transaction do
    csv_object.each do |row|
      next if row.header_row?

      public_object_for_row  = Metasploit::Credential::Public.where(username: row['username']).first_or_create
      private_object_for_row = private_credential_type.constantize.where(data: row['private_data']).first_or_create
      create_credential_core(origin:origin, workspace_id: workspace.id,
                                    public: public_object_for_row,
                                    private: private_object_for_row)
    end
  end
end

#key_data_from_file(key_file_name) ⇒ String

The key data inside the file at key_file_name

Parameters:

  • key_file_name (String)

Returns:

  • (String)


68
69
70
71
# File 'lib/metasploit/credential/importer/core.rb', line 68

def key_data_from_file(key_file_name)
  full_key_file_path = File.join(File.dirname(input.path), Metasploit::Credential::Importer::Zip::KEYS_SUBDIRECTORY_NAME, key_file_name)
  File.open(full_key_file_path, 'r').read
end