Title: Nullsoft Scriptable Installer System (NSIS) - Insecure Temporary Directory
Usage
Vendor URL: https://nsis.sourceforge.io/Main_Page
Versions Affected: NSIS 3.08 (September 25, 2021) and below
CVE Identifier: CVE-2023-37378
Risk:
7.8 CVSS:3.0/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H
7.3 CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Author: Richard Warren
Description
The NSIS uninstaller package did not enforce appropriate permissions on the temporary directory used during the uninstall process. Furthermore, it did not ensure that the temporary directory was removed before running executable content from it. This could potentially result in privilege escalation under certain scenarios.
Impact
A low-privileged, local attacker could exploit this vulnerability to execute arbitrary code with the privileges of the user that launched the uninstaller – potentially resulting in privilege escalation. An example of this could be a privileged Windows service that runs as SYSTEM , and runs an NSIS uninstall.exe
package. A malicious user could exploit this vulnerability to gain code execution with the privileges of that service.
Technical Details
During the uninstall process, the NSIS uninstaller.exe
executable creates a temporary
sub-directory under the current user’s %TEMP%
folder. It then copies itself to this directory before executing the a new temporary executable with CreateProcess
. However, the uninstaller executable does not protect this temporary directory from removal when it has been launched from a privileged context. Additionally, it ignores the ERROR_ALREADY_EXISTS
code returned by CreateDirectory
, and applies an overly-permissive ACL to the existing directory instead.
This allows users in the Everyone
group permission to delete the folder and re-create it with malicious content.
A malicious user could exploit these weaknesses to create a “poisoned” temporary directory containing a payload – which would get executed by the uninstaller. Looking at the nsis-3.08
source code, we can find the following line in Source\exehead\Main.c
On line 352, the program makes a call to UserIsAdminGrpMember
and sets the admin variable to the return value. The UserIsAdminGrpMember
function calls the shell32!IsUserAnAdmin
Windows API function.
This function is simply a wrapper for SHTestTokenMembership, which checks that the user’s token contains the RID 0x220
(i.e. SID S-1-5-32-544
(BUILTIN_ADMINISTRATORS
)).
If an uninstaller is launched as SYSTEM
, it will pass the UserIsAdminGrpMember
function, which the uninstaller.exe
process token will contain the administrator SID. Furthermore, its %TEMP%
and %TMP%
variables will be set to the global C:\Windows\Temp
temporary directory (via a call to GetTempPath
), which all users have Write access to.
As such, the NSIS code will go on to call the CreateRestrictedDirectory
, as the value of admin will be 1 . However, if we look at the code for this function, we can see that the ACL applied using SetFileSecurity
includes an ACE which allows Everyone to have DELETE
permissions.
Additionally, in the CreateRestrictedDirectory
, although the CreateDirectory
return code is checked for the ERROR_ALREADY_EXISTS
return code, it does not re-create the folder. Instead, it applies the permissive ACL to the existing folder. This means that if the folder already contains malicious content, it will not be removed.
The NSIS uninstaller does attempt to remove any existing Un_X.exe
executables from the~nsuA.tmp
folder. However, any other content will be left in place.
There is also a potential TOCTOU issue, since CopyFile
is used to write the Un_X.exe
file, no exclusive handle is maintained on the file. Therefore an attacker may be able to race between when the file is written with CopyFile
and when it is launched with CreateProcess
. The attacker could potentially improve their chances of winning this race by using oplocks.
Exploitation
Whilst it is tricky to exploit a race-condition, and DLL Hijacking is generally mitigated by the use of SetDefaultDllDirectories
in NSIS – another way to exploit this vulnerability would be to abuse Windows Side-by-Side (WinSxS) assembly loading and DotLocal redirection.
This is a relatively lesser-known technique that allows us to create a DLL hijacking primitive by creating a .local
folder in the executable directory. DotLocal abuse has been documented and exploited previously by multiple researchers, and is used in the UACME UAC bypass tool.
As mentioned earlier, an attacker can delete the C:\Windows\Temp\~nsuA.tmp
folder and re-create it with their own chosen permissions. Once the folder has been re-created with write permissions, the attacker can create an Un_A.exe.local
sub-directory inside the ~nsuA.tmp
folder. This will cause Windows to attempt to load SxS assemblies from this folder – which is controlled and write-able by the attacker.
In the following screenshot we can see the Un_A.exe
process attempting to open the .local
directory under normal usage:
If we delete the ~nsuA.tmp
folder, re-create it with weak permissions, and create the .local
folder sub-directory described above, we can see it now attempts to open the C:\Windows\Temp\~nsuA.tmp\Un_A.exe.local\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e
subdirectory from a .local
folder:
If we create the amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e
sub-directory too, then it will finally attempt to load the comctl32.dll
library, giving the attacker a DLL hijacking primitive:
Therefore, to exploit this issue, an unprivileged attacker simply has to:
- Delete any existing
C:\Windows\Temp\~nsuA.tmp
folder - Recreate the folder with Read/Write permissions
- Create the
.local
SxS redirection subfolder containing a maliciousCOMCTL32.dll
file - Trigger the
uninstaller.exe
process to run as a privileged (e.g. SYSTEM ) user (this will be product specific – e.g. RPC/COM).
This would give the attacker code execution within the Un_A.exe
process, which runs with the same privileges as the uninstaller.exe
process.
Proof of Concept
Whilst a full Proof of Concept is not provided, some example code can be found here which shows how to determine the required SxS folder name.
The following screenshot shows the PoC being run against a simple test NSIS package.
- At 1: the PoC exploit is run, creating the neccessary folder structure.
- At 2: the folder structure shows
~nsuA.tmp
directory, and the.local
folder containing the SxS DLL Hijack. - At 3: the
uninstaller.exe
package is run under the SYSTEM account using PSExec (for example purposes). - At 4: the DLL hijack is triggered, resulting in a new
cmd.exe
Window being spawned as SYSTEM.
Affected Software
We have identified multiple products using NSIS where this vulnerability is exploitable and leads to privilege escalation.
If your software package makes use of NSIS versions prior to 3.09 and allows a low-privileged user to initiate an uninstall operation from a privileged context; for example, auto-updaters, or software which uses a service for maintenance tasks (e.g. repairing an application install) – then it is likely be exploitable.
Furthermore, if your software can be (un)installed through a deployment service such MDM or Configuration Management software, then it may also be exploitable via this vulnerability – as many of these products install software packages as SYSTEM.
The Patch
A proposed patch was provided to the NSIS project maintainers, which removed the permissive ACE allowing all users to delete the temporary directory, and added error handling to delete the directory if it already existed.
This was reviewed by the project maintainers and multiple fixes were implemented, which:
- Creates an isolated temporary directory for each uninstaller process, deleting any existing directories if present.
- Checks that the temporary directory does not contain a symlink before deleting it.
- Removes the permissive ACL.
These fixes were released in NSIS version 3.09.
Report Timeline
2023-02-08 - Reported to NSIS Maintainers
2023-02-22 - Confirmation from maintainers, and patch provided for review
2023-05-21 - Initial patch committed to NSIS project
2023-05-30 - Feedback provided by NCC regarding proposed patch
2023-06-03 - Additional hardening added
2023-05-05 - Further feedback provided about patches
2023-06-21 - Additional hardening added
2023-07-01 - NSIS version 3.09 released
2023-07-11 - NCC Group advisory published
About NCC Group
NCC Group is a global expert in cybersecurity and risk mitigation, working with businesses to protect their brand, value and reputation against the ever-evolving threat landscape. With our knowledge, experience and global footprint, we are best placed to help businesses identify, assess, mitigate respond to the risks they face. We are passionate about making the Internet safer and revolutionizing the way in which organizations think about cybersecurity.
Published date: 2023-07-11
Written by: Richard Warren