You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
Loading
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.
Another consideration: We would most likely want to do a better job of storing ADCS certs in Metasploit too for future use in modules
Edit: We'll want to track arbitrary metadata on the core itself, such as the template name or oids that aren't present in the pkcs12 itself, and sid, and potentially linking it with the loot metadata filepath so folk can use it from the file system
Edit Edit: If we add metadata to the login core objects (or whatever node), we'll need to make sure it's searchable. I don't believe that's currently supported. If we use metadata store as JSONB in postgres
Problem
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:
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:
Kerberos Tickets
Defined by https://www.rfc-editor.org/rfc/rfc4120
Kerberos tickets are used as part of authenticating with a Key Distribution Center, or extracted from memory with Kiwi etc.
The original proposal for persisting these values can be found in https://github.com/rapid7/metasploit-framework/blob/2b6cb50dc39998ab7747fd79546b31f4fff037d8/docs/metasploit-framework.wiki/Metasploit-Credential-Kerberos-Support-Proposal.md - inlined below for readability
Common Terminology:
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 */*
.Data Requirements
Persisting the following data is required:
There should be support for:
krbtgt/host.realm
, or a servicecifs/host.realm
), auth timeKerberos Tickets are associated with a Client, SPN, Realm, and have different metadata for expiry/usage times:
Scenarios
Persisting Ticket granting ticket - TGT
Context:
Can be used to request additional tickets from the KDC
Generally acquired by:
Example:
Ticket Granting Service - TGS
Context: Can be used with a real service (cifs/mssql/etc) for authentication
Generally acquired by:
Kerberos Authentication Overview
cifs/host.realm.local
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:What we would ideally want is:
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 withrun 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:
creds
command by defaultklist
command implementation laterShortcomings:
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.
creds
command there's not a correlation between the SPN and the target/host that it can be used againstCurrent 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):
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:
The TGT/TGS is additionally stored as loot:
Benefits:
loot
commandShortcomings:
store_loot
API can be used regardless of having a Metasploit database connectedcreds
commandJWT
Defined by https://www.rfc-editor.org/rfc/rfc7519
JWTs contain three base64 separated values. Example:
The three segments are:
JWTs contain claims for tracking expiry metadata - https://www.rfc-editor.org/rfc/rfc7519#section-4.1
OAuth tokens
Defined by https://www.rfc-editor.org/rfc/rfc6749
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:{#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 usedusername
{Metasploit::Credential::Password password}
, password hash, or key file.Context- Was renamed toRealm
{#core core credential}
against a{#service service}
{Metasploit::Credential::Public}
can be used to authenticate or from which a{Metasploit::Credential::Private}
was looted.The gem dependencies/hierarchy:
Gem overviews:
The text was updated successfully, but these errors were encountered: