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