[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Trous de sécurité et BSD-Ftpd



J'ai un serveur FTP sur une passerelle Debian Slink avec paquet potato,
j'utilise bsd-ftpd. Le dernier Nessus m'a révélé de nouveaux trous de
sécurité que je détaille ici:

1) Un CWD ~{ (ou CWD ~...{  de façon générale) plantait le serveur. Cela
est du à un bug dans la glibc2.1.
Solution: Mise à jour en glibc2.2 (cela peut intéresser ceux qui ne font
pas des mises à jour tous les 4 matins sur des machines sensibles)

2) Un ls */../*/../*/../* (répété à l'avis) fait grossir le processus
jusqu'à saturer le swap et planter la machine. Il en est de même de mget
*/../*/../* etc. Cela n'a pas ému le mainteneur du paquet (je ne sais pas
pourquoi). Il est clair que cela vient plutôt de la glibc qui ne limite
pas le nombre de Wildcards. Un simple ls */../* ayant planté le serveur
(il est vrai qu'il n'a que 16M, les finances du lycée etc etc), j'ai fait
un patch limitant le nombre de '*' à 1.

3) Si on fait un repertoire en écriture seule (pas de lecture) (compte
anonyme), il est possible de créer un répertoire qui aura les droits
lecture/écriture. J'ai adopté la solution radicale consistant à interdire
la création de repertoire ainsi que la modification des droits.

Pour ceux qui veulent éliminer ces trous, voilà ci dessous les patchs
apportés.

F.Boisson


Voici les fichiers diff -u sur les fichiers concernés:
Fichier ftpd.c
--- ftpd.c      Tue Oct  8 21:39:04 2002
+++ ../bsd-ftpd-0.3.3.patch2/ftpd.c     Tue Oct  8 13:53:54 2002
@@ -166,8 +166,10 @@
 #ifdef ORIGINAL_SOURCE
 static char version[] = "Version 6.5/OpenBSD";
 #else
-static char version[] = "Version 6.5/OpenBSD, linux port 0.3.3";
+/* static char version[] = "Version 6.5/OpenBSD, linux port 0.3.3"; */
+static char version[] = "Version 6.5 patchée/OpenBSD, linux port 0.3.3";
 #endif /* ORIGINAL_SOURCE */
+#define SA_LEN(_x)    __libc_sa_len((_x)->sa_family)

 extern off_t restart_point;
 extern char cbuf[];
@@ -802,7 +804,7 @@

 static int login_attempts;     /* number of failed login attempts */
 static int askpasswd;          /* had user command, ask for passwd */
-static char *curname;          /* current USER name */
+static char curname[16];       /* current USER name */

 /*
  * USER command.
@@ -877,13 +879,8 @@
 #ifdef ORIGINAL_SOURCE
        if (logging) {
 #endif /* ORIGINAL_SOURCE */
-               if (curname) {
-                       free(curname);
-               }
-               curname = strdup(name);
-               if (!curname) {
-                       fatal("Out of memory");
-               }
+               strncpy(curname, name, sizeof(curname)-1);
+               curname[sizeof(curname)-1] = '\0';
 #ifdef ORIGINAL_SOURCE
        }
 #endif /* ORIGINAL_SOURCE */
@@ -2695,7 +2692,15 @@
        int simple = 0;
        int freeglob = 0;
        glob_t gl;
-
+/* FB: rajout BUG ls /../ * /../ * /../ * */
+        int Bug_ind;
+        int Bug_dec;
+        Bug_dec = 0;
+        Bug_ind = 0;
+/* Pas plus d'un * dans le nom */
+        for(Bug_ind = 0;Bug_ind < strlen(whichf);Bug_ind++)
+          if (whichf[Bug_ind]=='*') Bug_dec++;
+       if (Bug_dec > 1) reply(500, "Pas plus d'un *, bonhomme!");
        if (strpbrk(whichf, "~{[*?") != NULL) {
 #ifdef ORIGINAL_SOURCE
                int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
@@ -2860,10 +2865,7 @@
                if (vpw == NULL)
                        return;

-               if (*name == '/')
-                       snprintf(path, sizeof path, "%s", name);
-               else
-                       snprintf(path, sizeof path, "%s/%s", dir, name);
+               snprintf(path, sizeof path, "%s/%s", dir, name);
                if (realpath(path, rpath) == NULL) {
                        strncpy(rpath, path, sizeof rpath-1);
                        rpath[sizeof rpath-1] = '\0';


et fichier ftpcmd.y
--- ftpcmd.y    Mon Feb 26 17:40:20 2001
+++ ../bsd-ftpd-0.3.3.patch2/ftpcmd.y   Tue Oct  8 13:53:22 2002
@@ -174,8 +174,9 @@
        { "STAT", STAT, OSTR, 1,        "[ <sp> path-name ]" },
        { "HELP", HELP, OSTR, 1,        "[ <sp> <string> ]" },
        { "NOOP", NOOP, ARGS, 1,        "" },
-       { "MKD",  MKD,  STR1, 1,        "<sp> path-name" },
-       { "XMKD", MKD,  STR1, 1,        "<sp> path-name" },
+/* FB: MKD et XMKD chang<E9>s en FMKD et YMKD pour emp<E9>cher la
cr<E9>ation *
/
+       { "FMKD",  MKD,  STR1, 1,       "<sp> path-name" },
+       { "YMKD", MKD,  STR1, 1,        "<sp> path-name" },
        { "RMD",  RMD,  STR1, 1,        "<sp> path-name" },
        { "XRMD", RMD,  STR1, 1,        "<sp> path-name" },
        { "PWD",  PWD,  ARGS, 1,        "(return current directory)" },
@@ -189,9 +190,11 @@
 };

 struct tab sitetab[] = {
-       { "UMASK", UMASK, ARGS, 1,      "[ <sp> umask ]" },
+/* FB: UMASK chang<E9>s en VMASK meme raison */
+       { "VMASK", UMASK, ARGS, 1,      "[ <sp> umask ]" },
        { "IDLE", IDLE, ARGS, 1,        "[ <sp> maximum-idle-time ]" },
-       { "CHMOD", CHMOD, NSTR, 1,      "<sp> mode <sp> file-name" },
+/* FB: CHMOD en FHMOD */
+       { "FHMOD", CHMOD, NSTR, 1,      "<sp> mode <sp> file-name" },
        { "HELP", HELP, OSTR, 1,        "[ <sp> <string> ]" },
        { NULL,   0,    0,    0,        0 }
 };
@@ -581,8 +584,19 @@
                }
        | LIST check_login SP pathname CRLF
                {
-                       if ($2 && $4 != NULL)
-                               retrieve("/bin/ls -lgA %s", $4);
+/* FB: rajout BUG ls /../ * /../ * /../ * */
+                 int Bug_ind;
+                 int Bug_dec;
+                 Bug_dec = 0;
+                 Bug_ind = 0;
+/* Pas plus d'un * dans le nom */
+                 for(Bug_ind = 0;Bug_ind < strlen($4);Bug_ind++)
+                   if ($4[Bug_ind]=='*') Bug_dec++;
+                 if (($2 && $4 != NULL) && (Bug_dec <= 1))
+                   retrieve("/bin/ls -lgA %s", $4);
+                 else
+                   reply(500, "Pas plus d'un *, bonhomme!");
+/*retrieve("/bin/ls -lgA %s", "/"); */
                        if ($4 != NULL)
                                free($4);
                }



Reply to: