A hacker may try to compromise a system for various reasons. He may simply be trying to access protected data or, more ambitiously, trying to control the system remotely to use it as a bot. The first step to taking control of a system is to get his code running on the targeted system with sufficient privileges. The simplest method a hacker can use to run his code on the target machine is by exploiting the CreateProces API. This article will focus on the various quirks of the CreateProcess API that makes it so interesting to a hacker and discuss ways to make sure that his interest remains just an interest.
A hacker will try to exploit any calls to CreateProcess made by the vulnerable application to make the API launch his code instead of the applications intended code. There are numerous ways in which he can do that and the approach he chooses will depend on how the application is calling the CreateProcess API. The signature for this API is:
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
All arguments are explained in detail on MSDN. I am just going to concentrate on the ways of using the API that render an application vulnerable.
The preferred method of using CreateProcess is to set lpApplicationName to the full path of the application to run and fill lpCommandLine with any optional arguments to the application. However, this method is not strictly enforced allowing developers to set any one of the two arguments to NULL.
In the first case, a developer may set lpApplicationName to NULL and set lpCommandLine to the string used to launch the application from the command prompt. In this case, if the absolute path to the application is not specified, the system attempts to look for it in a few known locations. This gives rise to a problem known as Search Path Injection. The order in which the system looks into the known folders is:
A hacker will try to exploit any calls to CreateProcess made by the vulnerable application to make the API launch his code instead of the applications intended code. There are numerous ways in which he can do that and the approach he chooses will depend on how the application is calling the CreateProcess API. The signature for this API is:
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
All arguments are explained in detail on MSDN. I am just going to concentrate on the ways of using the API that render an application vulnerable.
The preferred method of using CreateProcess is to set lpApplicationName to the full path of the application to run and fill lpCommandLine with any optional arguments to the application. However, this method is not strictly enforced allowing developers to set any one of the two arguments to NULL.
In the first case, a developer may set lpApplicationName to NULL and set lpCommandLine to the string used to launch the application from the command prompt. In this case, if the absolute path to the application is not specified, the system attempts to look for it in a few known locations. This gives rise to a problem known as Search Path Injection. The order in which the system looks into the known folders is:
- The current directory of the application
- The directory of the parent process
- The Windows System directory
- The Windows directory
- All the other directories on the search path
For example, if lpCommandLine is set to:
program -a -bThe system tries to locate the executable "program" in the above mentioned folders in that order. If the attacker manages to place another executable named "program" somewhere higher in the search path, that executable will be launched. The mitigation for this attack is to always use the full canonical (unambiguous) path to the application no matter whether it is being used as lpApplicationName or included in lpCommandLine.
Using the full path may however, lead to a second type of problem. This problem is caused by the way the system parses lpCommandLine string when lpApplicationName is NULL. The first white space–delimited token in the lpCommandLine string is taken to be the module name. If the token does not contain an extension, a ".exe" is appended to it. 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
If the vulnerable application tries to launch an application located in some folder inside "C:\Program Files", all the hacker has to do is to name his executable program.exe and place it in "C:\".
The mitigation for this problem is to use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. Hence in the above example we would pass the literal string "\"C:\\program files\\sub dir\\program name\"" as lpCommandLine. Note however, the above mentioned problem does not arise if lpApplicationName is non-NULL.
To summarize, to avoid problems always use the full path of an application, do not use a NULL lpApplicationName and if you do, always quote the application path in lpCommandLine.
The mitigation for this problem is to use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. Hence in the above example we would pass the literal string "\"C:\\program files\\sub dir\\program name\"" as lpCommandLine. Note however, the above mentioned problem does not arise if lpApplicationName is non-NULL.
To summarize, to avoid problems always use the full path of an application, do not use a NULL lpApplicationName and if you do, always quote the application path in lpCommandLine.