Analyse d'un 0day sur Solaris 10 si simple qu'on pourrait croire à une backdoor :

Il suffit de se connecter par telnet avec la commande suivante pour se connecter root et sans mot de passe :

$ telnet -l"-froot" vuln_host

Enorme non ? Mais ce problème avait été signalé sur d'autres système Unix il y a plus de 12 ans (plus précisément sur rlogin). Pourquoi apparait il maintenant sur une version récente de Solaris ?

Bon une petite explication s'impose : En général lorsque l'on utilise telnet (hélas telnet est encore beaucoup utilisé) on saisit seulement une option : le nom d'hôte

 $ telnet monjoliserveurlinux

Par la suite on saisi le nom de login puis le mot de passe.

Donc là tout le monde a suivit et a compris que l'exploit c'est d'utiliser l'option -l"-froot". J'ai pas de solaris sous la main mais j'imagine que ça doit marcher également avec -l-froot ou -l -froot...

La question est de comprendre ce qu'est ce -l et -f et comment on arrive root sans mot de passe (!).

L'option -l de telnet permet de spécifier au niveau de la ligne de commande le nom d'utilisateur avec lequel on veut s'identifier sur le site distant. Le protocole telnet permet au client telnet de transmettre des variables d'environnement au serveur. En particulier, le nom de l'utilisateur est transmis au serveur via la variable d'environnement USER.

Si vous voulez en savoir plus sur la négociation et l'échange de variable d'environnement dans le protocole telnet, consultez la RFC 1572 et analysez la capture d'une session telnet avec wireshark.

Donc si vous avez suivi, on transmet au serveur telnet la variable USER=-froot

Le serveur telnetd lance la commande login qui vous permettra de vous authentifier et de vous offrir un shell : telnetd -> login -> sh

Voici comment telnetd lance la commande login via l'appel système execl :

3191 		(void) execl(LOGIN_PROGRAM, "login",
3192			    "-p",
3193			    "-d", slavename,
3194			    "-h", host,
3195			    "-s", pam_svc_name,
3196			    (AuthenticatingUser != NULL ? AuthenticatingUser :
3197			    getenv("USER")),
3198			    0);

Le contenu de la variable USER est mis en paramètre de la commande login sans aucun nettoyage ou autre contrôle (on se croirait dans une application web :-) L'élément le plus important dans cet exploit vient de là. Le contenu de user est -froot donc c'est en réalité une option supplémentaire qui est passée au programme login et non le nom de l'utilisateur.

Maintenant, à quoi sert -f pour le programme login ? Ben tout simplement à s'affranchir de l'authentification.

Voici les modifications apportées à telnetd pour corriger le problème.

3201		    "-p", "-h", host, "-d", slavename, "--",
3202		    getenv("USER"), 0);

le -- permet au programme login (via getopts) de considérer que ce qui suit n'est plus à parser comme des options. Ceci corrige donc le problème. Donc patchez votre système !

La façon dont le problème est traité sous GNU/Linux (netkit-telnet-0.17) :

            if (getenv("USER")) {
                addarg(&avs, getenv("USER"));
                if (*getenv("USER") == '-') {
                    write(1,"I don't hear you!
",19);
                    syslog(LOG_ERR,"Attempt to login with an option!");
                    exit(1);
                }

Alors, backdoor ou pas ?

Pour plus de précision sur l'arrivée de cette faille dans Solaris 10, je vous conseille de lire la discussion sur ce sujet sur bugtraq. Déjà pourquoi ce bug apparait t'il maintenant et pour la première fois sur Solaris ? Un élément de réponse est que la prise en compte par login de l'option -f vient d'apparaitre pour le support de kerberos (ktelnetd). Ceci permet d'exploiter le bug de telnetd qui ne protège pas des injections de paramètres via la variable d'environnement USER. Donc backdoor ou pas ? A vous de juger, certains pensent que oui d'autres qu'il est évident que non. Mais bon, ce qui est sur c'est qu'il faut patcher votre système.

d1cac3 Gaal l3p3t1t