Whilst having a look at Vlatko's locking code for ike-scan.nasl I realised that there is a problem in how the fwrite, fread and file_open NASL functions (and quite possibly others) behave.
Because they simply open the requested file without any checks, it is possible to carry out symlink attacks against these functions. I have attached a patch which should I believe resolve the issue but I welcome comments before I commit as to whether a) it resolves the issue correctly and b) whether it will have unwanted side effects. Cheers, Tim -- Tim Brown <mailto:[EMAIL PROTECTED]> <http://www.nth-dimension.org.uk/>
Index: nasl_cmd_exec.c =================================================================== --- nasl_cmd_exec.c (revision 1461) +++ nasl_cmd_exec.c (working copy) @@ -233,7 +233,8 @@ { tree_cell *retc; char *fname; - struct stat st; + struct stat lstat_info, fstat_info; + int fd; char *buf, *p; int alen, len, n; FILE *fp; @@ -246,19 +247,41 @@ nasl_perror(lexic, "fread: need one argument (file name)\n"); return NULL; } - - if (stat(fname, &st) < 0) - { - nasl_perror(lexic, "fread: stat(%s): %s\n", fname, strerror(errno)); + + if (lstat(fname, &lstat_info) == -1) { + if (errno != ENOENT) { + nasl_perror(lexic, "fread: %s: %s\n", fname, strerror(errno)); return NULL; } - - fp = fopen(fname, "r"); - if (fp == NULL) - { + fd = open(fname, O_RDONLY, 0600); + if (fd < 0) { nasl_perror(lexic, "fread: %s: %s\n", fname, strerror(errno)); return NULL; } + } else { + fd = open(fname, O_RDONLY, 0600); + if (fd < 0) { + nasl_perror(lexic, "fread: %s: possible symlink attack!?! %s\n", fname, strerror(errno)); + return NULL; + } + if (fstat(fd, &fstat_info) == -1) { + close(fd); + nasl_perror(lexic, "fread: %s: possible symlink attack!?! %s\n", fname, strerror(errno)); + return NULL; + } else { + if (lstat_info.st_mode != fstat_info.st_mode || lstat_info.st_ino != fstat_info.st_ino || lstat_info.st_dev != fstat_info.st_dev) { + close(fd); + nasl_perror(lexic, "fread: %s: possible symlink attack!?!\n", fname); + return NULL; + } + } + } + fp = fdopen(fd, "r"); + if(fp != FALSE) { + close(fp); + nasl_perror(lexic, "fread: %s: %s\n", fname, strerror(errno)); + return NULL; + } alen = st.st_size + 1; buf = emalloc(alen); @@ -338,6 +361,8 @@ { tree_cell *retc; char *content, *fname; + struct stat lstat_info, fstat_info; + int fd; int len, i, x; FILE *fp; @@ -356,12 +381,41 @@ } len = get_var_size_by_name(lexic, "data"); - fp = fopen(fname, "w"); - if (fp == NULL) - { + if (lstat(fname, &lstat_info) == -1) { + if (errno != ENOENT) { nasl_perror(lexic, "fwrite: %s: %s\n", fname, strerror(errno)); return NULL; } + fd = open(fname, O_WRONLY|O_CREAT, 0600); + if (fd < 0) { + nasl_perror(lexic, "fwrite: %s: %s\n", fname, strerror(errno)); + return NULL; + } + } else { + fd = open(fname, O_WRONLY|O_CREAT, 0600); + if (fd < 0) { + nasl_perror(lexic, "fwrite: %s: possible symlink attack!?! %s\n", fname, strerror(errno)); + return NULL; + } + if (fstat(fd, &fstat_info) == -1) { + close(fd); + nasl_perror(lexic, "fread: %s: possible symlink attack!?! %s\n", fname, strerror(errno)); + return NULL; + } else { + if (lstat_info.st_mode != fstat_info.st_mode || lstat_info.st_ino != fstat_info.st_ino || lstat_info.st_dev != fstat_info.st_dev) { + close(fd); + nasl_perror(lexic, "fread: %s: possible symlink attack!?!\n", fname); + return NULL; + } + } + } + fp = fdopen(fd, "w"); + if (fp != FALSE) { + close(fp); + nasl_perror(lexic, "fread: %s: %s\n", fname, strerror(errno)); + return NULL; + } + for (i = 0; i < len; ) { x = fwrite(content + i, 1, len - i, fp); @@ -445,6 +499,7 @@ { tree_cell *retc; char *fname, *mode; + struct stat lstat_info, fstat_info; int fd; int imode = O_RDONLY; @@ -475,12 +530,34 @@ else if ( strcmp(mode, "a+") == 0 ) imode = O_RDWR|O_APPEND|O_CREAT; - fd = open(fname, imode, 0600); - if ( fd < 0 ) - { + if (lstat(fname, &lstat_info) == -1) { + if (errno != ENOENT) { nasl_perror(lexic, "file_open: %s: %s\n", fname, strerror(errno)); return NULL; } + fd = open(fname, imode, 0600); + if (fd < 0) { + nasl_perror(lexic, "file_open: %s: %s\n", fname, strerror(errno)); + return NULL; + } + } else { + fd = open(fname, imode, 0600); + if (fd < 0) { + nasl_perror(lexic, "file_open: %s: possible symlink attack!?! %s\n", fname, strerror(errno)); + return NULL; + } + if (fstat(fd, &fstat_info) == -1) { + close(fd); + nasl_perror(lexic, "fread: %s: possible symlink attack!?! %s\n", fname, strerror(errno)); + return NULL; + } else { + if (lstat_info.st_mode != fstat_info.st_mode || lstat_info.st_ino != fstat_info.st_ino || lstat_info.st_dev != fstat_info.st_dev) { + close(fd); + nasl_perror(lexic, "fread: %s: possible symlink attack!?!\n", fname); + return NULL; + } + } + } retc = alloc_typed_cell(CONST_INT); retc->x.i_val = fd;
_______________________________________________ Openvas-devel mailing list Openvas-devel@wald.intevation.org http://lists.wald.intevation.org/mailman/listinfo/openvas-devel