Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Tempest in the ‘TEMP’ Directory

Purpose
Reason
Introduction
Vulnerability
Example 1
Example 2
Example 3
Example 4
Detection
Instrumentation
Examination
Mitigations
Alternative 1
Alternative 2
Alternative 3

Purpose

Document an easy to exploit trivial vulnerability of Microsoft® Windows® NT due to insufficient isolation of privileged processes running under the NT AUTHORITY\SYSTEM alias LocalSystem account.

Reason

While Microsoft runs its WHQL alias Windows Hardware Certification Program to qualify and certify hardware drivers, offering the Windows Hardware Certification Kit (for Window 7, Window 8, Window 8.1, Window Server 2008 R2, Window Server 2012, Window Server 2012 R2) and the Windows Hardware Lab Kit (for Windows 10, Window Server 2016, Window Server 2019) to perform their evaluation, a corresponding and complementary Windows Software Quality Laboratory or Windows Software Certification Program, accompanied by a Windows Software Compatibility Kit or a Windows Software Lab Kit, is but missing, resulting in insecurity and miserability of not just hardware drivers shipped by Microsoft as well as third parties, i.e. IHVs and ISVs.

Introduction

Since Windows 2000 every user account has its own %TEMP%\ alias %LOCALAPPDATA%\Temp\ alias %USERPROFILE%\AppData\Local\Temp\ alias %SystemDrive%\Users\%USERNAME%\AppData\Local\Temp\ directory, which is not accessible for other (unprivileged) users.

The user-specific environment variables TEMP and TMP are set with the following registry entries:

REGEDIT4

[HKEY_CURRENT_USER\Environment]
"TEMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"
"TMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"
For the builtin user accounts NT AUTHORITY\SYSTEM alias LocalSystem, NT AUTHORITY\LOCAL SERVICE alias LocalService, and NT AUTHORITY\NETWORK SERVICE alias NetworkService, the user-specific environment variables TEMP and TMP are set with the following registry entries:
REGEDIT4

[HKEY_USERS\S-1-5-18\Environment]
"TEMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"
"TMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"

[HKEY_USERS\S-1-5-19\Environment]
"TEMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"
"TMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"

[HKEY_USERS\S-1-5-20\Environment]
"TEMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"
"TMP"=expand:"%USERPROFILE%\\AppData\\Local\\Temp"
Note: HKEY_USERS\S-1-5-18 is a symbolic link to the registry key HKEY_USERS\.DEFAULT.

The user profiles for the NT AUTHORITY\LOCAL SERVICE alias LocalService and the NT AUTHORITY\NETWORK SERVICE alias NetworkService accounts are stored in the directories %SystemRoot%\ServiceProfiles\LocalService\ and %SystemRoot%\ServiceProfiles\NetworkService\ respectively, which too are not accessible for other (unprivileged) users.

On 32-bit editions of Windows NT the user profile for the NT AUTHORITY\SYSTEM alias LocalSystem account is stored in the directory %SystemRoot%\System32\Config\SystemProfile\, which also is not accessible for other (unprivileged) users.
On 64-bit editions of Windows NT, thanks to the File System Redirector, the user profile for the NT AUTHORITY\SYSTEM alias LocalSystem account is stored in the disjoint directories %SystemRoot%\System32\Config\SystemProfile\ and %SystemRoot%\SysWoW64\Config\SystemProfile\, which are not accessible for other (unprivileged) users.

Note: the (sub)directory %SystemRoot%\System32\Config\SystemProfile\AppData\Local\Temp\, on 64-bit editions of Windows NT also %SystemRoot%\SysWoW64\Config\SystemProfile\AppData\Local\Temp\, which corresponds to %USERPROFILE%\AppData\Local\Temp\, but doesn’t exist, i.e. the user-specific environment variables TEMP and TMP set for the NT AUTHORITY\SYSTEM alias LocalSystem account have an invalid (dangling) value!

Only for the NT AUTHORITY\SYSTEM alias LocalSystem account the user-specific environment variables TEMP and TMP are but ignored and the system-specific environment variables evaluated instead, which are set with the following registry entries:

REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
"TEMP"=expand:"%SystemRoot%\\TEMP"
"TMP"=expand:"%SystemRoot%\\TEMP"
Note: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet is a symbolic link to the registry key HKEY_LOCAL_MACHINE\SYSTEM\ControlSet‹three digit number›.

Due to its inheritable DACL D:PAI(A;CI;0x100026;;;BU)(A;;FA;;;BA)(A;OICIIO;GA;;;BA)(A;;FA;;;SY)(A;OICIIO;GA;;;SY)(A;OICIIO;GA;;;CO) the directory %SystemRoot%\Temp\ is writable for unprivileged users who can create arbitrary files and subdirectories with full access permission for themselves as well as NT AUTHORITY\SYSTEM alias LocalSystem and BUILTIN\Administrators there.

