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

Reply via email to