Chrooter apache
Matériel
Ajout disque dur
Ajout carte
Audit des disques durs
Gestion des peripheriques
Disquette d'installation
Ajout d'un scanner
Astuces
Ajout d'une imprimante
Réseau
Configuration reseau
Dns
Serveur cvs
Proxy squid 
Installation serveur ftp
Installation qmail 
Installation serveur courrier sous debian
Outil TCP/IP 
Le serveur samba
Connexion a distance securisee
Client/serveur vnc
Configurer apache
Dyndns
Installer un LAMP sous mandriva
Sécurité
Chiffrer un fichier/dossier
Securiser son poste
Mur pare feu pas a pas
Authentification ht-access
Surveillance de serveur CACTI
Snort
Snort-inline
Securiser Apache avec mod_security
Filtrage squid/squidguard/dansguardian
Auditer son site web
Sécuriser son linux
Installer un Lamp avec ssl
Contrer les scans de ports
Traitement anti-spam
Installer/Utiliser tripwire
Faire des sauvegardes incrémentales
Rsync
Nessus
Divers
Elisa, le multimédia facile
Utilisation de lilo
Les commandes Linux
Le multi-tache
Le crontab
Exploration de la configuration
Quotas
Messagerie
Installer une application
Debugger ses applications
Le format RPM
Mise a jour du noyau
Qemu
Tour d'horizon des principaux p2p
Récupération du système
Bips d'un pc
Astuces windows
Table Ascii
Lamerland
Conversion de fichiers musicaux
Compiler ses rpms
Graver en ligne de commande
Graver un fichier avi pour un dvd de salon
Récupérer des fichiers effacés
Liens
hakin9
Secureroot.com
Hackerthreads.org
Defcon
Hackerlounge
Les derniers exploits
Tous les codes sources
Securite sous Linux
Les logiciels libres quotidiens
Ezine divers
Madchat
Textes divers
Archives
 
Traductions LG
Toutes les traductions
Traductions Phrack
Toutes les traductions

Il y a actuellement 8 visiteurs connectés sur le site !

Google

Securiser ses scripts PHP
Securiser ses scripts PHP

 

Introduction
Les failles de PHP
Vulnerabilite 'escape shell'
Fonction include()
Fonction mail()
Les fichiers de logs de Apache
Script d'upload
PHP & MySQL
Requetes MySQL multiples
Fakes posts
Stupid DoS
Bypasser une authentification

 

Introduction

Le PHP est un language de script executé coté serveur spécialement concu pour le developpement web, dont le créateur est Rasmus Lerdorf au début de 1995. Il est possible de créér des utilitaires simples (livre d?or, compteur, forum, formulaires, etc.).. Ainsi de part la multitude de ses fonctions, le PHP offre aussi la possibilite d'obtenir des informations, voire meme un acces (partiel ou complet) au systeme. Des notions de sécurité sont donc necessaires à tout administrateur

Les failles de php

Vulnerabilite escape shell

Le language PHP possede une fonction 'system()' permettant d'utiliser directement des commandes systemes. Ainsi il est evident que cette fonction peut s'averer dangereuse puisque si l'attaquant reussi e detourner un script utilisant cette fonction, il gagne un acces partiel, voire meme complet (euh ca existe encore des httpd avec les droits root :p). Voyons tout d'abord un schema classique. Le webmaster desire afficher l'uptime de son server, dans le cadre d'une page de statistique. Il pourra alors porceder ainsi :

<? echo system("uptime"); >?
Ce qui affichera au client http une ligne dans ce genre :

4:00am up 1 day, 5:02, 3 users, load average: 0.00, 0.03, 0.00
Cependant imaginez que le webmaster en question desire passer ses commandes dans des variables, en pensant que cela lui facilitera la lecture de son script, ou pour n'importe quelle autre raison. Il procedera alors ainsi

<?
system($cmd);
>?

Si nous le consultons de cette maniere : http://subkulture/system.phpecmd=uptime, le serveur nous affichera le meme type de resultat que precedemment. Cependant il suffit que nous modifions la variable $cmd par une autre commande pour voir apparaitre tout autre chose :
http://subkulture/system.phpecmd=cat%20/etc/issue
[ Resultat : ] Red Hat Linux release 7.1 (Seawolf) Kernel 2.4.2-2 on an i686
Ainsi comme vous pouvez le constater, si nous detournons la variable $cmd, nous pouvons nous servir de la page script PHP comme un remote shell ayant les droits du daemon httpd.
Il est evident que cette faille est flagrante et que n'importe quel webmaster faisant appel e la fonction system() n'utilisera pas la deuxieme methode.
Cependant il existe une seconde possibilite de detourner cette fonction. Imaginons qu'un site web veuille fournir e ses usagers un services comme traceroute par exemple. Il pourra utiliser une page munie d'un formulaire HTML pour recuperer une IP, puis concatener cette IP avec une autre chaine de caractere, pour enfin executer la commande voulue. Petit exemple :

