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);
                }

Répondre à