Securable resources such as access tokens, events, files, threads, and others are represented via
HANDLE objects on Windows [MSDN]. Handle inheritance is a two-step process. When obtaining a
HANDLE, an option is given to specify whether the object is inheritable or not. This option is usually in the form of a
BOOL parameter (as in the case of
OpenMutex()), or a
SECURITY_DESCRIPTOR parameter (as in the case of
CreateFile()). When creating a process via the
CreateProcess() family of APIs, a parameter is given specifying whether the spawned process will inherit handles previously flagged as being inheritable. Any handles that were opened as being inheritable will be opened in the child process using the same handle value and access privileges as in the parent process. The parent process can then alert the child process of the handle values via an inter-process communication mechanism, and the child process can use those values as though it had opened the handle [MSDN].
When opening handles to securable resources or spawning child processes, prohibit handle inheritance by default to prevent accidental information leakage. If obtaining an inherited handle from a parent process, prevent leakage to subsequent child processes by duplicating the handle without inheritance.
Noncompliant Code Example (Mutex)
This noncompliant code example attempts to open an existing mutex handle that can be inherited by a child process:
Even if the process does not currently spawn child processes, this code example is noncompliant because future changes involving child processes could leak this handle accidentally.
Compliant Solution (Mutex)
This compliant solution opens the same mutex without specifying the handle can be inherited by a child process:
Noncompliant Code Example (Further Inheritance)
In this noncompliant example, the child process is spawned and inherits a single file handle from its parent process. The first argument to the main function is the handle's integer value as a hexadecimal string. However, the child process is not validating that the handle is a valid file handle, and it is not restricting further inheritance of the handle. Additionally, a portability concern arises if the parent process and the child process are the same architecture (for example, if one is 32-bit and the other is 64-bit).
Compliant Solution (Further Inheritance)
This compliant solution receives the inherited handle via the command line but prevents further inheritance by duplicating the handle. It also ensures that the value passed is a valid
HANDLE value. Then it validates the handle as a proper file handle by calling
GetFileInformationByHandle(). This solution also properly handles cross-architecture situations between the processes.
Noncompliant Code Example (
By default, all files on Windows that are opened using
fopen() will allow handle inheritance, and processes spawned via the
system() API automatically inherit handles. In this noncompliant code example,
SomeProcess.exe inherits the file handle for
Compliant Solution (
In this compliant solution, the Windows-specific
'N' mode parameter is passed to the call to
fopen(), which ensures the file is opened without allowing handle inheritance:
Leaking handles across process boundaries can leak information or cause denial-of-service attacks.