| Note |
|---|
This content has been VOIDed because it is entirely covered by the C rule VOID FIO32-C. Do not perform operations on devices that are only appropriate for files |
File names on many operating systems, including Windows and UNIX, may be used to access special files, which are actually devices. Reserved Microsoft Windows device names include AUX, CON, PRN, COM1, and LPT1 or paths using the \\.\ device namespace. Device files on UNIX systems are used to apply access rights and to direct operations on the files to the appropriate device drivers.
...
A Web browser that failed to check for these devices would allow an attacker to create a website with image tags such as <IMG src="file:///dev/mouse"> that would lock the user's mouse.
Noncompliant Code Example
In this noncompliant code example, the user can specify a locked device or a FIFO (first-in, first-out) file name, which can cause the program to hang on the call to fopen():
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h>
void func(const char *file_name) {
FILE *file;
if ((file = fopen(file_name, "wb")) == NULL) {
/* Handle error */
}
/* Operate on the file */
if (fclose(file) == EOF) {
/* Handle error */
}
} |
Compliant Solution (POSIX)
POSIX defines the O_NONBLOCK flag to open(), which ensures that delayed operations on a file do not hang the program [IEEE Std 1003.1:2013].
...
Essentially, an attacker can switch out a file for one of the file types shown in the following table with the specified effect.
File Types and Effects
Type | Note on Effect |
|---|---|
Another regular file | The |
FIFO | Either |
Symbolic link |
|
Special device | Usually the |
To be compliant with this rule and to prevent this TOCTOU race condition, file_name must refer to a file in a secure directory (see FIO15-C. Ensure that file operations are performed in a secure directory).
Noncompliant Code Example (Windows)
This noncompliant code example uses the GetFileType() function to attempt to prevent opening a special file:
...
Although tempting, the Win32 GetFileType() function is dangerous in this case. If the file name given identifies a named pipe that is currently blocking on a read request, the call to GetFileType() will block until the read request completes. This provides an effective attack vector for a denial-of-service attack on the application. Furthermore, the act of opening a file handle may cause side effects, such as line states being set to their default voltage when opening a serial device.
Compliant Solution (Windows)
Microsoft documents a list of reserved identifiers that represent devices and have a device namespace to be used specifically by devices [MSDN]. In this compliant solution, the isReservedName() function can be used to determine if a specified path refers to a device. Care must be taken to avoid a TOCTOU race condition when first testing a path name using the isReservedName() function and then later operating on that path name.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static bool isReservedName(const char *path) {
/* This list of reserved names comes from MSDN */
static const char *reserved[] = {
"nul", "con", "prn", "aux", "com1", "com2", "com3",
"com4", "com5", "com6", "com7", "com8", "com9",
"lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6",
"lpt7", "lpt8", "lpt9"
};
bool ret = false;
/*
* First, check to see if this is a device namespace, which
* always starts with \\.\, because device namespaces are not
* valid file paths.
*/
if (!path || 0 == strncmp(path, "\\\\.\\", 4)) {
return true;
}
/* Compare against the list of ancient reserved names */
for (size_t i = 0; !ret &&
i < sizeof(reserved) / sizeof(*reserved); ++i) {
/*
* Because Windows uses a case-insensitive file system, operate on
* a lowercase version of the given filename. Note: This ignores
* globalization issues and assumes ASCII characters.
*/
if (0 == _stricmp(path, reserved[i])) {
ret = true;
}
}
return ret;
} |
Risk Assessment
Allowing operations that are appropriate only for regular files to be performed on devices can result in denial-of-service attacks or more serious exploits depending on the platform.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
FIO32-C | Medium | Unlikely | Medium | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description |
|---|---|---|---|
|
| Could detect some violations of this rule. This rule applies only to untrusted file name strings, and ROSE cannot tell which strings are trusted and which are not. The best heuristic is to note if there is any verification of the file name before or after the | |
5.0 |
|
|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
| [Garfinkel 1996] | Section 5.6, "Device Files" |
| [Howard 2002] | Chapter 11, "Canonical Representation Issues" |
| [IEEE Std 1003.1:2013] | XSH, System Interfaces, open |
| [MSDN] |
...