...
Non-Compliant Code Example (device / i-node)
This non-compliant code example code opens and closes a file multiple times. It relies only solely on the file name to identify the file.
| Code Block | ||
|---|---|---|
| ||
FILE *fd = NULL; if ((fd = fopen(file_name, "w")); if (fd == NULL) { /* Handle Error */ } /* Write to file */ fclose(fd); fd = NULL; /* * A race condition here allows for an attacker to switch * out the file for another */ /* ... */ if ((fd = fopen(file_name, "r")); if (fd == NULL) { /* Handle Error */ } /* Read from file */ fclose(fd); fd = NULL; |
There is no guarantee that the file opened for reading is the same file that was opened for writing. An attacker could substitute a malicious file replace the original file (for example, with a symbolic link) between the first fclose() and the second fopen().
...
| Code Block | ||
|---|---|---|
| ||
struct stat orig_st; struct stat new_st; int fd = -1; if ((fd = open(file_name, O_WRONLY)); if (fd == -1) { /* Handle Error */ } /* Write to file */ if (fstat(fd, &orig_st) == -1)) { /* Handle Error */ } close(fd); fd = -1; /* ... */ if ((fd = open(file_name, O_RDONLY)); if (fd == -1) { /* Handle Error */ } if (fstat(fd, &new_st) == -1)) { /* Handle Error */ } if ((orig_st.st_dev != new_st.st_dev) || (orig_st.st_ino != new_st.st_ino)) { /* File was tampered with! */ } /* Read from file */ close(fd); fd = -1; |
...
Non-Compliant Code Example (owner)
This example code runs in a setuid-root program, opening non-compliant code example opens a file for reading. Although it expects the user to own the file, it relies only , relying solely on the file name to identify the file. If this code runs with elevated privileges, for example, as part of a setuid-root program, it can be easily exploited.
| Code Block | ||
|---|---|---|
| ||
FILE *fd = NULL; if ((fd = fopen(file_name, "r")); if (fd == NULL) { /* Handle Error */ } /* Read user's file */ fclose(fd); fd = NULL; |
There is no guarantee that the file opened is the correct file. In fact, the file opened may not even be owned by the user invoking the program. An attacker could use exploit this program to access data they would normally not be privileged to readread a file for which they lack sufficient privilges.
Compliant Solution (POSIX) (owner)
...
This enables the program to recognize if an attacker is passing data they don't control, by ensuring that the file's owner and group matchers the real userid user id and group id.
Alternatively, the same solution could be implemented using the C99 fopen() function to open the file and the POSIX fileno() function to convert the FILE object pointer to a file descriptor.
...