<?
$cmd = "traceroute ".$cmd;
system($cmd);
>?

Ainsi, en entrant comme valeur 'www.yahoo.com' nous obtiendrons un resultat de ce style :
traceroute: Warning: www.yahoo.com has multiple addresses; using 64.58.76.179
traceroute to www.yahoo.akadns.net (64.58.76.179), 30 hops max, 38 byte packets
...
9 gblon523-tc-p8-0.ebone.net (213.174.71.65) 52.138 ms 47.755 ms 47.945 ms
10 usnyk405-tc-p3-0.ebone.net (213.174.70.58) 115.571 ms 116.682 ms 119.300 ms
11 usnyk105-tc-r2-0.ebone.net (213.174.69.162) 119.398 ms 115.842 ms 119.985 ms
12 ebone-px-jrcy01.exodus.net (195.158.229.130) 120.114 ms 116.874 ms 119.346 ms
...

Imaginez maintenant que nous entrions comme requete 'www.yahoo.com | nmap localhost'. Le script PHP effectuera d'abord la premiere commande, e savoir 'traceroute www.yahoo.com', puis il ne concatenera pas la deuxieme commande avec 'traceroute ', et de ce fait elle sera executee. On aura alors un resultat de ce type :

Starting nmap V. 2.54BETA29 ( www.insecure.org/nmap/ )
Interesting ports on subkulture (127.0.0.1):
(The 1545 ports scanned but not shown below are in state: closed)

...Il est donc, comme nous l'avons vu, possible de corrompre le systeme ou encore utiliser des programmes; cependant il est beaucoup plus pratique pour une question de lecture des donnees, d'utiliser cette methode dans le but d'obtenir un maximum d'information sur le serveur (version du kernel, port ouvert, distribution ...).
Voyons maintenant comment resoudre cette faille. Dans le premier cas, il est possible de creer un script de parsing des commandes envoyees, cependant cette methode n'est pas envisageable, vu la quantitee de commandes *nix existante. Cependant une methode relativement simple consiste e ne pas placer les commandes dans des variables, ou alors faire une definition de la variable ($cmd= "uptime").
Dans le second cas, la solution la plus simple consiste e reperer le caractere pipe '|' et arreter le script. Attention, ne pas oublier d'effectuer une recherche sur l'equivalent du pipe en URL-Encode (e savoir %7c)
.N'oublions pas que cette methode fonctionne aussi avec les caracteres & (and) ou encore ; (point virgule). Il faut donc aussi parser notre requete pour ces memes caracteres.

