...
| Wiki Markup |
|---|
Performing operations on device files that are intended for ordinary character or binary files can result in crashes and denial-of-service attacks. For example, when Windows attempts to interpret the device name as a file resource, it performs an invalid resource access that usually results in a crash \[[Howard 02|AA. C References#Howard 02]\] . |
Non-Compliant Code Example
In this example, the user can specify a locked device or a FIFO filename, causing the program to hang on the call to open().
| Code Block |
|---|
|
if (!fgets(filename, sizeof(filename), stdin)) {
/* handle error */
}
if (open(filename, O_WRONLY) == -1) {
/* handle error */
}
|
Compliant Solution (POSIX)
| Wiki Markup |
|---|
Device files in UNIX can be a security risk when an attacker is able to access them in an unauthorized way. For instance, if attackers can read or write to the {{/dev/kmem}} device, they may be able to alter their priority, UID, or other attributes of their process or simply crash the system. Similarly, access to disk devices, tape devices, network devices, and terminals being used by others all can lead to problems \[[Garfinkel 96|AA. C References#Garfinkel 96]\]. |
...
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.
Non-Compliant Code Example
In this example, the user can specify a locked device or a FIFO filename, causing the program to hang on the call to open().
| Code Block |
|---|
|
if (!fgets(filename, sizeof(filename), stdin)) {
/* handle error */
}
if (open(filename, O_WRONLY) == -1) {
/* handle error */
}
|
Compliant Solution (POSIX)
Programmers can use the POSIX stat() function to obtain information about a named file, and the S_ISREG() macro to determine if the file is a regular file. Additionally, the O_NONBLOCK flag to open() will ensure that delayed operations on the file do not hang the program.
| Code Block |
|---|
|
struct stat pre_s;
struct stat post_s;
int fildes;
if (!fgets(filename, sizeof(filename), stdin)) {
/* handle error */
}
if ((stat(filename, &pre_s) != 0) || (!S_ISREG(pre_s.st_mode))) {
/* handle error */
}
/* due to a race condition here, we will verify with fstat later */
if ((fildes = open(filename, O_NONBLOCK, O_WRONLY)) == -1) {
/* handle error */
}
if (fstat(fildes, &post_s) != 0) {
/* handle error */
}
if(!(pre_s.st_mode == post_s.st_mode &&
pre_s.st_ino == post_s.st_ino &&
pre_s.st_dev == post_s.st_dev)) {
/* handle error */
}
/* operate on file */
|
...