From 9398d230339d5bfaa94093af89a17abf33b5dfad Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 18 Jul 2016 20:02:32 +0100 Subject: [PATCH] Lock down the search path for Windows DLL loading. At least on systems providing SetDefaultDllDirectories, this should stop PuTTY from being willing to load DLLs from its containing directory - which makes no difference when it's been properly installed (in which case the application dir contains no DLLs anyway), but does if it's being run from somewhere uncontrolled like a browser downloads directory. Preliminary testing suggests that this shouldn't break any existing deliberate use of DLLs, including GSSAPI providers. --- windows/window.c | 2 ++ windows/winmisc.c | 32 ++++++++++++++++++++++++++++++++ windows/winpgen.c | 2 ++ windows/winpgnt.c | 2 ++ windows/winplink.c | 2 ++ windows/winsftp.c | 2 ++ windows/winstuff.h | 1 + 7 files changed, 43 insertions(+) diff --git a/windows/window.c b/windows/window.c index 290e6a31..11546410 100644 --- a/windows/window.c +++ b/windows/window.c @@ -347,6 +347,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) HRESULT hr; int guess_width, guess_height; + dll_hijacking_protection(); + hinst = inst; hwnd = NULL; flags = FLAG_VERBOSE | FLAG_INTERACTIVE; diff --git a/windows/winmisc.c b/windows/winmisc.c index f2e4f223..11e2ca0f 100644 --- a/windows/winmisc.c +++ b/windows/winmisc.c @@ -149,6 +149,38 @@ char *get_username(void) return got_username ? user : NULL; } +void dll_hijacking_protection(void) +{ + /* + * If the OS provides it, call SetDefaultDllDirectories() to + * prevent DLLs from being loaded from the directory containing + * our own binary, and instead only load from system32. + * + * This is a protection against hijacking attacks, if someone runs + * PuTTY directly from their web browser's download directory + * having previously been enticed into clicking on an unwise link + * that downloaded a malicious DLL to the same directory under one + * of various magic names that seem to be things that standard + * Windows DLLs delegate to. + * + * It shouldn't break deliberate loading of user-provided DLLs + * such as GSSAPI providers, because those are specified by their + * full pathname by the user-provided configuration. + */ + static HMODULE kernel32_module; + DECL_WINDOWS_FUNCTION(static, BOOL, SetDefaultDllDirectories, (DWORD)); + + if (!kernel32_module) { + kernel32_module = load_system32_dll("kernel32.dll"); + GET_WINDOWS_FUNCTION(kernel32_module, SetDefaultDllDirectories); + } + + if (p_SetDefaultDllDirectories) { + /* LOAD_LIBRARY_SEARCH_SYSTEM32 only */ + p_SetDefaultDllDirectories(0x800); + } +} + BOOL init_winver(void) { ZeroMemory(&osVersion, sizeof(osVersion)); diff --git a/windows/winpgen.c b/windows/winpgen.c index 98319608..8468f805 100644 --- a/windows/winpgen.c +++ b/windows/winpgen.c @@ -1519,6 +1519,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) char **argv; int ret; + dll_hijacking_protection(); + InitCommonControls(); hinst = inst; hwnd = NULL; diff --git a/windows/winpgnt.c b/windows/winpgnt.c index 86998a2b..06c5fac1 100644 --- a/windows/winpgnt.c +++ b/windows/winpgnt.c @@ -1072,6 +1072,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) int argc, i; char **argv, **argstart; + dll_hijacking_protection(); + hinst = inst; hwnd = NULL; diff --git a/windows/winplink.c b/windows/winplink.c index 99e269fd..3b20a0ab 100644 --- a/windows/winplink.c +++ b/windows/winplink.c @@ -312,6 +312,8 @@ int main(int argc, char **argv) int just_test_share_exists = FALSE; unsigned long now, next, then; + dll_hijacking_protection(); + sklist = NULL; skcount = sksize = 0; /* diff --git a/windows/winsftp.c b/windows/winsftp.c index c786f7a6..7b08970f 100644 --- a/windows/winsftp.c +++ b/windows/winsftp.c @@ -773,6 +773,8 @@ int main(int argc, char *argv[]) { int ret; + dll_hijacking_protection(); + ret = psftp_main(argc, argv); return ret; diff --git a/windows/winstuff.h b/windows/winstuff.h index 4f2b4e88..c57ce6ea 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -478,6 +478,7 @@ void show_help(HWND hwnd); * Exports from winmisc.c. */ extern OSVERSIONINFO osVersion; +void dll_hijacking_protection(void); BOOL init_winver(void); HMODULE load_system32_dll(const char *libname); const char *win_strerror(int error); -- 2.45.2