We at gpg4win.org are happily using NSIS to create our Installers for over a
decade now. So first let me thank you for all the work providing and
It was recently brought to our attention that the Gpg4win installer could be
used to execute arbitrary code with Administrative privileges when an attacker
has control over the Folder in which the installer is placed or can modify the
temp directory. By either placing system DLL's like shfolder.dll or version.dll into the same directory as the installer or by modifing temporary extracted plugins an attacker could cause code to be executed. (And for Elevated installers this could also be used as a privilege escaltion attack). I've outlined the problems causing this below. As they are somewhat related I've decided not to split them up in different bugreports.
While this may be a general problem there are ways to prevent this and we would like to fix it as we see it a serious problem of our installer.
Attached patches try to mitigate this (in the patches.zip file as sourceforge only lets me attach one file). The patches are against 2.46 as provided by Debian GNU/Linux (as we needed fixes for this version and I'll also report a Bug with debian about this) but I'll port them to trunk if you want me to.
I just wanted to get opinions on our analysis and patches first. Patches tested on debian wheezy and debian jessie compiling NISIS with mingw. Minimum supported version for the code used is Windows XP (which I hope is ok)
We saw three problems:
Use of LoadLibrary in NSIS. LoadLibrary by default looks in the current
directory of the process and into the Folder of the Executable. This is bad
(especially in the regular case that users execute our installer from the
downloads folder) because an attacker can just drop a dll in that folder and
it will be loaded with high privileges. To try it out just place a fake
shfolder.dll (That brings up a message box in it's DllMain) in the same
directory as an NSIS installer. This is also a Problem for LoadLibraryEx for
plugins because their dependencies are also loaded from the executables
Solution: Using SetDefaultDllDirectories we can globally change the behavior
of LoadLibraryEx so that it only looks into the System32 folder and into any
directories explicitly added with AddDllDirectories.
While this is only available on Windows Vista and later with updates installed
I think that it is Ok to use for NSIS as it basically means that we won't
lower the security on maintained Windows Systems and privilege escalation is
not that relevant on Windows XP as it does not have the User Account Control.
Plugins are extracted in the temporary folder and can be overwritten without
elevated privileges and the uninstaller is copied into a temporary directory
before it is executed. This also gives an attacker the chance to modify an
If the NSIS installer runs with elevated privileges create the temporary
directory in a way that only elevated users can write into it.
Even without delayload / direct loading Windows prefers DLL's from the
executables directory if they are not in the KnownDLL's  list. For NSIS
this is problematic for Version.dll
No implicit linking against Version.dll instead we use wrapper functions that
resolve the dependency at runtime after we restricted the DLL Search order as
outlined for Problem 1.
With these three patches I was no longer able to modify the Created Temporary
directory as a normal user, and I could execute the installer from a folder
where all libraries names from a Windows 7 System32 pointed to "fake"
Uff, Long Text ;-)
Thanks for reading,