Exemple pour le caractere 'pipe' :
if( (strstr($cmd, "|")) || (strstr($cmd, "%7c") ) { echo "Erreur : caractere interdit !";
break(); }

La fonction include()

La fonction include permet, comme son nom l'indique, d'inclure le contenu d'un fichier dans un script php. Cette fonction est dans la plupart utiliser pour creer des pages dynamiques a proprement parler, comme par exemple en incluant un fichier de configuration. Ainsi, une page pourrait s'organiser de la fa?on suivante :

<? include("config.php");
include("header.php");
if(file_exists($page))
include($page);
else
include("erreur404.php");
include("footer.php");
>?

Appel de la page : http://subkulture/index.php?page=news.php

Ce code est assez simple a comprendre : le script PHP inclut un fichier de configuration et le header de la page (contenant diverses informations comme le titre, les feuilles de style ....), puis il verifie si le fichier contenu dans la variable $page existe, et l'inclut (ou inclut une page d'erreur 404 si il n'existe pas).
Enfin le script inclut le footer (contenant les fermetures de balise par exemple).Ainsi il est assez simple de detourner le script en modifiant le contenu de la variable par un fichier 'sensible' :

http://subkulture/index.php?page=../../../../../etc/inetd.conf
(la plupart des serveur utilsant encore inetd et pas xinetd)Comem vous pouvez le constater cette failles permet une fois encore d'obtenir des informations sur le serveur. Il est donc evident que plus un attaquant a d'information sur votre systeme, plus celui ci aura de chance de s'introduire dans ce systeme. Pour securiser une faille de ce genre, la possibilite la plus simple reste une fois encore d'intervenir directement au niveau du script, par exemple ajoutant une extension au fichier a consulter :

<? include("config.php");
include("header.php");
$page = $page.".php"; // Ajout d'une extension .php
if(file_exists($page))
include($page);
else
include("erreur404.php");
include("footer.php");
>?

ou encore de parser certains caracteres comme les slash, pour eviter le changement de repertoire :
$page = ereg_replace("/","subk"); // Modification de '/' par 'subk'
$page = ereg_replace("%2f","subk); // Idem mais avec l'equivalent unicode de / (%2f)
UNe autre solution serait d'intervenir directement au niveau du systeme, en changeant les authorisation des utilisateurs (chown), pour eviter que l'user 'httpd' ne puisse acceder aux fichier en dehors de sa racine (htdocs). Pour plus d'information man chown :).

La fonction mail()

La fonction mail() permet d'envoyer des emails par l'intermediaire d'un script PHP. Il n'existe pas vraiment de 'failles' utilisables avec cette fonction, cependant il est possible de l'utiliser dans le but de spamer/mailbomber des emails.Il est evident que vous n'utiliserez pas cette fonction a cet usage, cependant si vous hebergez des sites web, il est possible que vos utilisateurs soient tente de detournerl'utilisation normale de cette fonction en pensant que c'est votre IP qui apparaitra dans les headers des mails. En effet, un mailbomber est un script tres facile a mettre en place.

Exemple :
<? $to = "victim@troll.com";
$subject = "graou";
$message = "I'm a stupid kiddiez";
for($i=0;
$i<5000; $i++) {
mail($to, $subject, $message);
}
>?

Pour eviter que l'un de vos utilisateur n'effectue des spam/mailbomb, le plus simple et le plus efficace est de desactiver cette fonction. Cependant a la maniere de certains hebergeurs, vous pouvez aussi recoder une fonction mail personnalisee, que vous nommerez par exemple email().

Les fichiers de logs de Apache

Comme nous l'avons vu plus haut la fonction include() permet d'inclure un fichier dans un script PHP. Cependant, il existe une autre methode pour exploiter cette fonction. Cette methode permet non pas d'afficher le contenu de certains fichiers sensibles, mais d'obtenir un acces partiel voire complet au systeme (comme toujours, cela depend des droits du daemon http). Reprenons ainsi le meme exemple que precedemment :

<?
include("config.php");
include("header.php");
if(file_exists($page)) include($page);
else
include("erreur404.php");
include("footer.php");
>?

Tout d'abord, il nous faut verifier que le script permet le passage de path en argument. Dans notre exemple, cela est possible, a moins que les repertoire a ete chown correctement.

Pour savoir si cela est possible, ne specifiez pas de valeur pourla variable $page : http://www.subkulture.org/index.php?page=
Verifiez alors le message d'erreur renvoye par PHP. S'il s'agit d'un message de ce type : 'Fatal error: input in flex scanner failed in /home/www/subkulture on line 1', c'est que le script acceptera le passage de path en argument.
Voyons maintenant la faille en question Comme vous pouvez le constater il serait bien simple d'exploiter lafaille afin de recuperer le fichier/etc/passwd du serveur. Ainsi http://www.subkulture.org/index.php?page=/etc/passwd donnera un resultat de ce genre : root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin: daemon:x:2:2:daemon:/sbin:

Cependant comme vous pouvez le constater, la plupart des /etc/passwd sont shadowed de nos jours, et donc cette methode n'est pas efficace. Par contre nous pouvons tout de m?me nous servir de cette methode pour gagner des informations sur le serveur en question comme nous l'avons vu plus haut.

http://www.subkulture.org/index.php?page=/etc/inetd.conf
http://www.subkulture.org/index.php?page=/etc/issue
http://www.subkulture.org/index.php?page=/etc/motd
[ ... ]
Voyons maintenant la methode qui nous permettra d'obtenir un remote shell sur le serveur (avec les permissions du serveur http bien sur). Tout d'abord localisons le fichier de log de apache :

http://www.subkulture.org/index.php?page=/usr/local/apache/conf/httpd.conf. Je ne vais pas afficher tout le fichier log ici, car celui ci est trop long. Voici donc seulement la partie qui nous interesse :
DocumentRoot /home/www/subkulture
ServerName subkulture.org
ScriptAlias /cgi-bin/
/home/www/subkulture/cgi-bin/subkulture
ErrorLog
logs/subkulture.org-error_log
CustomLoglogs/subkulture.org-access_log combined
ServerAdmin webmaster@subkulture.org
Consultons le fichier qui log les requetes
http qui ont provoque une erreur (subkulture.org-error_log ) :
[ ... ]
[Wed Jun 6 12:12:29 2001] [error] [client 148.100.206.196] File does not exist: /home/www/subkulture/images/subk.jpg [ ... ]

Voyons maintenant ce qui se passe lorsque nous tentons des requetes qui ne peuvent pas marcher, comme par exemple un code PHP :
http://www.subkulture.org/<?echo"subkulture";>? -- ce qui donnera dans le fichier log :
[Tue Jul 24 21:39:30 2001] [error] [client xxx.xxx.xxx.xxx] File does not exist:
/home/www/subkulture/

L'idee etait de faire en sorte d'introduire un code PHP dans le fichier subkulture.org-error_log, puis de consulter le fichier log grace au script vulnerable, dans le but d'executer ce code. A premiere vu cela ne marche pas. Pourtant, si l'on cherche mieux, on se rend vite compte qu'il est possible de balancer du code en convertissant notre requete en URL-Encode. Voici donc un petit code en C qui fonctionne tres simplement : vous l'executez, et il vous donne un prompt. Vous entrez votre char et le programme vous affiche sont equivalent en URL-Encode :

a2h.c : convertit un char ascii en un char url-encode : /*
a2h.c - medgi : subkulture 2001 */
#include
#include

int main() {
char subk;
printf("Entrez un char:\t");
scanf("%c", &);
printf("%%%x",subk);
return 0;
}

Nous allons maintenant transformer une requete telle que

<? system("ls -al");>?

en URL-Encode, ce qui donne
%3c%3f%20system%28%22ls%20%2dal%22%29%3b%20%3f%3e.
Etudions maintenant le resultat de nos requetes URL-Encodees :
http://www.subkulture.org/%3c%3f%20system%28%22ls%20%2dal%22%29%3b%20%3f%3e
# permet de placer notre code dans le fichier subkulture.org-error_log
http://www.subkulture.org/index.php?page=/usr/local/apache/logs/subkulture.org-error_ log # Nous consultons le fichier subkulture.org-error_log.
RESULTATS :
[Tue Jul 24 22:12:30 2001] [error] [client xxx.xxx.xxx.xxx] File does not exist:
/home/www/subkulture/total 408
drwxr-xr-x 7 mariston mariston 4096 Mar 19 19:18 .
drwxr-xr-x 30 mariston mariston 4096 Jul 20 15:34 ..
-rw-r--r-x 1 mariston mariston 20992 Nov 15 2000 Donnelly_Tragedy.doc
drwxr-xr-x 2 mariston mariston 4096 Nov 15 2000 MRtoilet
-rw-r--r-x 1 mariston mariston 4109 Nov 15 2000 MRtoilet_article
-rw-r--r-x 1 mariston mariston 2123 Nov 15 2000 MRtoilet_review.htm
-rw-r--r-x 1 mariston mariston 403 Aug 23 2000 archive_list_ls
drwxr-xr-x 2 mariston mariston 4096 Aug 23 2000 barpics
-rw-r--r-x 1 mariston mariston 9220 Sep 14 2000 bars.html
-rw-r--r-x 1 mariston mariston 20115 Nov 15 2000 bathroom_wall.jpg
-rw-r--r-x 1 mariston mariston 10635 Oct 10 2000 bathrooms
-rw-r--r-x 1 mariston mariston 4415 Sep 6 2000 bookstore.html
[ ... ]

Comme vous pouvez le constater, si nous inserons du code PHP dans les fichiers error-logs, puis que nous consultons ces fichier par l'intermediaire de Apache, le code qui a ete depose va ?tre interprete par PHP. Ainsi, l'attaquant aura plusieures possibilitees : envoyer une requete avec la fonction system() pour obtenir un 'pseudo-shell', ecrire uen backdoor PHP dans un fichier (voir plus loin), modifier des fichiers du htdocs, ... Bref il s'agit la d'une faille tres importante, surtout si votre Apache tourne en root (ahem !). Pour resoudre ce probleme d'execution de code, il vous suffit de proceder comme avec la fonction include(), a savoir changer les permissions pour le repertoire, parser les slash. Pour plus de surete, vous pouvez aussi installer apache dans un autre path que celui habituel

Scripts d'upload

Les scripts d'upload de fichiers sont vraiment tres pratique, puisqu'il permette d'effectuer une mise a jour tres rapide, et d'autant plus rapide si les donnees sont geres avec une base de donnee comme par exemple MySQL. Ainsi, il est normal de constater que beaucoup de site aient recours a de tels scripts. Cependant, il existe plusieures vulnerabilitees liees a ce type de script.Pour mieux comprendre comment fonctionne un script d'upload en PHP, voici un petit extrait de code (extrait de l'advisory de zorgon a ce sujet) :

$uploaddir = "./uploadfiles";
if(ereg("^\.", "$filename_name") || ereg("[ %/,;:+~#````'$%&\\()?!^|\]\[]", $filename_name)) { ... }
elseif(file_exists("$uploaddir/$filename_name"))
{
...
}
elseif($filename_size <= $max_uploadsize)
{
copy($filename, "$uploaddir/$filename_name");
...
}

La variable $uploaddir contient le repertoire ou seront stocke les fichiers uploades. La premiere condition verifie les caracteres contenu dans le nom du fichier a uploader, puis execute une instruction (non presente ici) si ils sont present, a savoir un message d'erreur affichant que ces caracteres ne sont pas authorises.
La seconde condition verifie que le fichier que nous voulons uploader n'existe pas deja,dans le but d'eviter d'ecraser ce fichier. Si il existe deja, le script affichera unmessage d'erreur, puis un break. Enfin la derniere condiftion verifie que la tailledu fichier que nous voulons uploader est inferieure a la taille maximale authoriseepour un fichier. Si cette condition est remplie, le script copiera le fichier filedans /uploadfiles/file.Comme vous pouvez le constater, le script ne presente aucuncontrole de verification de l'extension. Ainsi il est possible aussi bien d'uploaderdes .png que des .txt.
Cependant la faille existe lorsque nous uploadons un fichier avec l'extension .php, .php3 ou encore .cgi (tout depend de la configuration du serveur). En uploadant un fichier avec une des ces extensions, nous pourrons alors excuter le code contenu dans ces fichiers, par le biais de notre navigateur.
A partir de ce point la, l'attaquant dispose de plusieurs methodes d'attaques, toutes baseessur le m?me principe.Tout d'abord il peut creer un petit script utilisant la fonction copy(). Ce script aura pour effet de copier le contenu d'un fichier PHP dans un fichier texte. Ainsi il sera possible d'obtenir le code source du fichier PHP copie.
L'inter?t de cette methode est qu'aujourd'hui la plupart des sites utilisant PHP ont recours a des bases de donnees, protegees par un systeme de login/password. Ce login/password doit ?tre stipule dans le code source pour que la connexion a la base de donnee puisse s'effectuer. Ainsi en recuperant le code source d'un script PHP, l'attaquant risque aussi de recuperer un ou des login/password de MySQL par exemple. Voici un petit exemple de script PHP a uploader :

<?
copy("page.php","page_source.txt"); >?



Il suffit maintenant a l'attaquant de consulter le fichier page_source.txt pour recuperer vos mots de passe d'administration de MySQL.
La deuxieme methode d'attaque est basee sur le m?me principe, mais est legerement plus complexe. Il s'agit la de gagner un acces au systeme lui m?me en creant une backdoor PHP. Il ne faut pas oublier que PHP offre des fonctions gerant les connexions sockets, et que donc toute sortes de scripts genant pour l'administrateur peuvent exister : bot IRC, backdoor, scanner de port, ....Pour resoudre ce probleme il existe, une fois encore, plusieures solutions. Tout d'abord, il est conseille soit de rajouter une extension, soit de parser les extensions. Voici donc deux exemple :

$filename = $filename.".subk"; # Rajoute l'extension .subk
if( ereg("php$", $filename) || ereg("php3$", $filename) || ereg("cgi$", $filename) ) { # Verifie l'extention de $filename
echo "Type de fichiers interdits pour raison de securite !";
break();

}Une autre methode serait de faire en sorte que l'attaquant n'aie pas acces au repertoire d'upload (/uploadfiles dans notre exemple). Pour ce faire utiliser les .htaccess de Apache par exemple, ou encore placez ce repertoire en dehors de la racine du httpd (htdocs).

PHP & MySQL

Requetes MYSQL multiples

MySQL est un systeme de base de donnees facile a utiliser, et de se fait la plupart des scripts PHP utilise MySQL pour gerer leurs donnees. La faille qui suit existe non seulement pour PHP, mais pour beaucoup d'autre languages tels que l'ASP, le CFM ou encore le JSP. Voyons tout d'abord comment fonctionne un script avec MySQL :

$table ="newsletter":
$query = "SELECT * FROM $table";
$result = mysql_query($query);
[ ... ]

Le systeme est simple : au debut de chaque script, il faut etablir une connexion a la base de donnees MySQL. Pour cela nous utilisons la fonctions mysql_connect(), avec comme argument un login et un password. Ensuite il faut selectionner une base de donnee avec la fonction mysql_select_bdd().
Une fois ces etapes remplies, il faudra selectionner le nom d'une table. La table est un tableau contenant differente donnees. Dans notre exemple il s'agit de newsletter, qui contient deux champ : nom de l'utilisateur et email. De meme pour inserer quelqu'un dans cette meme table nous pourrions effectuer un code comme ceci, ou $nom est le nom d'utilisateur et $email son email. [ ... ]

$table ="newsletter": $query = "INSERT INTO $table ('$nom', '$email')";
$result = mysql_query($query); [ ... ]
Rien de bien complique n'est ce pas ? De plus il faut savoir que MySQL est aussi capable d'effectuer deux requetes en meme temps. Ainsi pour inserer deux lignes dans une table MySQL, nous pourrions proceder ainsi :

$query = "INSERT INTO newsletter('subkulture', 'subkulture@unixlover.com');
INSERT INTO newsletter ('medgi', 'medgi@ht.st')";
$result = mysql_query($query);

C'est la que le premier probleme se pose : imaginez en effet que nous ayons un formulaire d'inscription qui a comme input nom et email.
Rentrons alors des valeures comme ceci : [ NOM ] medgi [ MAIL ] 'medgi@ht.st'); INSERT INTO newsletter ('subkulture','subkulture@unixover.com')
Le script recevra donc une requete double qui sera inseree dans la table 'newsletter'. Dans cette exemple, l'attaque a tres peu d'inter?t, si ce n'est surcharger la table MySQL.
Bien sur nous pourrions effectuer d'autres requete comme par exemple "SELECT * FROM login" cependant cela ) la aussi peu d'interet et ce pour deux raison : tout d'abord, il n'est pas sur que la table login existe, et ensuite meme si la requete MySQL recuperera tout le contenu de la table login (login/password/telephone/email/...), cela ne sera pas forcement disponible pour nous.
En effet, l'affichage de donnee MySQL se fait en general ainsi : nous recuperons les champs qui nous interesse par leur nom ($nom, $email, $password, ...) puis nous les affichons.
Cependant si par exemple la page que nous desirons attaquer est une page d'enregistrement, aucune fonction ne sera preseente pour l'affichage de donnees. Ainsi la deuxieme requete que l'attaquant effectuera, n'affichera en general pas les donnees que celui ci attend. Le probleme vient du fait qu'avec MySQL, il est aussi possible d'effectuer des requetes effacant une ligne, voir toute la table. Ainsi dans notre exemple precedent si nous rentrions une requete comme celle la :
[ NOM ] medgi [ MAIL ] 'medgi@ht.st'); DROP TABLE newsletter