The resulting well-known weaknesses are classified as CWE-379: Creation of Temporary File in Directory with Incorrect Permissions, CWE-426: Untrusted Search Path, and CWE-427: Uncontrolled Search Path Element.

Vulnerability

Processes running under the privileged NT AUTHORITY\SYSTEM alias LocalSystem account use the directory %SystemRoot%\Temp\ as their %TEMP%\ directory, thus defeating their isolation from unprivileged processes.

Setup programs, most notably self-extractors alias wrappers, unpack their payload, which typically includes executable files, to the processes %TEMP%\ alias %SystemRoot%\Temp\ directory and run the extracted executable files there.

When stored in a directory other than the system directory %SystemRoot%\System32\ and executed there, programs susceptible to CAPEC-471: Search Order Hijacking load system DLLs and system programs from their application directory instead from the system directory %SystemRoot%\System32\: as documented in the MSDN articles Dynamic-Link Library Security, Dynamic-Link Library Search Order, LoadLibrary() and CreateProcess(), the application directory is searched first per default.

By planting files in the directory %SystemRoot%\Temp\ which are executed from vulnerable programs run there any time later, unprivileged users can elevate their privileges to those of NT AUTHORITY\SYSTEM alias LocalSystem and BUILTIN\Administrators.

Example 1

Skype uses its own proprietary update mechanism instead of Microsoft Update: in version 7, the program %ProgramFiles%\Skype\Updater\Updater.exe is run periodically under the NT AUTHORITY\SYSTEM alias LocalSystem user account. When an update is available, %ProgramFiles%\Skype\Updater\Updater.exe copies or extracts another executable as %TEMP%\SKY‹abcd›.tmp alias %SystemRoot%\Temp\SKY‹abcd›.tmp and executes it using the command line
"%SystemRoot%\Temp\SKY‹abcd›.tmp" /QUIET
This executable is susceptible to CAPEC-471: Search Order Hijacking, it loads multiple system DLLs from its application directory %SystemRoot%\Temp\ instead from Windows’ system directory %SystemRoot%\System32\.

For the full story see Skype – or “Redmond, you’ve got a problem!”.

Example 2

Deployment and unattended installation of application software is typically performed via an agent or service running with administrative privileges on client computers, for example the built-in Group Policies, as documented in the MSKB article 816102.

For just one case where this still allows local users to escalate their privileges see ADV170017.

Example 3

With Windows 10 20H1 Microsoft moved the installation of (updated) drivers available online from Device Manager to Windows Update.

Contrary to previous versions, where driver installation initiated from Driver Manager runs under an administrator account, driver installation now runs under the NT AUTHORITY\SYSTEM alias LocalSystem user account.

Processes running under a normal user (or administrator) account use its (private) %LOCALAPPDATA%\Temp\ alias %USERPROFILE%\AppData\Local\Temp\ directory, which is not accessible for other (unprivileged) users, as %TEMP%\ directory, while processes running under the NT AUTHORITY\SYSTEM alias LocalSystem account use the (public) %SystemRoot%\Temp\ directory.

Quite some driver packages available on Windows Update contain besides their primary (kernel) drivers, which are typically installed via .INF scripts, also so-called satellites, i.e. additional programs and/or DLLs, which provide interfaces to configure and control the driver and its hardware. These satellites are typically installed by separate setup programs that are run during driver installation.

Note: satellites can of course be installed via .INF scripts too, but seldom are.

These setup programs are typically self-extractors, which use the %TEMP%\ directory to unpack and run their payload. Instead to create a properly secured subdirectory there, some self-extractors place their payload in the %TEMP%\ itself. Many, if not most such payloads are susceptible to CAPEC-471: Search Order Hijacking and execute files planted by unprivileged users in the %TEMP%\ alias %SystemRoot%\Temp\ directory with administrative rights and privileges.

Example 4

Vulnerable (setup) programs like those in example 3, when run via computer startup scripts.

Detection

Instrumentation

To instrument an installed system for detection, create hardlinks of all 32-bit system DLLs in the %SystemRoot%\Temp\ directory and configure the advanced logging feature of Software Restriction Policies to track (not only) their execution.

Run the following VBScript elevated, i.e. with administrative privileges, in the 32-bit execution environment:

Rem Copyright © 2004-2021, Stefan Kanthak <stefan‍.‍kanthak‍@‍nexgo‍.‍de>

Option Explicit

Const strCommandLine = "C:\Windows\System32\Cmd.exe /D /K For %? In (*.acm *.ax *.cpl *.dll *.drv *.ocx WBEM\*.dll) Do @MkLink /H C:\Windows\Temp\%~nx? %?"
Const strCurrentDirectory = "C:\Windows\System32"

