Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dll hijacking fix #1444

Merged
merged 2 commits into from
Jan 30, 2019
Merged

Dll hijacking fix #1444

merged 2 commits into from
Jan 30, 2019

Conversation

bitdisaster
Copy link
Contributor

The current DLL hijacking prevention code in Squirrel isn't effective enough.

How do we know
So how do we know that we are vulnerable and which DLLs are a vector to attack? A simple look into ProcMon reveals the loading attempts of DLL from the local folder. Its best to set filter for the name of our executable, Paths that end with DLL and Results of NAME NOT FOUND.
image

In order to avoid the local DLL loading on all platforms and each code path I had to deploy all the following techniques. 😭

Static linking
Enabling static linked reduced the number of local DLL loading already. However, this was not full enabled for our binary. While Multi-Threaded (/MT) was enabled we missed the Static Library setting for Use of MFC. Why do we need both. Because SO says so https://stackoverflow.com/questions/37398/how-do-i-make-a-fully-statically-linked-exe-with-visual-studio-express-2005
Setting the default DLL directory
Squirrel already had an attempt to fix DLL hijacking. First code in Setup was this:

HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
ATLASSERT(hKernel32 != NULL);

SetDefaultDllDirectoriesFunction pfn = (SetDefaultDllDirectoriesFunction) GetProcAddress(hKernel32, "SetDefaultDllDirectories");
if (pfn) { (*pfn)(LOAD_LIBRARY_SEARCH_SYSTEM32); }

Basically we telling the kernel32.dll to look first into the System32 folder. However, in my experimentations this had no effect. I also tried calling SetDefaultDllDirectories() directly on Setup.exe and other DLLs that get loaded.

Delayed DLL loading
As mentioned in the previous paragraph SetDefaultDllDirectories() had no effect. The reason for this is that by default DLL are loaded at load-time of the module. So before any code runs we are already doomed. Luckily there is way to tell the linker to change this behavior to runtime loading via the /DelayLoad switch. This way DLLs will only be loaded if they are accessed. This gives us a chance to run code very early in the main function before any DDL is loaded and therefor SetDefaultDllDirectories() offers salvation.

Preloading DLLs
While the previous steps were good enough for Windows 10, we still see DLLs loaded from the current folder on Windows 7. Since we have delayed loading enabled we are in luck and can use some trickery. If we load the libraries in question with a full path to System32 before the actual code that needs them then we no new attempt is made to load them because they are already in memory.

@anaisbetts
Copy link
Contributor

@anaisbetts anaisbetts merged commit 17863e1 into Squirrel:master Jan 30, 2019
@bitdisaster
Copy link
Contributor Author

❤️

@anaisbetts
Copy link
Contributor

I'll try to get this out in a release Soon:tm:

@bitdisaster
Copy link
Contributor Author

Do you have a rough timeline for this to go out?

@bitdisaster
Copy link
Contributor Author

If you could create the release then we could also tackle this issue electron/windows-installer#287 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants