Class: Metasploit::Credential::Importer::Pwdump
- Inherits:
-
Object
- Object
- Metasploit::Credential::Importer::Pwdump
- Defined in:
- lib/metasploit/credential/importer/pwdump.rb
Overview
Implements importation behavior for pwdump files exported by Metasploit as well as files from the John the Ripper hash cracking suite: www.openwall.com/john/
Please note that in the case of data exported from Metasploit, the dataset will contain information on the Mdm::Host and Mdm::Service objects that are related to the credential. This means that Metasploit exports will be limited to containing Login objects, which is the legacy behavior of this export prior to the creation of this library.
Constant Summary collapse
- COMMENT_LINE_START_REGEX =
Matches a line starting with a ‘#’
/^[\s]*#/
- JTR_NO_PASSWORD_STRING =
The string that John the Ripper uses to designate a lack of password in a credentials entry
"NO PASSWORD"
- NONREPLAYABLE_REGEX =
Matches lines that contain usernames and non-SMB hashes
/^[\s]*([\x21-\x7f]+):([\x21-\x7f]+):::/n
- PLAINTEXT_REGEX =
Matches lines that contain usernames and plaintext passwords
/^[\s]*([\x21-\x7f]+)[\s]+([\x21-\x7f]+)?/n
- SERVICE_COMMENT_REGEX =
Matches a line that we use to get information for creating Mdm::Host and Mdm::Service objects TODO: change to use named groups from 1.9+
/^#[\s]*([0-9.]+):([0-9]+)(\x2f(tcp|udp))?[\s]*(\x28([^\x29]*)\x29)?/n
- SMB_WITH_JTR_BLANK_PASSWORD_REGEX =
Matches the way that John the Ripper exports SMB hashes with no password piece
/^[\s]*([^\s:]+):([0-9]+):NO PASSWORD\*+:NO PASSWORD\*+[^\s]*$/
- SMB_WITH_HASH_REGEX =
Matches LM/NTLM hash format
/^[\s]*([^\s:]+):[0-9]+:([A-Fa-f0-9]+:[A-Fa-f0-9]+):[^\s]*$/
- SMB_WITH_PLAINTEXT_REGEX =
Matches a line with free-form text - less restrictive than SMB_WITH_HASH_REGEX
/^[\s]*([^\s:]+):(.+):[A-Fa-f0-9]*:[A-Fa-f0-9]*:::$/
- WARNING_REGEX =
Matches warning lines in legacy pwdump files
/^[\s]*Warning:/
Constants included from Base
Base::LONG_FORM_ALLOWED_PRIVATE_TYPE_NAMES, Base::SHORT_FORM_ALLOWED_PRIVATE_TYPE_NAMES
Instance Method Summary collapse
-
#blank_or_string(check_string, dehex = false) ⇒ String
Checks a string for matching Exporter::Pwdump::BLANK_CRED_STRING and returns blank string if it matches that constant.
-
#import! ⇒ void
Perform the import of the credential data, creating Mdm::Host and Mdm::Service objects as needed, parsing out data by matching against regex constants that match the various kinds of valid lines found in the file.
-
#initialize(args = {}) ⇒ Pwdump
constructor
A new instance of Pwdump.
-
#parsed_regex_results(username, private, dehex = false) ⇒ Hash
Break a line into user, hash.
-
#service_info_from_comment_string(comment_string) ⇒ Hash
Take an msfpwdump comment string and parse it into information necessary for creating Mdm::Host and Mdm::Service objects.
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
Constructor Details
#initialize(args = {}) ⇒ Pwdump
Returns a new instance of Pwdump.
137 138 139 |
# File 'lib/metasploit/credential/importer/pwdump.rb', line 137 def initialize(args={}) super args end |
Instance Method Details
#blank_or_string(check_string, dehex = false) ⇒ String
Checks a string for matching Exporter::Pwdump::BLANK_CRED_STRING and returns blank string if it matches that constant.
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/metasploit/credential/importer/pwdump.rb', line 59 def blank_or_string(check_string, dehex=false) if check_string.blank? || check_string == Metasploit::Credential::Exporter::Pwdump::BLANK_CRED_STRING || check_string == JTR_NO_PASSWORD_STRING "" else if dehex Metasploit::Credential::Text.dehex check_string else check_string end end end |
#import! ⇒ void
This method returns an undefined value.
Perform the import of the credential data, creating Mdm::Host and Mdm::Service objects as needed, parsing out data by matching against regex constants that match the various kinds of valid lines found in the file. Ignore lines which match none of the REGEX constants.
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 |
# File 'lib/metasploit/credential/importer/pwdump.rb', line 75 def import! service_info = nil Metasploit::Credential::Core.transaction do input.each_line do |line| case line when WARNING_REGEX next when COMMENT_LINE_START_REGEX service_info = service_info_from_comment_string(line) when SMB_WITH_HASH_REGEX info = parsed_regex_results($1, $2) username, private = info[:username], info[:private] creds_class = Metasploit::Credential::NTLMHash when SMB_WITH_JTR_BLANK_PASSWORD_REGEX info = parsed_regex_results($1, $2) username, private = info[:username], info[:private] creds_class = Metasploit::Credential::NTLMHash when SMB_WITH_PLAINTEXT_REGEX info = parsed_regex_results($1, $2) username, private = info[:username], info[:private] creds_class = Metasploit::Credential::NTLMHash when NONREPLAYABLE_REGEX info = parsed_regex_results($1, $2) username, private = info[:username], info[:private] creds_class = Metasploit::Credential::NonreplayableHash when PLAINTEXT_REGEX info = parsed_regex_results($1, $2, true) username, private = info[:username], info[:private] creds_class = Metasploit::Credential::Password else next end # Skip unless we have enough to make a Login if service_info.present? if [service_info[:host_address], service_info[:port], username, private].compact.size != 4 next end else next end public_obj = Metasploit::Credential::Public.where(username: username).first_or_create private_obj = creds_class.where(data: private).first_or_create core = create_credential_core(origin: origin, private: private_obj, public: public_obj, workspace_id: workspace.id) login_opts = { address: service_info[:host_address], port: service_info[:port], protocol: service_info[:protocol], service_name: service_info[:name], workspace_id: workspace.id, core: core, status: Metasploit::Model::Login::Status::UNTRIED } create_credential_login(login_opts) end end end |
#parsed_regex_results(username, private, dehex = false) ⇒ Hash
Break a line into user, hash
146 147 148 149 150 151 152 |
# File 'lib/metasploit/credential/importer/pwdump.rb', line 146 def parsed_regex_results(username, private, dehex=false) results = {} results[:username] = blank_or_string(username, dehex) results[:private] = blank_or_string(private, dehex) results end |
#service_info_from_comment_string(comment_string) ⇒ Hash
Take an msfpwdump comment string and parse it into information necessary for creating Mdm::Host and Mdm::Service objects.
158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/metasploit/credential/importer/pwdump.rb', line 158 def service_info_from_comment_string(comment_string) service_info = {} if comment_string[SERVICE_COMMENT_REGEX] service_info[:host_address] = $1 service_info[:port] = $2 service_info[:protocol] = $4.present? ? $4 : "tcp" service_info[:name] = $6 service_info else nil end end |