DLL hijacking (aka spoofing) is an attack on an application where the attacker uses a DLL the application tries to load that is missing or from an unexpected location (e.g. from the app’s directory instead of the system’s folder). One of the reasons this attack is open relates to how Windows searches where to load DLLs from and how software developers secure the way the OS does this search.
The initial discovery
During a routine analysis and while playing with Process Monitor, the Deceptive Bytes team noticed weird behavior from a .NET application, it tried loading a system DLL from the app’s folder. Testing further and researching the internet yields some information that indicates that this is not exactly new but at most it was for a specific DLL or for specific app types like WPF or the .NET installer itself.
The extensive discovery
The Deceptive Team decided to check if it’s widespread or just occurs with specific apps or types of apps.
The team ran a few known applications like Fiddler, KeePass and others and discovered that they try to load a system DLL from their install folder.
The team then searched the .NET Git code repository for native DLL loading with “DllImport” and related keywords. The team discovered that while .NET defaults to only loading from the app folder and from the system, .NET internally doesn’t limit system DLLs, allowing them to also load from the app’s folder, opening most .NET applications to DLL spoofing vulnerability (ironically, Microsoft does not adhere to its own security recommendations). The team then wrote 2 simple examples that showcase hijacking with a duplicate of cryptbase.dll:
Of course cryptbase.dll is just an example and is not the only one…
Recently released .NET 5 still vulnerable
.NET 5, the next major version which was recently released didn’t resolve the issue (though some cases might not be relevant anymore due to changes and the cross-platform nature of this release).
Here’s a fresh example with .NET 5:
Microsoft provided the following response after about 3 weeks:
“Thank you again for your report. Our analyst has completed reviewing your report, and we have determined that this issue does not meet our bar for servicing with an immediate security update. Rather, this is something that may be addressed in a future release. In this instance, the issue you have identified is an example of application directory binary loading/planting. Details about how these types of issues are assessed and the reasoning behind our decision can be found here – https://msrc-blog.microsoft.com/2018/04/04/triaging-a-dll-planting-vulnerability/
We have opened a tracking item with the .NET team, but we will be closing this case.
Thank you for the opportunity to review your findings, and please don’t hesitate to send any future reports to us at https://msrc.microsoft.com.”
Microsoft has different docs with relevant help including securing DLLs and securing DLL loading.
Calling WinAPI from .NET (using marshaling) can help as well, functions like SetDefaultDllDirectories, SetSearchPathMode, SetDllDirectory can help mitigate this issue for .NET apps
Make sure that when marshaling system DLLs to use the DefaultDllImportSearchPaths attribute with DllImportSearchPath.System32 to verify you’re not leaving your app exposed to other DLL hijacking vulnerabilities. For non-system native DLLs, it’s recommended to use the full path or DllImportSearchPath.ApplicationDirectory.