Package: nsis
Version: 2.46-10
Installers generated by NSIS 2.46 are vulnerable to attacks that can lead to
code execution and privilege escalation (if the installer is running with
elevated privileges).
This has been reported to us at Gpg4win (www.gpg4win.org) which is built under
Debian GNU/Linux. We saw no other option to mitigate the attacks then to patch
our version of NSIS.
We've also reported this upstream today:
https://sourceforge.net/p/nsis/bugs/1125/
Background: Windows loads Libraries that are not "Known DLL's" from the
directory of the executable first. As NSIS uses direct loading though
LoadLibrary / LoadLibraryEx system calls, and links a not "Well Known" library
(version.dll) placing Libraries with standard names like shfolder.dll or
version.dll in the same Folder as an NSIS Installer (usually the Downloads
folder) will load those libraries in the context of the installer. An attacker
could cause these Libraries to be executed in the context of the installer.
This is especially problematic for signed Installers and Installers that
require Elevated (Administrator) Privileges for installation. As this bypasses
the signature validation and can be used for a privilege escalation.
Additionally NSIS uses an insecure temporary directory that can be modified
with normal User access rights in case of an elevated installation. This can
be used to modify plugins in that directory which then will be loaded with
higher privileges. There is also a temporary file race on uninstallation where
the uninstaller is copied into a temporary directory and afterwards executed
with elevated privileges.
More details and descriptions about how we mitigate these attacks are
available in the NSIS bug report.
Attached are the patches we are planning to use with NSIS to prepare our
next gpg4win release. They can be applied in the Order of their names to the
debian version of NSIS and compile on wheezy and jessie.
Regards,
Andre
--
Andre Heinecke | ++49-541-335083-262 | http://www.intevation.de/
Intevation GmbH, Neuer Graben 17, 49074 Osnabrück | AG Osnabrück, HR B 18998
Geschäftsführer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner--- a/Source/exehead/util.c
+++ b/Source/exehead/util.c
@@ -942,12 +942,54 @@
{"SHFOLDER", "SHGetFolderPathA"}
};
+#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
+#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x0800
+#endif
+
+#ifndef LOAD_LIBRARY_SEARCH_USER_DIRS
+#define LOAD_LIBRARY_SEARCH_USER_DIRS 0x0400
+#endif
+
+// Check if the system supports LoadLibraryEx flags to
+// restrict the search order. This migitates current
+// directory attacks.
+void NSISCALL RestrictLibrarySearch()
+{
+ typedef BOOL (WINAPI *sddd_t)(DWORD DirectoryFlags);
+ sddd_t sddd;
+ HMODULE hModule = GetModuleHandle("KERNEL32");
+ if (!hModule)
+ {
+/* KERNEL32.dll is one of the few Known libraries
+ on Windows so this is safe to do */
+hModule = LoadLibrary("KERNEL32");
+ }
+
+ sddd = (sddd_t) GetProcAddress (hModule, "SetDefaultDllDirectories");
+
+ if (!sddd)
+ {
+// SetDefaultDllDirectories not found this means we are either
+// on an unmaintained Windows or on a windows that does
+// not have KB2533623 installed.
+log_printf("SetDefaultDllDirectories failed.");
+return;
+ }
+
+ /* Users may use AddDllDirectory (SEARCH_USER_DIRS) but otherwise
+ we only load from System32. No installer should depend on the
+ insecure behavior of loading libraries from the directory in which
+ the installer is placed. This prevents DLL search order attacks
+ (CAPEC-471) against the current directory. */
+ sddd(LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32);
+}
+
void * NSISCALL myGetProcAddress(const enum myGetProcAddressFunctions func)
{
const char *dll = MGA_FUNCS[func].dll;
HMODULE hModule = GetModuleHandle(dll);
if (!hModule)
-hModule = LoadLibrary(dll);
+hModule = LoadLibraryEx(dll, NULL, 0);
if (!hModule)
return NULL;
--- a/Source/exehead/util.h
+++ b/Source/exehead/util.h
@@ -117,6 +118,10 @@
void * NSISCALL myGetProcAddress(const enum myGetProcAddressFunctions func);
void NSISCALL MessageLoop(UINT uCheckedMsg);
+// Restrict the LoadLibraryEx library search folder to mitigate current
+// directory attacks.
+void NSISCALL RestrictLibrarySearch();
+
// Turn a pair of chars into a word
// Turn four chars into a dword
#ifdef __BIG_ENDIAN__ // Not very likely, but, still...
--- a/Contrib/System/Source/System.c
+++ b/Contrib/System/Source/System.c
@@ -703,7 +703,7 @@
{
// Get DLL address
if ((proc->Dll = GetModuleHandle(proc->DllName)) == NULL)
-if ((proc->Dll = LoadLibrary(proc->DllName)) == NULL)
+if ((proc->Dll = LoadLibraryEx(proc->DllName, NULL, 0)) == NULL)
{
proc->ProcResult = PR_ERROR;
break;
--- a/Source/exehead/Ui.c
+