Toute la table newsletter serait effacee, et c'est la que cette methode devient dangereuse. Voyons donc comment securiser vos scripts.
Le probleme vient de la requete passee par un champ de forumlaire, il suffit donc de parser la variable de ce formulaire, pour eviter toute mauvaise requete. Pour cela il suffit d'utiliser la fonction addslashes(), qui rajoutera un backslash '\' devant les caracteres suivant : quote ("), apostrophe (') et backslash(\).
Voici donc une partie de code pour parser votre variable :

$nom = addslashes($nom);
$email = addslashes($email);
# Definition de la requete : $query = "INSERT INTO $table ('$nom', '$email');

Vous pouvez aussiactiver l'option MAGIC_QUOTES dans votre php.ini (MAGIC_QUOTES = on).

fake posts

La plupart des moteurs de news actuels laissent la possibilte a leur utilisateurs de poster des commentaires. Dans certains scripts, l'utiisateur doit s'authentifier, et donc laisser ses coordonees, ce qui limite le nombre de personne indesirable, voir mal intentionnee. Cependant il existe des sites qui permettent de poster des commentaires s'en s'identifier. C'est ce cas precis qui interessera un attaquant. Ainsi voici un extrait de code qui s'averera vulnerable :

if ( $action=="ajout" )
{ $date=date("Y/m/d H:i");
$ajout_sql = mysql_query("insert into $table (nom, auteur, email, texte, date) values ('$nom', '$auteur', '$email', '$texte', '$date')",$connexion);
}

