...
The following non-compliant code example opens a file for writing, closes it, opens the same named file for reading, and then closes it again. The logic relies solely on the file name to identify the file.
| Code Block |
|---|
|
char *file_name;
/* initialize file_name */
FILE *fd = fopen(file_name, "w");
if (fd == NULL) {
/* Handlehandle Error */
}
/* Writewrite to file */
fclose(fd);
fd = NULL;
/*
* A race condition here allows for an attacker to switch
* out the file for another
*/
/* ... */
fd = fopen(file_name, "r");
if (fd == NULL) {
/* Handlehandle Error */
}
/* Readread from file */
fclose(fd);
fd = NULL;
|
...
| Code Block |
|---|
|
struct stat orig_st;
struct stat new_st;
char *file_name;
/* initialize file_name */
int fd = open(file_name, O_WRONLY);
if (fd == -1) {
/* Handlehandle Error */
}
/* Writewrite to file */
if (fstat(fd, &orig_st) == -1)) {
/* Handlehandle Errorerror */
}
close(fd);
fd = -1;
/* ... */
fd = open(file_name, O_RDONLY);
if (fd == -1) {
/* Handlehandle Errorerror */
}
if (fstat(fd, &new_st) == -1)) {
/* Handlehandle Errorerror */
}
if ((orig_st.st_dev != new_st.st_dev) ||
(orig_st.st_ino != new_st.st_ino)) {
/* Filefile was tampered with! */
}
/* Readread from file */
close(fd);
fd = -1;
|
...
Because the file is not re-opened, the possibility of an attacker tampering with the file between the writes and subsequent reads is eliminated.
| Code Block |
|---|
|
char *file_name;
FILE *fd;
/* initialize file_name */
fd = fopen(file_name, "w+");
if (fd == NULL) {
/* Handlehandle Error */
}
/* Writewrite to file */
/* ... */
/* Gogo to beginning of file */
fseek(fd, 0, SEEK_SET);
/* Readread from file */
fclose(fd);
fd = NULL;
|
...
In this non-compliant code example, the programmer's intent is to open a file for reading, but only if the user running the process owns the specified file. This is a more restrictive requirement that that imposed by the operating system, which only requires that the effective user have permissions to read the file. The code, however, relies solely on the file name to identify the file.
| Code Block |
|---|
|
char *file_name;
FILE *fd;
/* initialize file_name */
fd = fopen(file_name, "rw+");
if (fd == NULL) {
/* Handlehandle Error */
}
/* Readread user's file */
fclose(fd);
fd = NULL;
|
...
| Code Block |
|---|
|
struct stat st;
char *file_name;
/* openinitialize file_name for reading */
int fd = open(file_name, O_RDONLY);
if (fd == -1) {
/* Handle Error */
}
if ((fstat(fd, &st) == -1) |
(st.st_uid != getuid()) ||
(st.st_gid != getgid())) {
/* Filefile does not belong to user */
}
/*... Readread from file ...*/
close(fd);
fd = -1;
|
...