Opened 2 years ago

Last modified 2 years ago

#1141 new Bug / Defect

Harden OpenVPN on Windows against generic DLL hijacking vulnerabilities

Reported by: Samuli Seppänen Owned by:
Priority: major Milestone:
Component: Building / Compiling Version:
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords:


This was originally reported to HackerOne by locu. Some modifications were made for Trac.


Programmers who need to import a DLL into their application would specify
its exact path prior to compilation (or if it was a Windows DLL, Windows would already know exactly where to find it by name). Once it had been found, Windows would validate its digital signature and then load it into the address space of the requesting application. In reality the Windows Loader typically does not validate the digital signature, it often has no idea where to find any given DLL (including a lot of its own system DLLs), and the average compiler/programmer specifies DLL imports by name, not path. The end result is a ubiquitous presence of DLL hijacking vulnerabilities in virtually every application written for Windows regardless of manufacturer.

More info at MSDN article.

Exploiting this vulnerability requires local admin-level privileges.


openvpn.exe is looking for 5 libraries in the program folder instead to looks at the correct path.

Module fwpuclnt.dll vulnerable at C:\Program Files\OpenVPN\bin\fwpuclnt.dll (real path: C:\WINDOWS\system32\fwpuclnt.dll)

Module bcrypt.dll vulnerable at C:\Program Files\OpenVPN\bin\bcrypt.dll (real path: C:\WINDOWS\system32\bcrypt.dll)

Module IPHLPAPI.DLL vulnerable at C:\Program Files\OpenVPN\bin\IPHLPAPI.DLL (real path: C:\WINDOWS\system32\IPHLPAPI.DLL)

Module ncrypt.dll vulnerable at C:\Program Files\OpenVPN\bin\ncrypt.dll (real path: C:\WINDOWS\system32\ncrypt.dll)

Module NTASN1.dll vulnerable at C:\Program Files\OpenVPN\bin\NTASN1.dll (real path: C:\WINDOWS\system32\NTASN1.dll)

Steps To Reproduce:

This can be reproduced by using a tailored DLL and EXE of your choice into C:\Program Files\OpenVPN\bin and run openvpn or openvpn-gui. (A proof of concept is available in the HackerOne report). Doing the above requires local admin-level privileges.


Modify the PE in order to specifies DLL imports by the absolute path. Suggestions from locu:

  • Ensure that the full path is hardcoded. Avoidusing relative paths for any resources.
  • Confirm that the imported DLL actually exists.
  • Ensure that imported functions are valid.
  • Ensure that the operating system is correct.
  • Utilize DLL redirection or a manifest. Recent versions of Visual Studio enable developers to create manifests to ensure that the loaded library is valid.


An attacker or a malware could exploit this vulnerability in order to eavesdrop communications, steal users credential or to maintain persistence on an infected system.
The malware can also bypass firewall rules without needing to touch the firewall configuration by camouflaging its own network activity into the processes.

Change History (5)

comment:1 Changed 2 years ago by Samuli Seppänen

I wonder if we'd have to stop offering the choice to install to a custom directory to really fix this. If we need to sign an external manifest file we could not modify any paths in it after the build has finished.

comment:2 Changed 2 years ago by Samuli Seppänen

As rozmansi said in today's community meeting we can't hardcode any of the DLL paths. Somebody may have installed Windows to D:\Windows for example.

The reason why it is better for the attacker to play with the DLLs is to avoid breaking the code signature in openvpn.exe or openvpn-gui.exe and thus alarming the user. Apparently this type of exploit is able to evade AV detection as well (in some cases?).

Last edited 2 years ago by Samuli Seppänen (previous) (diff)

comment:3 Changed 2 years ago by tincantech


comment:4 Changed 2 years ago by Locu

Another solution could be to bundle the dlls inside the main PE and extract/remove them at every restart of the application, but I don't know if it could be affordable for third party use.

Last edited 2 years ago by Locu (previous) (diff)

comment:5 Changed 2 years ago by Selva Nair

I don't know what's the point of this report. Loading DLLs from certain locations starting with the module (excutable) path is a feature of the OS. What is wrong with it? If I have write access to the executable's location I will just replace it with something malicious instead of messing with dlls.

There may be cases like security frameworks that protect against replacing executables but do not check dlls -- then do not give an untrusted user write access to ProgramFiles?/OpenVPN/bin. Or get a better security framework. Another thing an admin can do is to add all system dlls to the KnownDLLs in the registry. Windows already does that for most common dlls and and admin can add to that list.

Note that these are not loaded using LoadLibrary?() but are resolved by the runtime linker. So a place to add these paths would be the manifest but why? And why openssl libraries are not singled out? -- should we install them to System32 and hard code that path somewhere?

Note: See TracTickets for help on using tickets.