Post

The Configuration of Hades Dog

The Configuration of Hades Dog

Overview

Now, I’ve done a few boxes so far in Hack The Box and I’ve occasionally had to use kerberos to get a ticket. And it was a realm (yeah, I did that) of complete fuzziness for me as to how to properly generate the correct configuration to actually get the ticket. I’ve watched a complete deep dive about how the authentication mechanism works in Keberos, the whole flow: mermaid_seq

and how small aspects of this process are exploitable in certain situations. However, the more practical use-case within pen-testing of actually dealing with the configuration to initialize it, I have just been fumbling along and it’s finally bothered me off enough to learn. So, I’m writing this down hopefully for anyone else to see, because you’ll come across some situation where nxc smb --generate-krb5-file won’t work because you need kerberos to authenticate, and then you cry because you have no idea what the domain realm is supposed to be or what comes after that.

The File

They typically look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[libdefaults]
    default_realm = MY.TLD
    dns_lookup_realm = true
    dns_lookup_kdc = true

[realms]
    MY.TLD = {
        kdc = DC.my.tld
        admin_server = DC.my.tld
        default_domain = DC.my.tld
    }

[domain_realm]
    my.tld = MY.TLD
    .my.tld = MY.TLD

The Situation

Let’s say you had a nice nmap scan with the typical scripts run and you get an output like this:

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
88/tcp    open  kerberos-sec  syn-ack Microsoft Windows Kerberos (server time: 2025-07-09 07:34:53Z)
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: voleur.htb0., Site: Default-First-Site-Name)
593/tcp   open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
3268/tcp  open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: voleur.htb0., Site: Default-First-Site-Name)
5985/tcp  open  http          syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open  msrpc         syn-ack Microsoft Windows RPC
49668/tcp open  msrpc         syn-ack Microsoft Windows RPC
62028/tcp open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
62029/tcp open  msrpc         syn-ack Microsoft Windows RPC
62041/tcp open  msrpc         syn-ack Microsoft Windows RPC
62046/tcp open  msrpc         syn-ack Microsoft Windows RPC
62060/tcp open  msrpc         syn-ack Microsoft Windows RPC

Host script results:
| smb2-time: 
|   date: 2025-07-09T07:35:47
|_  start_date: N/A
|_clock-skew: 7h59m55s
| smb2-security-mode: 
|   3.1.1: 
|_    Message signing enabled and required
| p2p-conficker: 
|   Checking for Conficker.C or higher...
|   Check 1 (port 48495/tcp): CLEAN (Timeout)
|   Check 2 (port 28595/tcp): CLEAN (Timeout)
|   Check 3 (port 60782/udp): CLEAN (Timeout)
|   Check 4 (port 34236/udp): CLEAN (Timeout)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Jul  8 13:36:34 2025 -- 1 IP address (1 host up) scanned in 233.16 seconds

The observant of you may notice this a HackTheBox box, don’t worry there won’t be any spoilers other than using the default credentials provided, but this was the impetus for me to learn, so I don’t think there’s a better example. As you can see, we have some common Microsoft AD services, and a domain being referenced: voleur.htb0 Let’s clear up something, the 0 probably is irrelevant, it’s not a valid TLD.

1
2
3
4
5
6
7
8
9
10
11
1.2 The ASCII label must be a valid host name, as
specified in the technical standards DOD Internet
Host Table Specification (RFC 952), Requirements for
Internet Hosts — Application and Support (RFC
1123), and Application Techniques for Checking
and Transformation of Names (RFC 3696),
Internationalized Domain Names in Applications
(IDNA)(RFCs 5890-5894), and any updates thereto.
This includes the following:
    1.2.1 The ASCII label must consist entirely of letters
    (alphabetic characters a-z),

And we verify it with ldapsearch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ldapsearch -x -H 'ldap://10.10.11.76' -b "" -s base namingcontexts
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: namingcontexts
#
#
dn:
namingcontexts: DC=voleur,DC=htb
namingcontexts: CN=Configuration,DC=voleur,DC=htb
namingcontexts: CN=Schema,CN=Configuration,DC=voleur,DC=htb
namingcontexts: DC=DomainDnsZones,DC=voleur,DC=htb
namingcontexts: DC=ForestDnsZones,DC=voleur,DC=htb
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1

We see the DC=voleur, DC=htb so the actual domain is voleur.htb. So where’s the 0 coming from? nmap has a service probe that runs with the -sV option. The list of regexes actually are located typically: /usr/share/nmap/nmap-service-probes You can open the file up and search for Domain: it should be around line 14745 and look a little something like this:

