Hi @ll, on 2014-11-14 once again a Microsoft employee tried to downplay CWE-428 : In standard installations of Windows NT users are per default on the wrong side of this (not so) "airtight hatchway": the user account(s) created during setup is/are member(s) of the "Administrators" group, and the security theatre named "user account control" is NO security boundary! Despite this, unprivileged users can create a directory %SystemDrive%\Program [*] on ALL versions of Windows NT. From : | * There is a file or folder on your computer's hard disk that | has the same name as a file or folder in the path to the | service's executable file. | | For example, if the path of the executable file for a service | is C:\Program Files\MyProgram\MyService.exe, and if a folder | that is named C:\Program also exists on your hard disk, Windows | locates the C:\Program folder on your hard disk before the | C:\Program Files\MyProgram\My Service.exe file, and then tries | to run it. On Windows NT5.x (Windows Embedded POSReady 2009 is in extended support until April 2019) CreateProcess*(NULL, "C:\\Program Files\\Internet Explorer\\iexplore.exe", ...) as well as CreateProcess*(NULL, "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe", ...) return ERROR_ACCESS_DENIED if the directory C:\Program exists. On Windows NT6.x the directory C:\Program is but ignored/skipped and the command line executed successfully. On Windows NT5.x AND Windows NT6.x CreateProcess*(NULL, "C:\\Program Files\\Internet Explorer\\iexplore.exe", ...) return ERROR_ACCESS_DENIED if the directory "C:\Program Files\Internet" (yes, you need administrative rights to create it, but that's not the point here) exists. Now remove the directories "C:\Program Files\Internet" and "C:\Program" and create the file "C:\Program Files\Internet.exe": COPY "%COMSPEC%" "C:\Program Files\Internet.exe" (yes, you need administrative rights to create it, but that's still not the point here). On Windows NT5.x AND Windows NT6.x CreateProcess*(NULL, "C:\\Program Files\\Internet Explorer\\iexplore.exe", ...) executes the file "C:\Program Files\Internet.exe". Create the directory "C:\Program Files\Internet" and retry: CreateProcess*(NULL, "C:\\Program Files\\Internet Explorer\\iexplore.exe", ...) does NOT execute the file "C:\Program Files\Internet.exe" but "C:\Program Files\Internet Explorer\iexplore.exe" instead, i.e. the presence of the directory "C:\Program Files\Internet" lets Windows skip/ignore a file "C:\Program Files\Internet.exe"! Does this work for the file "C:\Program.exe" too? After COPY "%COMSPEC%" "C:\Program.exe" both CreateProcess*(NULL, "C:\\Program Files\\Internet Explorer\\iexplore.exe", ...) CreateProcess*(NULL, "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe", ...) execute "C:\Program.exe" on ALL versions of Windows NT. Create the directory "C:\Program" and retry: CreateProcess*(NULL, "C:\\Program Files\\Internet Explorer\\iexplore.exe", ...) return ERROR_ACCESS_DENIED on Windows NT5.x, but execute the command line on Windows NT6.x PS: if 8.3 filename creation is enabled a user with privilege SE_RESTORE_NAME might just create short names (see or ): PROGRAM for "C:\Program Files", PROGRAM.EXE for "C:\", INTERNET for "C:\Program Files\Internet Files" or INTERNET.EXE for "C:\Program Files\". JFTR: the documentation of CreateProcess*() behaviour for unquoted command lines is incomplete: | lpCommandLine ... | For example, consider the string | "c:\program files\sub dir\program name". | This string can be interpreted in a number of ways. | The system tries to interpret the possibilities in the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | following order: (quotes added for clarity) | | "c:\program.exe" files\sub dir\program name | "c:\program files\sub.exe" dir\program name | "c:\program files\sub dir\program.exe" name | "c:\program files\sub dir\program name.exe" Neither the 4 other possibilities: "C:\Program" files\sub dir\program name "C:\Program files\sub" dir\program name "C:\Program files\sub dir\program" name "C:\Program files\sub dir\program name" (executables dont need to have a file extension at all!) nor the precedence of directories "C:\" over files "C:\.exe" are documented! JFTR: LoadLibrary*("") searches for a file .DLL and loads it. Executables also dont need to have a filename at all.-P stay tuned Stefan Kanthak [*] finding the appropriate directory name for non-english versions of Windows NT3.x, NT4.x and NT5.x (where unprivileged users can but create a file %SystemDrive%\Program [*] as well as %SystemDrive%\Program.exe which will be executed) is left as an exercise to the reader. PS: If you want to play further: see the documentation of NTFS reparse points : | A file or directory can contain a reparse point, which is a | collection of user-defined data. ... | When the file system opens a file or directory (obvious omission added) | with a reparse point, it attempts to find the file system filter | associated with the data format identified by the reparse tag. ... | If a file system filter is not found, the file open operation | fails. and add this "collection of user-defined data" to the just created directory %SystemDrive%\Program: - users with the privilege SE_CREATE_SYMBOLIC_LINK_NAME can create a symbolic link; - ALL users can create a junction (or mount point), an NFS symbolic link, a WIM or SIS reparse point, etc. (Un)fortunately the file system filter driver for symbolic links only handles reparse points from file to file and directory to directory; it fails on reparse points from file to directory and from directory to file. The file system filter driver for junctions (and mount points) only handles reparse points from directory to directory or from directory to drive; it fails on reparse points with all other combinations.