Urgences 24 sur 7 – (888) 287-5858   Connexion au Portail TitanSupport    Contactez-nous      Blogue

The story of a privileged handle…

 

Context

As virtualization technology continues to become the corporate standard, the popularity of Virtual Desktop Infrastructure (VDI) in large enterprises has been increasing. These automated environments can provision desktops and applications from the internal and external network on top of virtualization technology without an IT administrator’s input. There are many components involved in a VDI infrastructure, but one specifically caught our attention on a customer mandate back in September 2017: the Windows « vmwagent.exe ».

On this particular mandate, we had to escape the VDI environment with developer access and without local administrative access. The customer had done a great job at image hardening; services, applications and operating systems were well configured and patched, with up-to-date antivirus software, behavior monitoring, and strong passwords. Faced with this situation, we decided to perform a quick look around with the popular Process Explorer from the SysInternals Suite. One of the many notable features we like about this tool is the ability to display opened handles per process.

We were shocked to find a privileged process handle in an unprivileged process! We had stumbled onto a potential vulnerability in the VMWare Horizon solution. Ultimately, we were able to exploit this to grant us local administrative privileges on all Windows desktops in the VDI. These results were then reported to VMWare.

Our goal therefore for this blog post is to deliver some background as well as technical details on the CVE-2017-4946 vulnerability. Hopefully we will be able to draw the attention of as many VMWare customers as possible and better explain the urgency of applying the new update, as stated in the VMSA-2018-0003 advisory.

We also want to urge as many security professionals to not overlook such vulnerabilities. They are easy to identify.

 

Handles in Windows

Each process in Windows has its own memory space in which various code, data, and metadata sections are mapped. A process cannot directly access resources outside of its memory space boundary. It needs a handle authorized by the kernel first.

The handle allocation protocol is simple, you declare what resource you want and what you intend to do with it. The kernel will then decide, based on the originating security token and other parameters, if it is authorized to allocate a handle. Once authorized, the process needs to use the handle for each action on the associated resource. The kernel will only allow actions that were previously authorized when the handle was given. Basically, this works like a session token in the web application world.

Here is a list of objects from which we can retrieve a handle:

Access token Change notification
Console input Console screen buffer
Desktop Event
File File mapping
Job Mailslot
Mutex Pipe
Process Registry Key
Semaphore Thread
Timer Transaction
Window Station

Details on MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251(v=vs.85).aspx

 

Identifying the vulnerability

In a VDI session, using Process Explorer, it took no time to realize that the « vmwagent.exe » process (6912) had an opened process handle to its parent process « v4pa_agent.exe » (1540). The lower pane of Process Explorer window, as displayed below, reveals the opened handle. The upper pane of the window shows that we were not authorized to access the « v4pa_agent.exe » process since it was running under the NT AUTHORITY\SYSTEM privileged account.

Our plan became obvious, if we could use that handle from our user-owned « vmwagent.exe » process and interact with the privileged parent process « v4pa_agent.exe », we could leverage code execution under the security context of the system.

Image 1 – Process Explorer capture showing the privileged handle in an unprivileged process.

 

The only missing element was to confirm the handle’s granted access rights. Since we were the owner of the « vmwagent.exe » process which holds the handle we wanted, we could dump the process memory using the minidump feature of Process Explorer and analyze it with the Windows Debugger as shown below.

Image 2 – WinDBG capture showing the privileged handle granted access rights. 

 

At this point, we confirmed that the vulnerability was exploitable. Due to time constraints, we decided to develop the exploit directly on the vulnerable system. Visual Studio was available, we were given developer access, remember?!

 

Exploiting a privileged process handle

There are multiple ways to exploit a privileged process handle, but first we needed to acquire the handle! We could either inject a library in the « vmwagent.exe » process itself and use the handle from there or use the DuplicateHandle call. Once acquired, we could use the privileged process handle to hijack the execution flow of the parent process: allocating memory and altering protections was possible with VirtualAllocEx and VirtualProtectEx calls. This done, we examined possible exploits.

Below is a partial list of our options:

  • Perform a DLL injection technique targeting the parent process with CreateRemoteThread call.
  • Overwrite a callback in the parent process. (Note that this technique could fail under the Control Flow Guard (CFG) security mechanism. Unless you attack CFG directly.)
  • Hook a common library function with raw instruction patching.

In this environment, CreateRemoteThread was not possible and a callback overwrite would be too risky, so we chose to go with a good old hook.

The function we decided to hook was RtlInitUnicodeString in NtDll.dll library. This function initializes UNICODE_STRING structure from a wide char string (PCWSTR). It is often called and was our best bet on hijacking execution flow. We could find its address easily in our own process with the GetProcAddress function. NtDll.dll shares the same base address across all processes until reboot.

Image 3 – Attack scenario representation. Processes from left to right are vmwagent.exe, exploit.exe and v4pa_agent.exe.

 