1
match ldap m|^0\x84\0\0..\x02\x01.*dsServiceName1\x84\0\0\0.\x04.CN=NTDS\x20Settings,CN=([^,]+),CN=Servers,CN=([^,]+),CN=Sites,CN=Configuration,DC=([^,]+),DC=([^,]+)0\x84\0|s p/Microsoft Windows Active Directory LDAP/ i/Domain: $3.$4, Site: $2/ o/Windows/ h/$1/ cpe:/o:microsoft:windows/a

So it’s capturing the dsServiceName query and capturing someoutput and it seems it’s precisely matching a zero at the end, but we’re still capturing it? Perhaps it’s in that query and the AD is just poorly configured?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ldapsearch -x -H 'ldap://10.10.11.76' -b "" -s base  dsServiceName
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: dsServiceName
#

#
dn:
dsServiceName: CN=NTDS Settings,CN=DC,CN=Servers,CN=Default-First-Site-Name,CN
 =Sites,CN=Configuration,DC=voleur,DC=htb

# search result
search: 2
result: 0 Success

Nope. So let’s look at some packet captures.

1
2
3
4
5
6
7
8
9
10
11
12
13
tshark -i tun0 -f "port 389"
# <snip>
0050  7e 04 0d 64 73 53 65 72 76 69 63 65 4e 61 6d 65   ~..dsServiceName
0060  31 84 00 00 00 69 04 67 43 4e 3d 4e 54 44 53 20   1....i.gCN=NTDS
0070  53 65 74 74 69 6e 67 73 2c 43 4e 3d 44 43 2c 43   Settings,CN=DC,C
0080  4e 3d 53 65 72 76 65 72 73 2c 43 4e 3d 44 65 66   N=Servers,CN=Def
0090  61 75 6c 74 2d 46 69 72 73 74 2d 53 69 74 65 2d   ault-First-Site-
00a0  4e 61 6d 65 2c 43 4e 3d 53 69 74 65 73 2c 43 4e   Name,CN=Sites,CN
00b0  3d 43 6f 6e 66 69 67 75 72 61 74 69 6f 6e 2c 44   =Configuration,D
00c0  43 3d 76 6f 6c 65 75 72 2c 44 43 3d 68 74 62 30   C=voleur,DC=htb0
00d0  84 00 00 00 10 02 01 02 65 84 00 00 00 07 0a 01   ........e.......
00e0  00 04 00 04 00                                    .....
# </snip>

Clearly it ends in that same pattern: 0\x84\0 So it seems the regex implementation is doing something interesting with the + and unecessarily capturing the trailing 0, even though we don’t want it. I won’t lie it’s kind of confusing, because it is somehow ‘capturing’ the 0 but still using it as a delimiter. I’m unaware of how this behavior occurs, nmap apparently uses its own modified version of PCRE regex, which might hold the key to this behavior.

I do know that adding a simple ? to the end of the + allows for the correct domain parsing.

