[<prev] [next>] [day] [month] [year] [list]
Message-ID: <754FD6E6FF294DC8BF1E456C9E5C4291@W340>
Date: Sun, 15 Nov 2015 07:01:03 +0100
From: "Stefan Kanthak" <stefan.kanthak@...go.de>
To: <bugtraq@...urityfocus.com>
Cc: fulldisclosure@...lists.org
Subject: [FD] Defense in depth -- the Microsoft way (part 36): CWE-428 or
fun with unquoted paths
Hi @ll,
on 2014-11-14 once again a Microsoft employee tried to downplay
CWE-428 <https://cwe.mitre.org/data/definitions/428.html>:
<http://blogs.msdn.com/b/aaron_margosis/archive/2014/11/14/it-rather-involved-being-on-the-other-side-of-this-airtight-hatchway-unqu
oted-service-paths.aspx>
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 <https://support.microsoft.com/en-us/kb/812486>:
| * 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
<https://msdn.microsoft.com/en-us/library/aa365543.aspx> or
<https://technet.microsoft.com/en-us/library/bb490642.aspx>):
PROGRAM for "C:\Program Files",
PROGRAM.EXE for "C:\<arbitrary_executable>",
INTERNET for "C:\Program Files\Internet Files" or
INTERNET.EXE for "C:\Program Files\<arbitrary_executable>".
JFTR: the documentation of CreateProcess*() behaviour for
unquoted command lines is incomplete:
<https://msdn.microsoft.com/en-us/library/ms682425.aspx>
<https://msdn.microsoft.com/en-us/library/ms682429.aspx>
<https://msdn.microsoft.com/en-us/library/ms682431.aspx>
<https://msdn.microsoft.com/en-us/library/ms682434.aspx>
| 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:\<something>" over
files "C:\<something>.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
<https://msdn.microsoft.com/en-us/library/aa365503.aspx>:
| 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.
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: http://seclists.org/fulldisclosure/
Powered by blists - more mailing lists