Code for modeling and managing credentials in Metasploit, implemented as a Rails Engine
License: BSD 3-Clause "New" or "Revised" License
Ruby 98.90%HTML 0.86%JavaScript 0.13%CSS 0.11%
metasploit-credential's Introduction
Metasploit::Credential
Versioning
Metasploit::Credential is versioned using semantic versioning 2.0. Each branch
should set Metasploit::Credential::Version::PRERELEASE to the branch name, while master should have no PRERELEASE
and the PRERELEASE section of Metasploit::Credential::VERSION does not exist.
Documentation
Metasploit::Credential is documented using YARD. For each ActiveRecord::Base descendant, it uses RailsERD to
generate an Entity-Relationship Diagram of all classes to which the descendant has a belongs_to relationship either
directly or indirectly.
Database Setup
RailsERD requires access to the database to walk the ActiveRecord::Base associations, so setup the database.yml,
create the database, and run the migrations:
cp spec/dummy/config/database.yml.example spec/dummy/config/database.yml
# fill in passwords
edit spec/dummy/config/database.yml
rake db:create db:migrate
Graphviz Setup
In order to generate the diagrams as PNGs, graphviz is used. It will need to be installed using your OS's package
manager.
OSX
`brew install graphviz`
Graphviz may have issues when used on OSX Mavericks or later. If rake yard hangs or you get
'CoreTest performance note' messages when running 'rake yard', you should reinstall graphviz as follows:
brew reinstall graphviz --with-bindings --with-freetype --with-librsvg --with-pangocairo.
Generate
rake yard
Reading
open doc/frames.html
ERDs
To view the ERDs, which you can't see on rubydoc.info, you can look
at the docs for Metasploit::Credential
open doc/Metasploit/Credential.html
Installation
Add this line to your application's Gemfile:
gem 'metasploit-credential'
And then execute:
$ bundle
This gem's Rails::Engine is not required automatically. You'll need to also add the following to your config/application.rb:
require 'metasploit/credential/engine'
Or install it yourself as:
$ gem install metasploit-credential
Net::SSH
Metasploit::Credential::SSHKey depends on 'net/ssh', but metasploit-credential does not declare the net-ssh gem
as a runtime dependency because metasploit-framework includes
its own version of 'net/ssh' which would
conflict with the gem.
If you're not using metasploit-framework, then you need add the net-ssh to your Gemfile:
Metasploit modules may authenticate to services and retrieve temporary access tokens that allow future access to a service. For instance, cookies, JSON Web Tokens (JWT), Kerberos Tickets, OAuth, tokens etc. These values may be extracted from a compromised target, or generated with valid user/credentials.
Currently Metasploit-Credential does not offer a model for persisting these temporary access values that support future retrieval, or tracking the metadata for start/end/expiry information.
Example Values
Below is a high level summary of the types of temporary access values which can be looted from a compromised system, or retrieved from a service after authenticating.
The common themes for data requirements are:
The token itself that is used with the service
Time information - such as not-valid-before and not-valid-after times
Client/Server/Service information
Token status - valid/invalid/expired
An associated refresh token
Cookies
Generated when interacting with an HTTP service. Often an opaque value which the server can use at a later point of time, i.e. it may be the name of a randomly generated file on disk, or a lookup value in a database.
The expiry metadata may be returned to the user in an HTTP response header, but not always:
Service Principal Name (SPN) - Forest unique string. Associates a service to a service logon account.
The SPN is set on a user pr computer object via the AD Schema. Generally in the form <service class>/<host><realm>:<port>/<service name>.
A service can have multiple SPNs. Viewable on a Windows DC with setspn -q */*.
Key Distribution Center (KDC) - Performs authentication and creates tickets
Data Requirements
Persisting the following data is required:
Ticket granting tickets (TGT) - Requested after using the kerberos encryption key to prove identity
Service Tickets (TGS) - Used to prove authenticate with a target system such as SMB etc.
There should be support for:
Finding kerberos TGS/TGT tickets based on workspace, host (kdc), username (case insensitive), realm, sname (i.e. the kdc krbtgt/host.realm, or a service cifs/host.realm), auth time
Kerberos Tickets are associated with a Client, SPN, Realm, and have different metadata for expiry/usage times:
Generate Kerberos Encryption key from user credentials
Persisted and stored for later use in a keytab file for wireshark decryption
Requested with sname = “krbtgt/#{realm}”
AS_REP
Stored for later usage to request future service tickets
Step 2. Request Service Ticket
TGS_REQ
Use the TGT from Step 1
Specify SPN (Service principal name), i.e. cifs/host.realm.local
TGS_REP
Receive new TGS which we can use with a service
Step 3. Interact with service
AP_REQ
Send the service ticket
AP_REP
Success/Failure information
sequenceDiagram
participant msf as metasploit
participant kdc as Kerberos
participant smb as smb
Note over msf,kdc: 1) Request Ticket Granting Ticket - TGT
msf->>kdc: AS_REQ<br >encKey = EncKeyFor(user, pass, realm)<br >sname = krbtgt/realm
kdc->>msf: AS_REP<br >TGT
Note over msf,kdc: 2) Request Service Ticket - TGS
msf->>kdc: TGS_REQ<br>Ticket<br>spn=cifs/host.domain.local
kdc->>msf: TGS_REP<br>TGS
Note over msf,kdc: 3) Request Access
msf->>smb: AP_REQ<br>Service Ticket
smb->>msf: AP_REP
Original metasploit-credential approach
Kerberos ticket persistence originally leveraged the creds API, however it was deemed to not be viable. For instance - after running the winrm_login module this results in the following creds output:
Unfortunately it's not always possible to correlate a TGS request to the service in question. i.e. in the scenario of
the user running the admin/kerberos/get_ticket module with run verbose=true rhosts=10.0.0.24 domain=mylab.local user=serviceA password=123456 action=GET_TGS spn=custom_spn/dc02.mylab.local impersonate=Administrator
Benefits:
Tgt/Tgs information appears as part of the creds command by default
Easy to iterate on, and we can add a separate klist command implementation later
Easier to integrate with Pro
Shortcomings:
Can't invalidate private information, i.e. due to tickets expiring or being rejected from a KDC etc.
Noise in private key information
Privates have a single data field which is assumed to be a string. It's not possible to add
additional fields due to the current rails sti approach (single table inheritance). Which requires a workaround of using rail's serialize to store JSON blobs,
and re-inventing active record's field validation.
Related to the above; The default search capabilities for private creds assumes string and break on serialized json blobs
Not everyone wants to persist/reuse keys/tickets when calling kerberos authentication, requiring hack-y "do not persist" and "do not use cache" flags
No way to search directly via the database for SPN
When running the creds command there's not a correlation between the SPN and the target/host that it can be used against
Will require extra changes to Pro as part of MVP to not break the UI
Current Implementation
Metasploit currently stores Kerberos tickets in loot, and provides a simplified interface for interacting with these persisted values:
The ticket metadata is stored in the 'info' field as a serialized JSON structure (code):
Status
Realm
Client
Server
The original user/password is stored in the creds table against the target service - such as SMB. However, it should really be be stored against Kerberos:
OAuth 2.0 uses the concept of Access tokens, but not does not define a specific format - but can be JWT tokens or opaque blobs.
In OAuth 2.0, Refresh Tokens also exist which can be used to request an additional token after an expiry has surpassed.
Additional context/domain knowledge
Metasploit::Credential::Core is a glue object between the various objects in metasploit-credential - here's the rendered version of the outdated credential.graffle file:
Core - Glue object. Core credential that combines {#private}, {#public}, and/or {#realm} so that {Metasploit::Credential::Private} or {Metasploit::Credential::Public} that are gathered from a {Metasploit::Credential::Realm} are properly scoped when used
Public - A publicly disclosed credential, i.e. a username
Private - A private credential is any credential that should not be publicly disclosed, such as a {Metasploit::Credential::Password password}, password hash, or key file.
Context - Was renamed to Realm
Origin - Where the credentials came from, i.e. session/import/crackedpassword/manual/service
Login - The use of a {#core core credential} against a {#service service}
Realm - The realm in which a {Metasploit::Credential::Public} can be used to authenticate or from which a {Metasploit::Credential::Private} was looted.
metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::DBManager Traceback (most recent call last): 23: from /usr/bin/msfconsole:21:in
'
22: from /usr/bin/msfconsole:21:in require' 21: from /usr/share/metasploit-framework/lib/msf/core/payload_generator.rb:2:in <top (required)>'
20: from /usr/share/metasploit-framework/lib/msf/core/payload_generator.rb:2:in require' 19: from /usr/share/metasploit-framework/lib/msf/core/payload/apk.rb:3:in <top (required)>'
18: from /usr/share/metasploit-framework/lib/msf/core/payload/apk.rb:3:in require' 17: from /usr/share/metasploit-framework/lib/msf/core.rb:44:in <top (required)>'
16: from /usr/share/metasploit-framework/lib/msf/core.rb:44:in require' 15: from /usr/share/metasploit-framework/lib/msf/core/db_manager.rb:24:in <top (required)>'
14: from /usr/share/metasploit-framework/lib/msf/core/db_manager.rb:66:in <class:DBManager>' 13: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:115:in optionally_include_metasploit_credential_creation'
12: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:68:in optionally_include_metasploit_credential_creation' 11: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:22:in optionally'
10: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:22:in require' 9: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/metasploit-credential-3.0.4/lib/metasploit/credential.rb:11:in <top (required)>'
8: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/metasploit-credential-3.0.4/lib/metasploit/credential.rb:11:in require' 7: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/metasploit_data_models-3.0.10/lib/metasploit_data_models.rb:15:in <top (required)>'
6: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/metasploit_data_models-3.0.10/lib/metasploit_data_models.rb:15:in require' 5: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/activerecord-4.2.11.3/lib/active_record.rb:27:in <top (required)>'
4: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/activerecord-4.2.11.3/lib/active_record.rb:27:in require' 3: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/arel-6.0.4/lib/arel.rb:14:in <top (required)>'
2: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/arel-6.0.4/lib/arel.rb:14:in require' 1: from /usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/arel-6.0.4/lib/arel/visitors.rb:6:in <top (required)>'
/usr/share/metasploit-framework/vendor/bundle/ruby/2.7.0/gems/arel-6.0.4/lib/arel/visitors.rb:6:in require': cannot load such file -- arel/visitors/mysql (LoadError) 13: from /usr/bin/msfconsole:21:in '
12: from /usr/bin/msfconsole:21:in require' 11: from /usr/share/metasploit-framework/lib/msf/core/payload_generator.rb:2:in <top (required)>'
10: from /usr/share/metasploit-framework/lib/msf/core/payload_generator.rb:2:in require' 9: from /usr/share/metasploit-framework/lib/msf/core/payload/apk.rb:3:in <top (required)>'
8: from /usr/share/metasploit-framework/lib/msf/core/payload/apk.rb:3:in require' 7: from /usr/share/metasploit-framework/lib/msf/core.rb:44:in <top (required)>'
6: from /usr/share/metasploit-framework/lib/msf/core.rb:44:in require' 5: from /usr/share/metasploit-framework/lib/msf/core/db_manager.rb:24:in <top (required)>'
4: from /usr/share/metasploit-framework/lib/msf/core/db_manager.rb:66:in <class:DBManager>' 3: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:115:in optionally_include_metasploit_credential_creation'
2: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:68:in optionally_include_metasploit_credential_creation' 1: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:20:in optionally'
/usr/share/metasploit-framework/lib/metasploit/framework/require.rb:25:in rescue in optionally': undefined method without' for #Bundler::Settings:0x000055c543fa9ef8 (NoMethodError)
`
We would like an easy way of persisting AWS SECRET_ACCESS_KEY / ACCESS_KEY_ID / REGION information in Metasploit's database. We would need similar mechanism for GCP/Azure.
I'm writing a new juniper module based on the cisco one, I've run in to the problem where saving a credential bombs. The first line of this output is a print of self.fullname for debugging.
I was thinking that it would be awesome if you could preload the db with a few password list hashes kinda like john.pot. Then when you grab hashes the easy ones would be cracked waiting for you instantly without having to submit them to brute forcing. Mostly thinking of ntlm.
Ditto default passwords for things like oracle(if you have sqli into db rather than bruted login) or sap. As default pass lists for specific services arent big could potentially include in msf?
Just pondering if NTLM hash should be split into its component parts. For example RDP PTH with XFreeRDP accepts only the NTLM hash. Not sure if I can think of any captures where you don't get a blank LM hash but I expect it may occur at some point. Or just a way to grab them out from the object to pass neatly to other things without having to split them etc.
Comments suggest that it is used only for SMB but that's not accurate ;)
lm_hash_present? logic is wrong if the entire password is blank?
Note: I have only looked at the model and don't really know how this all works at the moment
Update metasploit::credential::core to contain references to services where the credential can be used against.
I think this metadata is different to metasploit::credential::login - which verifies whether the creds works or not, versus this feature request of allowing cores to differentiate between where creds came from and where they could be used against (verified or not)
Context:
The requirement originally came when adding support for Kerberos tickets #165 - which allows you to authenticate with kerberos, and receive a ticket that can be used against a different target system.
This scenario also comes up when running post modules against targets, i.e.:
a .env file containing database credentials that exist on a different service to the origin that the creds were found
Finding ssh creds on a compromised host that should work against known targets, but they haven't been verified
I just opened kali, I've been using msfconsole without issues the last days but know I can't open the console.
Executing “sudo msfdb init && msfconsole”
[i] Database already started
[i] The database appears to be already configured, skipping initialization
metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::DBManager
Traceback (most recent call last):
13: from /usr/bin/msfconsole:48:in <main>' 12: from /usr/bin/msfconsole:48:in require'
11: from /usr/share/metasploit-framework/lib/msf/core/payload_generator.rb:2:in <top (required)>' 10: from /usr/share/metasploit-framework/lib/msf/core/payload_generator.rb:2:in require'
9: from /usr/share/metasploit-framework/lib/msf/core/payload/apk.rb:3:in <top (required)>' 8: from /usr/share/metasploit-framework/lib/msf/core/payload/apk.rb:3:in require'
7: from /usr/share/metasploit-framework/lib/msf/core.rb:44:in <top (required)>' 6: from /usr/share/metasploit-framework/lib/msf/core.rb:44:in require'
5: from /usr/share/metasploit-framework/lib/msf/core/db_manager.rb:24:in <top (required)>' 4: from /usr/share/metasploit-framework/lib/msf/core/db_manager.rb:66:in class:DBManager'
3: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:115:in optionally_include_metasploit_credential_creation' 2: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:68:in optionally_include_metasploit_credential_creation'
1: from /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:20:in optionally' /usr/share/metasploit-framework/lib/metasploit/framework/require.rb:25:in rescue in optionally': undefined method `without' for #Bundler::Settings:0x0000561d16167608 (NoMethodError)
Did you mean? with_options
As it is linking to the original credential core object I would expect the Realm to be populated when using create_cracked_credential however a specific Realm: nil is passed in :(
For example, I've experienced it (unique_private_metasploit_credential_cores) while validating this PR: rapid7/metasploit-framework#4493 It happens when trying to create two different users with the same password. I think the duplication error is unexpected on a situation like that. But maybe there is some issue while using metasploit-credential. Please let me know if it's the case and I'll fix.
Another example, on rapid7/metasploit-framework#4392, when running the module two times. The second one will generate a unique_public_metasploit_credential_cores violation. Also unexpected I think.
Basically, trying to import a 8192bits (or longer) RSA key triggers the next error:
[-] Post failed: ActiveRecord::StatementInvalid PG::ProgramLimitExceeded: ERROR: index row size 6408 exceeds maximum 2712 for index "index_metasploit_credential_privates_on_type_and_data"
HINT: Values larger than 1/3 of a buffer page cannot be indexed.
Consider a function index of an MD5 hash of the value, or use full text indexing.
: INSERT INTO "metasploit_credential_privates" ("created_at", "data", "type", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"
[-] Call stack:
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql_adapter.rb:810:in `get_last_result'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql_adapter.rb:810:in `exec_cache'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql/database_statements.rb:139:in `block in exec_query'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract_adapter.rb:442:in `block in log'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract_adapter.rb:437:in `log'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql/database_statements.rb:181:in `exec_insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:97:in `insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:76:in `insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:513:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/attribute_methods/dirty.rb:78:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:306:in `block in _create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:373:in `_run__3811821103018841406__create__callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:80:in `run_callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:306:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/timestamp.rb:57:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:481:in `create_or_update'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:302:in `block in create_or_update'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:383:in `_run__3811821103018841406__save__callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:80:in `run_callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:302:in `create_or_update'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:103:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/validations.rb:51:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/attribute_methods/dirty.rb:32:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:270:in `block (2 levels) in save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:330:in `block in with_transaction_returning_status'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:203:in `block in transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `within_new_transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:203:in `transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:209:in `transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:327:in `with_transaction_returning_status'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:270:in `block in save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:285:in `rollback_active_record_state!'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:269:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:34:in `create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:121:in `block in create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:270:in `scoping'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:121:in `create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:133:in `first_or_create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:391:in `block in create_credential_private'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:532:in `retry_transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:383:in `create_credential_private'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:130:in `create_credential'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/lib/msf/core/auxiliary/report.rb:34:in `create_credential'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:81:in `block (2 levels) in download_loot'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:59:in `each'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:59:in `block in download_loot'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:46:in `each'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:46:in `download_loot'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:41:in `run'
[*] Post module execution completed
msf post(ssh_creds) >
Steps to Reproduce
In order to reproduce:
Set up a linux target machine. I've used Ubuntu server 12.04
Generate a ssh 8192 bits rsa key. No passphrase. Save it in the default location ~/.ssh
juan@ubuntu:~$ ssh-keygen -b 8192 -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/juan/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/juan/.ssh/id_rsa.
Your public key has been saved in /home/juan/.ssh/id_rsa.pub.
The key fingerprint is:
59:53:9d:19:be:51:ef:d2:2c:80:d7:46:69:da:db:60 juan@ubuntu
The key's randomart image is:
+--[ RSA 8192]----+
| ..o=.|
| o +*..|
| + o+= .|
| o o.oE* |
| S .+++|
| .o.|
| |
| |
| |
+-----------------+
Get a linux shell session on the target. Just execute an elf with the shell payload. The user should have access to the ~/.ssh/id_rsa generated in the step above, of course :)
msf post(ssh_creds) > use exploit/multi/handler
msf exploit(handler) > run
[*] Started reverse handler on 172.16.158.1:4444
[*] Starting the payload handler...
[*] Sending stage (36 bytes) to 172.16.158.136
[*] Command shell session 3 opened (172.16.158.1:4444 -> 172.16.158.136:34002) at 2015-06-29 13:24:17 -0500
^Z
Background session 3? [y/N] y
use post/multi/gather/ssh_creds on the new session to reproduce the crash.
msf post(ssh_creds) > set session 3
session => 3
msf post(ssh_creds) > workspace
default
report_auth_info_test
glassfish
* ssh_creds
msf post(ssh_creds) > run
[*] Finding .ssh directories
[*] Looting 1 directories
[+] Downloaded /home/juan/.ssh/id_rsa -> /Users/jvazquez/.msf4/loot/20150629132444_ssh_creds_172.16.158.136_ssh.id_rsa_436134.txt
HINT: Values larger than 1/3 of a buffer page cannot be indexed.
Consider a function index of an MD5 hash of the value, or use full text indexing.
: INSERT INTO "metasploit_credential_privates" ("created_at", "data", "type", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"
[-] Call stack:
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql_adapter.rb:810:in `get_last_result'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql_adapter.rb:810:in `exec_cache'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql/database_statements.rb:139:in `block in exec_query'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract_adapter.rb:442:in `block in log'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract_adapter.rb:437:in `log'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/postgresql/database_statements.rb:181:in `exec_insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:97:in `insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:76:in `insert'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:513:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/attribute_methods/dirty.rb:78:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:306:in `block in _create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:373:in `_run__3811821103018841406__create__callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:80:in `run_callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:306:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/timestamp.rb:57:in `_create_record'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:481:in `create_or_update'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:302:in `block in create_or_update'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:383:in `_run__3811821103018841406__save__callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activesupport-4.0.13/lib/active_support/callbacks.rb:80:in `run_callbacks'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/callbacks.rb:302:in `create_or_update'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:103:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/validations.rb:51:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/attribute_methods/dirty.rb:32:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:270:in `block (2 levels) in save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:330:in `block in with_transaction_returning_status'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:203:in `block in transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `within_new_transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:203:in `transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:209:in `transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:327:in `with_transaction_returning_status'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:270:in `block in save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:285:in `rollback_active_record_state!'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/transactions.rb:269:in `save'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/persistence.rb:34:in `create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:121:in `block in create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:270:in `scoping'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:121:in `create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/activerecord-4.0.13/lib/active_record/relation.rb:133:in `first_or_create'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:391:in `block in create_credential_private'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:532:in `retry_transaction'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:383:in `create_credential_private'
[-] /Users/jvazquez/.rvm/gems/ruby-2.1.6@metasploit-framework/gems/metasploit-credential-1.0.0/lib/metasploit/credential/creation.rb:130:in `create_credential'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/lib/msf/core/auxiliary/report.rb:34:in `create_credential'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:81:in `block (2 levels) in download_loot'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:59:in `each'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:59:in `block in download_loot'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:46:in `each'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:46:in `download_loot'
[-] /Users/jvazquez/Projects/Code/metasploit-framework/modules/post/multi/gather/ssh_creds.rb:41:in `run'
[*] Post module execution completed
msf post(ssh_creds) > [*] 172.16.158.136 - Command shell session 3 closed. Reason: Died from EOFError
Since @dmaloney-r7 added the reporting to the module ( rapid7/metasploit-framework@90c63ef ) I bet the reporting of rsa keys as privates is intended and should be supported.
When running the crack_windows auxiliary module in metasploit a key error is thrown. The :address option should be set with a default option to avoid this error condition.
This seems more relevant than msf side for this issue.
The example smb login code in electro seems to try both admin$ and ipc$ on failure. I fear this will count towards a lockout policy which the user will be unaware of. The current module requires an option to be set to perform the admin check