1
match ldap m|^0\x84\0\0..\x02\x01.*dsServiceName1\x84\0\0\0.\x04.CN=NTDS\x20Settings,CN=([^,]+),CN=Servers,CN=([^,]+),CN=Sites,CN=Configuration,DC=([^,]+),DC=([^,]+?)0\x84\0|s p/Microsoft Windows Active Directory LDAP/ i/Domain: $3.$4, Site: $2/ o/Windows/ h/$1/ cpe:/o:microsoft:windows/a
1
nmap -sV -p 389 10.10.11.76
1
2
3
4
5
6
7
 Starting Nmap 7.97 ( https://nmap.org ) at 2025-07-09 11:37 -1000
 Nmap scan report for voleur.htb (10.10.11.76)
 Host is up (0.19s latency).

PORT    STATE SERVICE VERSION
389/tcp open  ldap    Microsoft Windows Active Directory LDAP (Domain: voleur.htb, Site: Default-First-Site-Name)
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows

So I threw in a pull request. Hopefully it will get fixed.

So indeed, the 0 is a lie. Do not believe it.

What we were doing again? Oh right Kerberos Configuration. So, we got this scan and verified the correct domain is voleur.htb Let’s try to use nxc to generate the kerberos config:

1
nxc smb 10.10.11.76 --generate-krb5 custom_krb.conf -u ryan.naylor -p HollowOct31Nyt --verbose
1
2
3
4
5
6
7
8
9
[13:07:12] INFO     Socket info: host=10.10.11.76, hostname=10.10.11.76, kerberos=False, ipv6=False, link-local ipv6=False                                                                                                    connection.py:165
           INFO     Creating SMBv3 connection to 10.10.11.76                                                                                                                                                                         smb.py:606
[13:07:13] INFO     Creating SMBv1 connection to 10.10.11.76                                                                                                                                                                         smb.py:575
           INFO     SMBv1 disabled on 10.10.11.76                                                                                                                                                                                    smb.py:598
[13:07:14] INFO     Resolved domain: 10.10.11.76 with dns, kdcHost: 10.10.11.76                                                                                                                                                      smb.py:321
SMB         10.10.11.76     445    10.10.11.76      [*]  x64 (name:10.10.11.76) (domain:10.10.11.76) (signing:True) (SMBv1:False) (NTLM:False)
           INFO     Creating SMBv3 connection to 10.10.11.76                                                                                                                                                                         smb.py:606
SMB         10.10.11.76     445    10.10.11.76      [-] 10.10.11.76\ryan.naylor:HollowOct31Nyt STATUS_NOT_SUPPORTED (The request is not supported.)

Oh no! It’s not supported! Now we have to learn. (It does actually generate the configuration, but it just sticks the ip everywhere and is useless)

[libdefaults]

default_realm

It specifies the default behaviors for the kerberos libraries, it, it’s only for default behavior so it technically isn’t required. It makes usage quite easier eg. If we don’t specify a default_realm when we kinit, the default_realm will be used, otherwise we have to do is kinit [email protected]

  • We still need to DEFINE our realm in the lower config!

dns_lookup_realm

Allows kerberos to use DNS to map domain names to kerberos realms eg. voleur.htb -> VOLEUR.HTB

  • Only if the appropriate DNS txt records are set up and configured correctly on the target domain

dns_lookup_kdc

Allows keberos to use DNS SRV records to find Key Distribution Centers (KDC’s), which will eliminate the need to specify the kdc field when we define our realms.

  • This is only if those DNS SRV records exist, which may not always be the case. They would look like _kerberos._tcp.voleur.htb

[realms]

This is where you define the realms which in kerberos’ typical convention is the capitalized domain name, in our case it’s VOLEUR.HTB This was also a confusing thing for me, as why does capitalization matter? I always have had this association in my mind that kerberos tightly associated with windows, as that was the context I have almost always seen it. However the origins date back before windows even gained a foothold. And the reason they chose capitalization for realms is just convention. So we always assume the convention until we have conflicting information otherwise. Because we can even have VolEuR.HtB if we wanted, but people don’t configure things that way.

REALM.DOMAIN

the realm name corresponds to the target domain name eg. voleur.htb

kdc

Ideally stick the $ip:$kerb_port here to be explicit. kdc = 10.10.11.76:88

default_domain

Maps the realm back to a domain_name, the oppost of what we do below. default_domain = voleur.htb

[domain-realm]

This is the explicit mapping of the domains to the kerberos realm You typically do 2: voleur.htb = VOLEUR.HTB .voleur.htb = VOLEUR.HTB The second one is for any extra domains, view it as *.voleur.htb

Final Config

So if you have 10.10.11.76 voleur.htb in your /etc/hosts file and the appropriate DNS records are supported by the box, this would be all you need.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[libdefaults]
    default_realm = VOLEUR.HTB

    dns_lookup_realm = true

    dns_lookup_kdc = true

[realms]

    VOLEUR.HTB = {}

[domain_realm]
    .voleur.htb = VOLEUR.HTB
    voleur.htb = VOLEUR.HTB

Otherwise, you need some more explicit mapping, which you probably should for CTF’s (you could set them the two false’s to true, but it’s better to be explicit for intended behavior)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[libdefaults]
    default_realm = VOLEUR.HTB

    dns_lookup_realm = false

    dns_lookup_kdc = false

[realms]
    VOLEUR.HTB = {
        kdc = 10.10.11.76:88
        default_domain = voleur.htb
         }

[domain_realm]
    .voleur.htb = VOLEUR.HTB
    voleur.htb = VOLEUR.HTB

You can add a few the admin_server as well in the realms section, but for basic auth that’s not necessary and this should be enough to give you enough of an “Oh this is how this works”, to delve deeper if you have to.

This mainly was caused by a lot of confusion I received from nmap, paired with only a extremely surface level look at the configuration file. It goes to show that understanding exactly what your tools are doing is a far more valuable skill than just reading the output of the tool and it’s interesting how a tool’s very mild innaccuracy can cause a host of confusion when your understanding isn’t as confident as it should be.

I also made a script that generates a krb5config, that uses ldapsearch, so it should be useful for any other kerberos ventures.

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