With GetObject("WinMgmts:{impersonationLevel=Impersonate, (Backup, Restore)}!\\.\Root\CIMv2")
	Dim objProcessStartup
	Set objProcessStartup = .Get("Win32_ProcessStartup").SpawnInstance_
	With objProcessStartup
	'	.CreateFlags = 8	' Detached_Process
	'	.EnvironmentVariables = Array("NoDefaultCurrentDirectoryInExePath=*", _
	'	                              "SYSTEMDRIVE=C:", _
	'	                              "SYSTEMROOT=C:\Windows", _
	'	                              "TEMP=C:\Windows\Temp")
		.ErrorMode = 2		' Fail_Critical_Errors
		.FillAttribute = 240	' Black on White
		.PriorityClass = 32	' Normal
		.ShowWindow = 1		' SW_NORMAL
		.Title = vbNull
		.WinstationDesktop = vbNull
	'	.X = 0
		.XCountChars = 80
	'	.XSize = 640
	'	.Y = 240
		.YCountChars = 50
	'	.YSize = 480
	End With

	Dim intReturn, intProcessID
	intReturn = .Get("Win32_Process").Create(strCommandLine, strCurrentDirectory, objProcessStartup, intProcessID)
	If intReturn <> 0 Then
		WScript.Echo "Error " & intReturn
	Else
		WScript.Echo "Process " & intProcessID & " created"
	End If
End With

With WScript.CreateObject("WScript.Shell")
	.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers\AuthentiCodeEnabled", 0, "REG_DWORD"
	.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers\DefaultLevel", 262144, "REG_DWORD"
'	.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers\ExecutableTypes", vbNull, "REG_MULTI_SZ"
	.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers\LogFileName", "C:\Windows\System32\LogFiles\SAFER.Log", "REG_SZ"
	.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers\PolicyScope", 0, "REG_DWORD"
	.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers\TransparentEnabled", 2, "REG_DWORD"
End With
Alternative: run the following batch script in Windows PE after SETUP.exe /NoReboot, with the drive letter of the target volume as its only argument:
Rem Copyright © 2004-2021, Stefan Kanthak <stefan‍.‍kanthak‍@‍nexgo‍.‍de>

If "%~1" == "" Goto :USAGE
If Not "%1" == "%*" Goto :USAGE
If /I Not "%~1" == "%~d1" Goto :USAGE
If "%~d1" == "%SystemDrive%" Goto :USAGE
If Not Exist "%~d1\Windows\System32\Config\SOFTWARE" Goto :USAGE

If Exist "%~d1\Windows\SysWoW64" (
For %%? In ("%~d1\Windows\SysWOW64\*.acm"
            "%~d1\Windows\SysWOW64\*.ax"
            "%~d1\Windows\SysWOW64\*.cpl"
            "%~d1\Windows\SysWOW64\*.dll"
            "%~d1\Windows\SysWOW64\*.drv"
            "%~d1\Windows\SysWOW64\*.ocx"
            "%~d1\Windows\SysWOW64\WBEM\*.dll") Do @MkLink /H "%~d1\Windows\Temp\%%~nx?" "%%?"
) Else (
For %%? In ("%~d1\Windows\System32\*.acm"
            "%~d1\Windows\System32\*.ax"
            "%~d1\Windows\System32\*.cpl"
            "%~d1\Windows\System32\*.dll"
            "%~d1\Windows\System32\*.drv"
            "%~d1\Windows\System32\*.ocx"
            "%~d1\Windows\System32\WBEM\*.dll") Do @MkLink /H "%~d1\Windows\Temp\%%~nx?" "%%?"
)
"%SystemRoot%\System32\Reg.exe" LOAD   "HKEY_USERS\SOFTWARE" "%~d1\Windows\System32\Config\SOFTWARE"
"%SystemRoot%\System32\Reg.exe" QUERY  "HKEY_USERS\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers" /S
"%SystemRoot%\System32\Reg.exe" ADD    "HKEY_USERS\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers" /V "AuthentiCodeEnabled" /T REG_DWORD /D 0 /F
"%SystemRoot%\System32\Reg.exe" ADD    "HKEY_USERS\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers" /V "DefaultLevel" /T REG_DWORD /D 262144 /F
"%SystemRoot%\System32\Reg.exe" ADD    "HKEY_USERS\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers" /V "ExecutableTypes" /T REG_MULTI_SZ /D "" /F
"%SystemRoot%\System32\Reg.exe" ADD    "HKEY_USERS\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers" /V "LogFileName" /T REG_SZ /D "C:\Windows\System32\LogFiles\SAFER.Log" /F
"%SystemRoot%\System32\Reg.exe" ADD    "HKEY_USERS\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers" /V "PolicyScope" /T REG_DWORD /D 0 /F
"%SystemRoot%\System32\Reg.exe" ADD    "HKEY_USERS\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers" /V "TransparentEnabled" /T REG_DWORD /D 2 /F
"%SystemRoot%\System32\Reg.exe" UNLOAD "HKEY_USERS\SOFTWARE"
Exit /B