Comme vous pouvez le constater, le formulaire transmet a la page de script une variable 'hidden'. Si son contenu est ajout, le scripts executera une requete d'ajout dans la base de donnee. Le nom de la table est variable, et correspond au numero de la news : si il s'agit d'un commentaire pour la news 40, le nom de la table sera par exemple news_40. Dans cet exemple je ne comprend pas vraiment comment le devellopeur a fait pour faire un script aussi insense, il n'empeche que celui ci existe :) !Voici donc la pseudo-faille, qui va vous paraitre inutile certes, mais qui peut s'averer agacante pour le webmaster. L'attaquant va poster un commentaire "fantome". Ainsi imaginons que la requete pour ajouter une news soit :

http://subkulture/addcommentaire.php?newsID=40&nom=medgi&email=medgi@ht.st&texte=subk ulture%200wnz%20y0u.

Si la news numero 40 existe, le commentaire va ?tre poste. Cependant si la news numero 40 n'existe pas, la news va quand meme ?tre postee (erf) :) !Comme vous pouvez le constater, il est ainsi possible de poster des commentaires sur des news qui n'existe pas. Peu d'inter?t certes, cependant le webmaster soucieux de son site doit vite ?tre agace de ces posts de gamin. Ainsi pour securiser ce petit bug, rien de plus simple :