Finally, the exploit shellcode used for the payload was straightforward. We only wanted to allow a simple LoadLibraryA call to load a malicious library into the process. At this point, we could have used any type of shellcode, but we found it useful to have a « static » shellcode. It would allow us to only have to rebuild a library to execute our desired code. Time not being on our side, we quickly allocated a full memory page for the shellcode and used the following offsets for dynamic values:

  • +0x0      => shellcode base
  • +0xF00 => Name of the library to load
  • +0xFF0 => Toggle bit (used to avoid calling LoadLibraryA on every call)
  • +0xFF8 => Address of LoadLibrary
;; (Poorly written) Exploit shellcode to call a function with 1 argument within process memory.
;; by Martin Lemay, GoSecure Inc. 2017

push rcx
push rdx
push rax
push rbx
call bridge
and rbx, 0xfffffffffffff000
mov rcx, qword ptr [rsp+0x20]
add rcx, 8
mov qword ptr [rsp+0x20], rcx
mov rax, qword ptr [rbx+0xff0]
cmp al, 1
je repair
mov qword ptr [rbx+0xff0], 1
mov rcx, rbx
add rcx, 0xf00
call qword ptr [rbx+0xff8]

repair:
  pop rbx
  pop rax
  pop rdx
  pop rcx
  xor eax,eax
  mov QWORD PTR [rcx+0x8],rdx
  mov WORD PTR [rcx+0x2],ax
  mov WORD PTR [rcx],ax
  jmp qword ptr [rsp]

bridge:
  pop rbx
  push rbx
  ret

After execution, we recovered the execution state and returned to the original RtlInitUnicodeString function. Improvements could be made at this point for a more stable and re-usable exploit across various Windows flavors and architectures, but in our case, it was more than enough for our needs: we had successfully exploited the vulnerability.

 

Conclusion

In the past months, we’ve encountered multiple instances of bad handle usage that went undetected by vendors. Note that we are not only seeing bad process handle usage, but also bad device handle usage that led to kernel privilege escalations.

Interestingly, this old attack vector is still not well understood in the industry. We hope this blog serves as an incentive for security professionals to not overlook this crucial attack vector on engagements and for developers to properly manage handles on Windows applications.

Farewell!

Détection et réponse gérées et étendues GoSecure TitanMC (MXDR)

Détection et réponse gérées et étendues GoSecure TitanMC (MXDR) Fondation

Gestion des vulnérabilités en tant que service GoSecure TitanMC (VMaaS)

Surveillance des événements liés aux informations de sécurité gérée GoSecure TitanMC (SIEM gérée)

Défense du périmètre gérée GoSecure TitanMC (pare-feu)

Détection et réponse des boîtes de messagerie GoSecure TitanMC (IDR)

Passerelle de messagerie sécurisée GoSecure TitanMC (SEG)

Modélisateur de menaces GoSecure TitanMC

Identity GoSecure TitanMC

Plateforme GoSecure TitanMC

Services de sécurité professionnels de GoSecure

Services de réponse aux incidents

Évaluation de la maturité de la sécurité

Services de confidentialité

Services PCI DSS

Services de piratage éthique

Opérations de sécurité

MicrosoftLogo

GoSecure MXDR pour Microsoft

Visibilité et réponse complètes au sein de votre environnement de sécurité Microsoft

CAS D'UTILISATION

Cyberrisques

Mesures de sécurité basées sur les risques

Sociétés de financement par capitaux propres

Prendre des décisions éclairées

Sécurité des données sensibles

Protéger les informations sensibles

Conformité en matière de cybersécurité

Respecter les obligations réglementaires

Cyberassurance

Une stratégie précieuse de gestion des risques

Rançongiciels

Combattre les rançongiciels grâce à une sécurité innovante

Attaques de type « zero-day »

Arrêter les exploits de type « zero-day » grâce à une protection avancée

Consolider, évoluer et prospérer

Prenez de l'avance et gagnez la course avec la Plateforme GoSecure TitanMC.

24/7 MXDR

Détection et réponse sur les terminaux GoSecure TitanMC (EDR)

Antivirus de nouvelle génération GoSecure TitanMC (NGAV)

Surveillance des événements liés aux informations de sécurité GoSecure TitanMC (SIEM)

Détection et réponse des boîtes de messagerie GoSecure TitanMC (IDR)

Intelligence GoSecure TitanMC

Notre SOC

Défense proactive, 24h/24, 7j/7

À PROPOS DE GOSECURE

GoSecure est un leader et un innovateur reconnu en matière de cybersécurité, pionnier de l'intégration de la détection des menaces au niveau des terminaux, du réseau et des courriels en un seul service de détection et réponse gérées et étendues (MXDR). Depuis plus de 20 ans, GoSecure aide ses clients à mieux comprendre leurs failles en matière de sécurité et à améliorer leurs risques organisationnels ainsi que leur maturité en matière de sécurité grâce aux solutions MXDR et aux services professionnels fournis par l'une des équipes les plus fiables et les plus compétentes de l'industrie.

CALENDRIER D’ÉVÉNEMENTS

DERNIER COMMUNIQUÉ DE PRESSE

BLOGUE GOSECURE

AVIS DE SÉCURITÉ

Urgences 24 sur 7 – (888) 287-5858