
| auteur : july |
Les pirates peuvent parfois réussir à voler le contenu d'une
base de données. Les noms d'utilisateur et les mots de passe
de l'ensemble des utilisateurs leur sont alors accessibles.
Les mots de passe doivent donc être stockés, hashés, dans la
base de données. Ainsi, en cas de vol de la base, le pirate
n'a pas accès aux mots de passe. Ceux-ci devraient être codés
avec l'algorithme du SHA 256 car le MD5 a été craqué, ce qui
le rend moins efficace. Lorsque l'utilisateur saisit son mot
de passe, il est codé et la vérification s'effectue avec les
deux versions codées : celle de la base de données et celle
saisie.
De cette manière, l'administrateur de la base de données n'a
pas non plus accès aux mots de passe en texte clair.
Dès lors, le pirate aura pour but de récupérer les mots de
passe en clair en sniffant le réseau. En fait, ils récupèrent
les données transitant entre le client et le serveur puisque
les mots de passe sont codés côté serveur.
Pour éviter ce problème, il est possible grâce à un JavaScript
d'encoder les mots de passe côté client. Le champ mot de passe
est vidé grâce au JavaScript donc, dans la requête, seul le
mot de passe crypté transite. L'avantage est que si un pirate
récupère les données qui voyagent entre le client et le serveur,
il récupère un mot de passe crypté et ne peut pas l'utiliser.
Le problème est que le JavaScript peut être désactivé par
l'utilisateur. Il faut donc, côté serveur, prévoir deux types
de vérification de mot de passe : ceux en clair et en crypté.
<?php
$sql = "SELECT U.login, U.password FROM user U WHERE U.login ='".mysql_real_escape_string($_POST['login'])."'";
$result_user = mysql_query($sql);
if ($user = mysql_fetch_object($result_user))
{
if ($user->password == mhash(MHASH_SHA256, $_POST['password'])
or $_POST['sha1'] == mhash(MHASH_SHA256, user->password.$_SESSION['grain_de_sel']) )
{
...
header('HTTP/1.1 204 No Content');
header('location: index.php');
exit;
}
else
{
return "<div class=MessErr>Erreur, veuillez essayer de nouveau !</div>";
}
}
else
{
return "<div class=MessErr>Erreur, veuillez essayer de nouveau !</div>";
}
?> |
|
| auteur : july |
Une méthode peut être mise en place. Le numéro de session ne
change jamais. À chaque page, un autre numéro de session
aléatoire est généré. Il est stocké dans une variable session
et dans un cookie
envoyé au client. À la page suivante, on
vérifie que le numéro stocké dans la session est bien le même
que celui dans le cookie. S'ils sont différents, la session
est détruite et les deux (pirate et utilisateur) sont déconnectés.
Le délai d'action du pirate qui aurait volé un numéro de session
est donc réduit. L'inconvénient est que si l'utilisateur
consultait sa dernière page (donc qu'il a fermé son navigateur
sans fermer sa session) le numéro reste disponible. La seule
solution reste d'éduquer les utilisateurs pour qu'ils cliquent
systématiquement sur "se déconnecter" en quittant le site.
<?php
if($logged_in)
{
if(!ctype_digit($_COOKIE['id_aleatoire']) or !ctype_digit($_SESSION['id_aleatoire']))
{
}
else
{
$id2 = $_COOKIE['id_aleatoire'];
if( isset($_SESSION['id_aleatoire']) )
{
if($id2 != $_SESSION['id_aleatoire'])
{
logout();
}
else
{
$expire = time()+24*3600;
$nb_aleatoire = mt_rand();
$_SESSION['id_aleatoire'] = $nb_aleatoire;
setcookie("id_aleatoire", $nb_aleatoire, $expire);
}
}
}
}
?> |
|
| auteur : july |
Un session_timeout doit être implémenté afin de fermer la
session si l'utilisateur quitte le site sans se déconnecter
(en fermant son navigateur)
ou si le temps d'inactivité est trop long.
La fonction de déconnexion doit détruire l'objet $_SESSION de
l'utilisateur. Ainsi si un pirate vole la session, elle sera
inutilisable. Il faut faire de même avec le cookie, sauf qu'il
n'est pas possible de supprimer un cookie (puisqu'il est côté
client et qu'il n'est pas possible d'agir sur les fichiers
côté client). Il faut donc remplir le cookie d'une valeur
volontairement fausse. Si ce cookie était volé, il serait
inutilisable puisqu'il ne contiendrait qu'une valeur fausse.
Ensuite à chaque affichage de page, il faut vérifier si le
temps d'inactivité a été dépassé.
<?php
define ('SESSION_TIMEOUT', "1800");
if (isset($_SESSION['login']))
{
if(time()-$_SESSION['last_access'] > SESSION_TIMEOUT)
{
logout();
}
else
{
$_SESSION['last_access'] = time();
}
}
?> |
|
| auteur : july |
Il faut utiliser la libgd pour générer une image
volontairement dégradée. Bien sûr, moins la fonte utilisée est
connue, plus le système est efficace. Il existe des systèmes
encore plus efficaces avec des images GIF animées.
<?php
$length = 5;
$alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
$nb_characters = strlen($alphabet);
$string = '';
for($i = 0; $i < $length; ++$i)
{
$string .= $alphabet[mt_rand(0, $nb_characters-1)];
}
$str_length = strlen($string);
$image = imagecreatetruecolor(30 * $str_length, 50);
for($x = 0; $x < imagesx($image); ++$x)
{
for($y = 0; $y < imagesy($image); ++$y)
{
if (mt_rand(1,5) == 4 )
{
$vred = mt_rand(0, 100);
$vgreen = mt_rand(0, 100);
$vblue = mt_rand(0, 100);
}
else
{
$vred = mt_rand(100, 150);
$vgreen = mt_rand(100, 150);
$vblue = mt_rand(100, 150);
}
$color = imagecolorallocate($image, $vred, $vgreen, $vblue);
imagesetpixel($image, $x, $y, $color);
imagecolordeallocate($image, $color);
}
}
$vred = mt_rand(0, 240);
$vgreen = mt_rand(0, 240);
$vblue = mt_rand(0, 240);
$color = imagecolorallocate($image, $vred, $vgreen, $vblue);
imagerectangle($image, 0, 0, imagesx($image)-1 , imagesy($image)-1, $color);
imagecolordeallocate($image, $color);
for($i = 0; $i < $str_length; ++$i)
{
$vred = mt_rand(150, 240);
$vgreen = mt_rand(150, 240);
$vblue = mt_rand(150, 240);
$size = mt_rand(20, 30);
$angle = mt_rand(-10, 20);
$x = 13 + (20 * $i);
$y = mt_rand(30, imagesy($image) - 10);
$color = imagecolorallocate($image, $vred, $vgreen, $vblue);
$font = 'comic.ttf';
imagettftext($image, $size, $angle, $x, $y, $color, $font, $string[$i]);
imagecolordeallocate($image, $color);
}
header("Content-type: image/png");
imagepng($image);
?> |
|
| auteur : Yogui | Cela se fait en deux temps. D'une part, le code PHP : Ou, si la directive magic_quotes est activée sur votre configuration :
Ensuite, il suffit d'appeler ce script dans le navigateur avec
le paramètre "page" et de lui donner du code JavaScript à exécuter :
http://localhost/test.php?login=<script>alert("Je t'ai eu !");</script> |
À partir de là, il ne reste plus qu'à être inventif. Il est par
exemple possible de récupérer le contenu des cookies du
navigateur pour ce site et d'utiliser Ajax pour s'envoyer le tout...
Une faille XSS est simplement l'affichage de valeurs soumises
par l'utilisateur, directement dans le navigateur sans aucun filtrage.
|
| auteur : Yogui |
Il suffit d'envoyer au navigateur Web les caractères auxquels
il s'attend.
Si l'on souhaite afficher une variable numérique entière :
Si l'on souhaite afficher du texte :
Notez l'utilisation des deux paramètres optionnels,
fondamentaux pour une bonne sécurité. Notez également que le
paramètre charset (le dernier) doit être le même dans tout le script.
À la longue, cette syntaxe devient fastidieuse. Il est donc
préférable de définir une fonction dont l'usage sera plus simple :
function html($string)
{
return htmlentities($string, ENT_QUOTES, 'UTF-8');
}
echo html($host);
echo html($login);
echo html($password);
echo html($database); |
Important : Se protéger de la faille XSS permet de se protéger
d'une très grosse partie des failles de sécurité des applications Web.
|
lien : Définition de cross-site scripting
lien : Comment reproduire une faille XSS ?
|
| auteur : Eusebius |
Tout d'abord, il faut bien être conscient que dans le cas
d'une configuration saine, le code source n'est pas accessible
directement. Seul le code HTML (ou autre) généré par le
parseur sera envoyé au client. Ainsi vos identifiants de connexion
(par exemple) sont normalement protégés.
En supposant que c'est un fichier sur lequel vous faites
un include, on peut cependant augmenter le niveau de sécurité.
-
Niveau 1 : vous laissez tel quel, en prenant bien
soin de nommer ce fichier en .php et pas en .inc
(qui pourraient être lus sans être interprétés).
-
Niveau 2 : vous mettez ce script dans un répertoire
protégé par un .htaccess. Par exemple, pour interdire
tout accès au répertoire, le fichier .htaccess pourra
contenir :
<LIMIT GET POST> order deny,allow deny from all </LIMIT> |
-
Niveau 3 (pas forcément réalisable sur n'importe
quel hébergement) : vous mettez ce script dans un
répertoire non accessible par le serveur web (c'est
à dire, pour apache, à l'extérieur du DocumentRoot
spécifié dans le httpd.conf), tout en prenant garde
qu'il soit toujours accessible par PHP (si
open_basedir est spécifié, il doit pointer vers un
répertoire parent du répertoire choisi).
|
| auteur : Yogui |
Il faut échapper les paramètres des fonctions de manière adéquate.
Dans le cas d'une requête SQL, il vous faut utiliser le mécanisme
mis à disposition par votre SGBD. Certaines classes comme PDO
proposent un mécanisme bien plus fiable (les paramètres liés)
qui nous évite d'utiliser de telles fonctions.
|
Consultez les autres F.A.Q's
Les sources présentés sur cette pages sont libre de droits,
et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs.
Copyright ©2003
Developpez LLC. Tout droits réservés Developpez LLC.
Aucune reproduction, même partielle, ne peut être faite de ce site et de
l'ensemble de son contenu : textes, documents et images sans l'autorisation
expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans
de prison et jusqu'à 300 000 E de dommages et intérets.
Cette page est déposée à la SACD.
|