$query = "SELECT * FROM table_news";
$requete = mysql_query($query);
$nb = mysql_numrows($requete);
if ( ($action=="ajout") && ($newsID < $nb) ) {
$date=date("Y/m/d H:i");
$ajout_sql = mysql_query(...);

}

En passant, si quelqu'un tombe sur un script qui presente le m?me bug, qu'il me l'envoie parce que m?me si je comprend les grandes lignes du raisonnement, je ne vois vraiment pas comment on peut construire un script de commentaire sur une architecture aussi tordu :).

stupid dos

Le principe est similaire a celui plus haut : imaginez que l'attaquant peut poster des commentaires pour des news qui n'existe pas, et ceci sans identification. Il peut alors en poster 1, 2 voire 5000. Cependant au bout d'un certain nombre de requete la base de donnees commence a legerement surchargee. Ainsi imaginons un code source
comme celui ci (en C) :

[ ... ]
int i; char buffer[] = "POST
/commentaire.php?newsID=40&nom=el8&email=fuck@fuck.com&texte=im%20a%20stupid%20kiddie z HTTP/1.0\n\n";
for(i=0; i=5000; i++) {
send(socket, buffer, strlen(buffer); } [ ... ]

Je n'ai pas donne ici le code source entier, pour eviter que les troll le reprenne, cependant il s'agit la d'un code tres facile a mettre en place, et qui peut s'averer ennuyeux : imaginez que votre base de donnee MySQL soit deficiente pendant tres longtemps suite a des attaques repetees : cela peut s'averer tres ennuyant, surtout que la plupart des sites web sont gere avec MySQL ! Voici donc une petite solution : sachant que les requete sont envoyees sur le port 80 (http), et donc passent par apache, il vout suffit de modifier une ligne dans votre httpd.conf :

MaxKeepAliveRequests 100
Sachant que si vous mettez la valeure a 0 cela permettra unnombre ilimite de requete, tandis que si vous mettrez la valeure a un nombre plus haut, cela permettra de reduire le nombre de requetes. Tout depend donc du type de serveur que vous utilise : parametrez en fonction de vos statistiques (mettre la valeur a 0 alors qu'il s'agit d'un serveur personnel destine au test de script PHP serait ridicule !). Je n'ai pas trouve d'autres solutions a ce probleme, si vous avez une idee, mailez moi.

Bypasser une authentification

Cette technique est basee sur le m?me principe que l'attaque vu en [ 3.1 ] : la faille mis en cause est la requete au serveur SQL.
Ainsi lors d'une authentification, le script PHP va recuperer les variables $login et $password, puis va parcourir la base de donnee a la recherche du couple Login/Password. Ainsi la requete MySQL ressemblera a quelquechose de ce type :

$table = identification";
$query = " SELECT Login, Password FROM $table WHERE Login='$login' and Password='$password' ";
$result = mysql_query($query);

Login et Password sont des champs de la table identification ($table), tandis que $login et $password sont des valeurs entrees par l'utilisateur a travers un formulaire. Ainsi si l'utilisateur entre comme login medgi et comme password subkulture, la requete correspondra a ceci :

SELECT Login, Password FROM identification WHERE Login='medgi' AND Password='subkulture'
Maintenant imaginez que l'utilisateur entre comme valeur pour le login 'or''=' et pour le password 'or''='.
La requete MySQL correspondante ressemblera a ceci : SELECT Login, Password FROM identification WHERE Login=''or''='' AND Password=''or''=''

Etudions cette requete plus en detail. Le script PHP va parcourir la base de donnees MySQL a la recherche de plusieurs choses. Tout d'abord il va chercher un champ Login qui ne contient rien. En theorie il ne trouvera pas car chaque compte possede un nom d'utilisateur. Si il ne trouve pas il va essayer la deuxieme condition stipiluee par le or.
Cette condition demande qu'une chaine vide soit egale a une chaine vide, cela reviens a dire 0 = 0 : c'est toujours vrai. Ensuite le script PHP tentera de verifier les m?mes conditions pour le champ Password. Ainsi les deux conditions seront vrai, et l'authentification sera correct.De meme si nous passons comme argument admin pour la variable $login et que nous passons 'or''=' pour la variable $password, nous obtiendrons une requete de ce genre :

SELECT Login, Password FROM identification WHERE Login='admin' AND Password=''or''=''

Une fois de plus nous pouvons contourner l'identification, mais cette fois ci nous pouvons m?me stipuler l'utilisateur, et donc avoir les m?me froit que lui (il est logique que l'utilisateur Admin aie plus de permissions que l'utilisateur Guest318).
Il est aussi possible de passer l'authentification en utilisant des commentaires. Petits rappels des commentaires : definits entre /* et */ ou encore par le caractere dieze (#). Ainsi si nous rentrons comme valeure pour login 'or''=''#, notre requete MySQL sera de la sorte :

SELECT Login, Password FROM identification WHERE Login=''or''=''# AND Password=' $pasword '
Ce qui reviens a effectuer une requete de la forme :

SELECT Login, Password FROM identification WHERE Login= '' or ''=''
Ainsi en utilisant les commentaires nous effa?ons une partie de la requ?te ce qui nous permet d'eviter certaines etape de controle (ici la verification du password).En utilsant cette methode un attaquant peut bypasser une authentification, et le compte obtenu sera le premier de la table MySQL, qui est en general l'admin ! Ainsi pour securiser cette faille, il faut parser les input avant d'effectuer la requete MySQL, en verifiant que $login et $password ne contiennent pas les caracteres suivant : () / , ; . : # < > | \ ".

Voici comment proceder :
$login = trim(htmlspecialchars(addslashes($login))); # Parsing du login
$password = trim(htmlspecialchars(addslashes($password))); # parsing du password
if( ( strlen($login)!=0) && (strlen($password)!=0) ) { #
REQUETE MYSQL else { echo "fuck you :) \n"; }

Sources de l'article


 

Blog
Le blog
La radio
La Radio
Boutique
La boutique du Geek
Php/Mysql
Formulaire en php
Administrer un serveur Mysql
Session en php
Gerer ses bases mysql
Les bases php
Securiser ses scripts PHP
Controler ses programmes avec RATS
Convertir une base sql en utf8
Astuces php
Le fichier php.ini
Programmation
Python rapide
Tutorial Python
Tutorial Perl
Tutorial Perl complet
Tutoriel ruby
Tutoriel C
Introduction à gawk
Filtres et utilitaires
Find
Programmation Shell
Ecriture de scripts bash
Expressions regulieres
Vi
Introduction a Javascript
Compiler avec gcc
Astuces en Bash
Cracking
Tutoriel Assembleur
Guide du cracking pour débutant
Assembleur
Manual Unpacking
Techniques de Protection
Différentes failles Web
Arp spoofing dans un réseau switché
Les intrusions
Les attaques externes
Defacage
Defacage complet
Buffer overflow
Netcat
Injection sql
Injection sql(suite)
John the Ripper
Spoofer un email
Utiliser google
La faille system
Usurper une identité
Le rooting
Shellcode sous Unix
La faille race condition
La faille xss
La faille xss (2)
Attaques sur un routeur
P2P
Azureus pas-a-pas
News
Lire les news de Linux-pour-lesnuls.com au format RSS
Distros
Gestion des paquets debian
101 commandes debian
Jeu
Webtarot
Graphisme
Effet neon dans GIMP
Effet vapeur dans GIMP
Cours fonctionnalités de GIMP
Redimentionner une image avec GIMP
Redimentionner une photo pour en faire un cadre avec gimp
Morphing avec gimp
Détourer avec gimp
Réduire le poids d'une image avec gimp
Caricature avec gimp
Humour
Ensemble
Divers