[<prev] [next>] [day] [month] [year] [list]
Message-ID: <7FCE27711A4646AF82B65FAFC986D36F@W340>
Date: Sat, 21 Feb 2015 15:43:09 +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 29): contradicting,
ambiguous, incomplete documentation
Hi @ll,
the MSDN documents the BRAINDEAD behaviour of the functions
CreateProcess() <https://msdn.microsoft.com/en-us/library/ms682425.aspx>,
CreateProcessAsUser() <https://msdn.microsoft.com/en-us/library/ms682429.aspx>
CreateProcessWithLogonW() <https://msdn.microsoft.com/en-us/library/ms682431.aspx>
CreateProcessWithTokenW() <https://msdn.microsoft.com/en-us/library/ms682434.aspx>
for an unquoted "long" pathname of the executable in command lines:
| [...] the module name must be the first white space-delimited token in
| the lpCommandLine string. If you are using a long file name that contains
| a space, use quoted strings to indicate where the file name ends and the
| arguments begin; otherwise, the file name is ambiguous.
| 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: ~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 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
...
| [...] the first white space-delimited token of the command line
| specifies the module name. If you are using a long file name that
| contains a space, use quoted strings to indicate where the file name
| ends and the arguments begin [...] If the file name does not contain
| an extension, .exe is appended. [...] if the file name contains a path,
| .exe is not appended. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~
1. self-contradictory/ambiguous:
If the second underlined clause of the documentation were correct,
and the usual definition of path(name) ['] is assumed (so "c:\",
"c:\program files\sub" and "c:\program files\sub dir\program"
qualify as pathnames), the interpretation of the string
"c:\program files\sub dir\program name"
given above would be wrong.
The interpretation given above but matches the observed behaviour
of the CreateProcess*() functions, therefore the underlined clause
of the documentation is WRONG and should be removed!
2. incomplete/ambiguous:
the documentation does not specify what "tries to interpret the
possibilities" exacly means: using the example given above, is
CreateProcess*() expected to skip
"c:\program.exe", "c:\program files\sub.exe" and/or
"c:\program files\sub dir\program.exe" if they exist but are not
executable
a) due to invalid file contents?
Observed behaviour:
CreateProcess*() tries to execute c:\program.exe etc. and returns
ERROR_BAD_EXE_FORMAT, ERROR_EXE_MARKED_INVALID,
ERROR_INVALID_EXE_SIGNATURE, etc.
b) due to insufficient permissions?
Observed behaviour:
CreateProcess*() tries to execute c:\program.exe etc. and returns
ERROR_ACCESS_DENIED!
c) because they are an unsupported or unknown [²] reparse point?
Observed behaviour:
CreateProcess*() tries to execute c:\program.exe etc. and returns
ERROR_CANT_ACCESS_FILE, ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND,
etc.
d) because they are a directory (including directories overlaid with
a reparse point), a mount point, a junction to a directory or a
symlink to a directory?
Observed behaviour:
in contradiction to MSKB 812486 [³] CreateProcess*() does not
try to execute a directory c:\program.exe etc. and skips it.
Skipping over directories or reparse points targetting
directories is but surprising behaviour, since
CreateProcess*("<directory>", NULL, ...) and
CreateProcess*(NULL, "<directory>", ...) return
(as expected) ERROR_ACCESS_DENIED!
3. incomplete/surprising:
The observed behaviour for
CreateProcess(NULL, "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe", ...)
is: CreateProcess*() tries to execute "C:\Program.exe" and
"C:\Program Files (x86)\Internet.exe", but NOT
"C:\Program Files.exe"
WTF?
Why is "C:\Program Files.exe" NOT a "possibility to try"?
4. incomplete:
when CreateProcess*() is called (for example) with the command
line "c:\program files\sub dir\program name" and plays try&error,
the executed application does NOT receive the original command line,
but a MODIFIED command line:
- "c:\program files\sub.exe" dir\program name
- "c:\program files\sub dir\program.exe" name
- "c:\program files\sub dir\program.exe name.exe"
i.e. the pathname of the found executable gets quoted if it contains
a space.
The documentation of the function GetCommandLine()
<https://msdn.microsoft.com/en-us/library/ms683156.aspx>
but misses this completely!
Stay tuned!
regards
Stefan Kanthak
['] as soon as a name contains a single '\' or ':' it is a pathname!
Cf. <https://msdn.microsoft.com/en-us/library/aa365247.aspx>
[²] <https://msdn.microsoft.com/en-us/library/aa365503.aspx>:
| 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 found, the filter processes the file
or directory (obvious omission added)
| as directed by the reparse data. If a file system filter is not
| found, the file open operation fails.
[³] <https://support.microsoft.com/kb/812486/en-us>:
| * 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.
_______________________________________________
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