:USAGE
Echo Usage: %~nx0 ^<drive letter^>:
Exit /B
Note: since (the hardlinks of) the system DLLs are writable only for the TrustedInstaller account or with SeRestorePrivilege enabled, this instrumentation inhibits attacks via (malicious) fake system DLLs and mitigates the vulnerability!

Note: some hardlinks will become orphans over time and thus undergo bit rot, they are not updated by (security) updates; orphaned hardlinks can be deleted and recreated any time!

Examination

Run the following command line to list the pathnames of files executed in and below the %SystemRoot%\Temp\ directory:
REM Copyright © 2004-2021, Stefan Kanthak <stefan‍.‍kanthak‍@‍nexgo‍.‍de>

FIND.EXE /I "%SystemRoot%\Temp\" "%SystemRoot%\System32\LogFiles\SAFER.log"

Mitigations

Never create or execute files directly in the %SystemRoot%\Temp\ directory; always create a properly secured subdirectory which other (less privileged) users can’t access first, then create your files there!

Since this doesn’t help with existing self-extractors which ignore this basic rule of isolation and privilege separation, better use the following alternative mitigation.

Alternative 1

Create the missing subdirectory %SystemRoot%\System32\Config\SystemProfile\AppData\Local\Temp\, on 64-bit systems also %SystemRoot%\SysWoW64\Config\SystemProfile\AppData\Local\Temp\, owned by the NT AUTHORITY\SYSTEM alias LocalSystem user account, and set the system-specific environment variables TEMP and TMP to the value %USERPROFILE%\AppData\Local\Temp.

Use the following command lines in the batch script %SystemRoot%\Setup\Scripts\SetupComplete.cmd to perform these changes automatically during setup:

Rem Copyright © 2009-2021, Stefan Kanthak <stefan‍.‍kanthak‍@‍nexgo‍.‍de>

MkDir "%SystemRoot%\System32\Config\SystemProfile\AppData\Local\Temp"
If Exist "%SystemRoot%\SysWoW64\Config\SystemProfile" MkDir "%SystemRoot%\SysWoW64\Config\SystemProfile\AppData\Local\Temp"

"%SystemRoot%\System32\SetX.exe" TEMP "%%USERPROFILE%%\AppData\Local\Temp" /M
"%SystemRoot%\System32\SetX.exe" TMP "%%USERPROFILE%%\AppData\Local\Temp" /M
Exit /B
Note: this mitigation also stops many other attacks and thus prevents vulnerabilities like Microsoft Windows Defender Elevation of Privilege Vulnerability alias CVE-2020-1170 from being exploited in the first place!

Caveat: on 64-bit systems, the disjoint directories may cause surprising behaviour!

Alternative 2

Add the ACEs (D;OIIO;WP;;;WD) and (D;CIOIIO;WD;;;OW) to the ACL of the %SystemRoot%\Temp\ directory: the first ACE denies execute permission for all files created there, the second ACE denies the respective owner of files and subdirectories the permission to change their ACL.

Also set the attributes hidden and system to prevent File Explorer from granting full access to any UAC controlled administrator account, as documented in the MSKB article 950934.

Use the following command lines in the batch script %SystemRoot%\Setup\Scripts\SetupComplete.cmd to perform these changes automatically during setup:

Rem Copyright © 2009-2021, Stefan Kanthak <stefan‍.‍kanthak‍@‍nexgo‍.‍de>

"%SystemRoot%\System32\CACLs.exe" "%SystemRoot%\Temp" /S:"D:PAR(D;CIOIIO;WD;;;OW)(D;OIIO;WP;;;WD)(A;CI;0x100026;;;BU)(A;;FA;;;BA)(A;OICIIO;GA;;;BA)(A;;FA;;;SY)(A;OICIIO;GA;;;SY)(A;OICIIO;GA;;;CO)"
"%SystemRoot%\System32\Attrib.exe" +H +R +S "%SystemRoot%\Temp" /M
Exit /B

Alternative 3

See detection above!

Note: the instrumentation prevents only attacks via fake system DLLs; it does not prevent similar attacks via fake system programs like Cmd.exe etc., which may be called from batch scripts running in the %SystemRoot%\Temp\ directory via unqualified filenames.

Contact

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2021 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>