PhpBB-Power Communauté francophone de support et de mods pour phpBB
|
| Voir le sujet précédent :: Voir le sujet suivant |
| Auteur |
Message |
Aramiil Membres actifs
Inscrit le: 30 Nov 2004 Messages: 368 Localisation: Dans les limbes de mon imagination
|
Posté le: Lun 04 Avr 2005 à 22:48 Sujet du message: [PHP-Programmation] La sécurité |
|
|
Bonjour,
Dans le tutorial d'aujourd'hui, je vous propose de nous attaquer à l'une des pierres d'angle de l'informatique: la sécurité.
A une époque où les trois principaux algorithmes de hachage (md5, sha0 et sha1 - nous en parlerons à nouveau plus tard) ont étés cassés, on peut en effet se demander où en est la sécurité de nos sites web et même si elle existe encore.
Ce tutorial d'un genre assez particulier va commencer par une partie (assez longue) de théorie, aussi, si vous souhaitez vous attaquer directement au code, vous pouvez passer directement à la partie III.
Partie I: Ce que dit la loi
Dans un premier temps, examinons ce que dit la loi sur le piratage. Les principaux articles sur ce sujet proviennent de la loi Godfrain du 5/01/1988 actualisée par la LCEN du 21/06/2004:
"Le fait d'accéder ou de se maintenir, frauduleusement, dans tout ou partie d'un système de traitement automatique de données est puni de deux ans d'emprisonnement et de 30000€ d'amende" (article 323-1)
(Donc si quelqu'un pirate l'accès à un site, ou utilise un code qu'il ne devrait pas utiliser, par exemple)
"Lorsqu'il en résulte soit la suppression ou la modification de données contenue dans le système, la peine est de trois ans d'emprisonnement et de 45000€ d'amendes" (article 323-1 toujours)
Et pour continuer le point juridique:
"Le fait d'entraver ou de fausser le fonctionnement d'un systeme de traitement de données" (article 323-2) et "le fait d'introduire frauduleusement des données dans un systeme de traitement automatisé ou de supprimer ou de modifier frauduleusement les données qu'il contient" (article 323-3) sont punis de cinq ans d'emprisonnement et de 75000€ d'amende. Dans cette categorie peuvent entre autres être inclus le spam, les inscriptions massives à des fora, etc...
"Le fait, pour toute personne, de présenter aux personnes mentionnées au 2 un contenu ou une activité comme étant illicite dans le but d'en obtenir le retrait ou d'en faire cesser la diffusion, alors qu'elle sait cette information inexacte, est puni d'une peine d'un an d'emprisonnement et de 15 000 EUR d'amende." (Loi pour la confiance en l'économie numérique, Chapitre II, article 6, alinéa 4). En d'autres termes, toute personne responsable de la diffusion d'un hoax du style "attention, le virus le plus dangereux..." ou "msn va fermer" ou encore "msn vous pirate, vous devez arrêter" est passible de cette peine si elle est au courant que c'est faux.
"Est puni d'un an d'emprisonnement et de 75 000 EUR d'amende le fait, pour une personne physique ou le dirigeant de droit ou de fait d'une personne morale exerçant l'une des activités définies aux 1 et 2 du I, de ne pas satisfaire aux obligations définies au quatrième alinéa du 7 du I, de ne pas avoir conservé les éléments d'information visés au II ou de ne pas déférer à la demande d'une autorité judiciaire d'obtenir communication desdits éléments." (même loi, article 6, alinéa 8, VI, 1). Le texte de legifrance n'est pas très clair: il est possible que cette partie ait été déclarée non conforme à la constitution. Si ce n'est pas le cas, elle stipule que toute personne s'occupant de fournir un service relatif au stoquage de données (forum, hébergement, etc...) et aux fournisseurs d'accès doit garder à disposition, durant une durée de 1 an, toutes les informations que fournissent les utilisateurs de ce service (message, nom, adresse, pseudo, etc...) afin de permet un droit de réponse (lui aussi obligatoire). Ces informations sont couvertes par le secret professionnel, mais pas auprès de la justice.
"Le fait, sans motif légitime, d'importer, de détenir, d'offrir, de céder ou de mettre à disposition un équipement, un instrument, un programme informatique ou toute donnée conçue ou spécialement adaptés pour commettre une ou plusieurs des infractions prévues par les articles 323-1 à 323-3 est puni des peines prévues respectivement pour l'infraction elle-même ou pour l'infraction la plus sévèrement réprimée." (LEN, titre III, article 46, alinéa 1). En d'autres termes, si vous mettez à disposition le matériel pour commettre un délit (in extenso: virus, logiciels de peer-to-peer, etc...), sans raisons valables (in extenso: étude du code-source, apprentissage, téléchargement de logiciels gratuits), vous êtes passible des même peines que si vous aviez effectivement commis le délit. Si le matériel à disposition permet plusieurs délits, vous êtes passible de la peine la plus lourde parmi les délits.
Enfin, je signale que la simple tentative de délits, même suivie d'un échec, est punie des même peines que le délit lui-même (article 323-7).
Après ce petit point législatif, un petit mot: durant ce tutorial, je vais vous donner des noms de méthodes permettant de pirater un systeme. Comme précisé ci-dessus - et c'est d'ailleurs la raison de ce petit rappel législatif particulièrement ennuyeux - l'utilisation des techniques qui seront nommées ici dans un autre but que la sécurité de votre site est strictement illégale.
Partie II: Un peu de théorie
Durant l'élaboration d'un site web, il est toujours logique de chercher à rendre celui-ci aussi sur que possible. Pour cela, la seule méthode est d'essayer d'imaginer tout ce que pourrait faire un pirate et de bloquer toutes les possibilités. Bien sur, il est largement hors du but de cet exercice d'essayer d'empêcher Kévin Mitnik (alias Le Condor) de pirater un site: c'est de toutes manières largement hors de nos compétences.
Mais il existe néanmoins des moyens de protection efficace pour empêcher un pirate de voler des informations et/ou de modifier, voir de s'approprier votre site.
1) La protection des données
La première chose importante dans un site consiste à protéger les données de l'utilisateur - et les vôtres. En effet, qui irait donner son mot de passe - ou pire, son numéro de carte bleu - sur un site, alors qu'il sait qu'il n'y aura aucune protection de ces données? Personne, évidement.
Il est donc logique de chercher à protéger les données de vos utilisateurs. Pour cela, il convient de choisir entre deux méthodes:
a) Le cryptage
La cryptage se base sur une clé (ou deux, dans le cas des algorithmes asymétrique comme le cryptage RSA) qui servira à chiffrer un texte. En d'autres termes, en utilisant cette clé, on pourra transformer un texte important - par exemple un mot de passe - en un ensemble totalement illisible pour celui qui ne connaîtra pas notre clé. Ce procédé est bien sur utile principalement avec une clé très complexe (32 caractères constituent un bon début )
Le cryptage à un avantage très simple: il est possible de revenir en arrière. En d'autres termes, vous pouvez à tout moment, en utilisant la clé de cryptage, transformer la bouillie informe générée par l'algorithme pour retrouver le mot de passe qu'avait saisi l'utilisateur!
Mais cet avantage est aussi un inconvénient: en effet, si un pirate découvre votre clé - ou s’il la devine - il lui sera très simple de retrouver toutes les données fournies par les utilisateurs de votre site!
Exemple de cryptage: Décaler toutes les lettres de l'alphabet de x. X est alors la clé.
Par exemple, ce cryptage avec une clé de 1 donnerais ceci:
Bonjour => Cpokpvs
b) Le hachage
Le hachage est une méthode permettant de transformer un texte quelconque, de n'importe quelle taille, en un autre texte, de taille fixe. La particularité de cette méthode réside en ce qu'elle n'utilise pas de clé: il suffit d'appeler la fonction correspondante pour hacher un texte.
L'intérêt principal de cette méthode est aussi son gros inconvénient: il est totalement impossible de revenir en arrière. Une fois un mot haché, il est impossible de retrouver le mot de départ.
Il existe trois algorithmes principaux de hachage: md5, sha0 et sha1. Ces trois algorithmes sont généralement implémentés en tant que fonction dans la plupart des langages de programmation (PHP et SQL par exemple).
Note: De nombreux sites vous informe qu'ils ne pourront pas retrouver votre mot de passe si vous le perdez. Le plus souvent, cela vient simplement du fait que ce mot de passe est haché dans la base de donnée, et qu'un hachage est irréversible.
Note bis: Les hachages md5 et sha1 peuvent aussi servire à s'assurer de l'intégrité des fichiers. Mais cela n'entre pas dans le cadre de ce tutorial.
c) Application en programmation
Comment utiliser ce que nous venons de voir en programmation? Sans rentrer dans la sécurité pure, voici un petit exemple de ce que peuvent faire les différents moyens de protection des données:
| Code: | <?php
$maVariable = "Mouche";
echo 'Variable de départ: ' . $maVariable;
echo '<br><hr><br>';
/* Premier exemple: cryptage.
* Pour effectuer ce cryptage, on utilisera la fonction str_rot13
* dont voici le prototype:
* string str_rot13 ( string str )
* Cette fonction décale toutes les lettres de l'alphabet de 13
* caractères. */
$maVariable = str_rot13($maVariable);
echo 'Cryptage: ' . $maVariable;
echo '<br><hr><br>';
/* La clé de cryptage de la fonction str_rot13() est donc 13.
* La particularité de cette clé est qu'il suffit de la ré-appliquer pour
* décrypter le message (puisque 13+13 = 26) */
$maVariable = str_rot13($maVariable);
echo 'Décryptage: ' . $maVariable;
echo '<br><hr><br>';
/* Nous allons maintenant nous intéresser aux fonctions de
* hachage. Nous allons pour cela observer les deux fonctions implémentées
* sous PHP: md5 et sha1. */
/* Commençons par md5. C'est l'algorithme le plus rapide des deux,
* mais aussi le moins sécurisé. Cela dit, rassurez-vous: il faut tout de même
* des heures de travail à un ordinateur pour retrouver un mot de passe haché en
* md5 - mais nous en parlerons plus loin. Ce qu'il faut noter en revanche ici, c'est
* que md5() retourne toujours une chaîne de 32 caractères. Voici son prototype:
* string md5 ( string str [, bool raw_output] )
* (attention, le second argument à été rajouté en PHP5) */
$monMd5 = md5($maVariable); //Le hachage ne pouvant être inversé, on utilise une autre variable
echo 'Hachage md5: ' . $monMd5;
echo '<br><hr><br>';
/* Passons à présent au hachage sha1. Contrairement au md5(), il retourne un
* code de 40 caractères. Jusqu'a cet été, il était considéré comme inviolable. Voici
* son prototype:
* string sha1 ( string str [, bool raw_output] )
* (le second argument a de nouveau été ajouté en PHP5) */
$monSha = sha1($maVariable); //idem que précédemment
echo 'Hachage sha1: ' . $monSha;
?> |
Voici le résultat afficher par l'exemple précédent:
| Code: | Variable de départ: Mouche
Cryptage: Zbhpur
Décryptage: Mouche
Hachage md5: a678aafe2c1046d9cc825ad1ccb4db1e
Hachage sha1: b880bab9ae99c195d52758c63c63b194b672bcd3 |
d) Les dernières nouvelles
Passons maintenant aux tristes nouvelles: oui, les algorithmes de cryptage ne sont pas inviolables. Même la tristement célèbre enigma, qui servit durant la seconde guerre mondiale, à put être déchiffrée. Un pirate qui s'en donnera le temps et les moyens pourra donc toujours récupérer les valeurs que vous aurez crypté.
De la même manière, oui, on a brisé les hachages. Et oui, il est désormais possible de récupérer, non pas le mot de passe original, mais une combinaison qui donnera le même résultat. En effet, il existe nécessairement deux combinaisons qui donnent le même résultat, puisqu'une chaîne haché ne présente que x caractères, tous appartenant au domaine de l'hexadécimal. Il n'existe donc que 16^x combinaisons possibles, ce qui implique nécessairement une répétition. En se basant sur le "paradoxe des anniversaires" (loi mathématique qui indique que, parmi 26 personnes, il y à 50% de chance que deux soient nées le même jours), on peut donc trouver des chaînes de caractères qui peuvent "marcher", et donc être reconnues comme valide.
Cela dit, inutile de s'affoler: il faut encore des heures - voir des jours, dans le cas de sha1 - à un ordinateur pour casser un hachage. Tout n'est donc pas fini, et le hachage à encore de beaux jours devant lui.
2) La sécurisation des fichiers
Le second type de failles particulièrement courant en PHP concerne les apports extérieurs. Je m'explique: imaginons un site web quelconque. Le vôtre, par exemple. Dans ce site web, vous voulez proposer au gens de passer dans l'url un texte qui sera affiché - ou tout simplement, vous utilisez une méthode GET dans vos formulaires, ou (pire), vous avez activé register_global.
Dans ce cas, que se passe-t-il? Il y à plusieurs possibilités. La première: si vous avez activé register_global, il suffit de passer comme paramètre: www.monsite.com/index.php?userlevel=Admin pour que le pirate soit automatiquement considéré comme administrateur (si, bien sur, le niveau d'autorisation de l'utilisateur est stocké dans la variable userlevel). Embêtant, non?
Imaginons maintenant que vous (ou votre hébergeur) avez désactivé register_global. Il reste tout de même deux grosses vulnérabilités:
1) Imaginons un code de ce type:
| Code: | <?php
$variable = $_GET['texte_a_afficher'];
echo $variable;
?> |
ou pire:
| Code: | <?php
$variable = $_GET['texte_a_afficher'];
eval($variable);
?> |
un programmeur avisé pourrait, sans le moindre problème, utiliser ceci. En effet, il suffirait de bien choisir le texte passé en URL pour pouvoir effectuer un nombre illimité de fonctions (affichage de variables, etc...). Gênant, pas vrai?
2) Un exemple encore plus courant. Imaginons ceci:
| Code: | <?php
$page = $_GET['page'];
include($page);
?> |
Courant, non? Et généralement utilisé. Et bien, messieurs, ce genre de chose ne tiendrait pas une seconde. Et ce, pour deux raisons:
1) Il suffit d'inclure un fichier distant situé sur le même serveur pour pouvoir exécuter toutes les actions contenues dans ce fichier distant. Appel à la base de donnée, affichage des mots de passe... tout! Et ce, quelle que soit la configuration de votre hébergeur.
2) Même si vous protégez votre script contre ce genre de choses, il suffit de provoquer volontairement une erreur en passant par url des commandes php, puis de naviguer dans le buffer de votre serveur pour effectuer ces commandes. Cette méthode est certes plus compliquée, mais pas impossible - loin de là.
Nous verrons donc dans la partie III comment mettre en place un systeme permettant d'éviter ce genre de failles.
3) Les injections SQL
Une des failles les plus embêtantes du PHP. En effet, elle est dure à détecter, et pourtant très simple à exploiter... Elle consiste en fait à envoyer une commande à la base de données, formatée de telle manière que cette commande retourne un résultat incorrect.
Je crains que cette explication ne soit pas très claire, aussi, voici un exemple:
| Code: | <?php
//Ouverture de session
session_start()
//l'utilisateur a-t-il envoyé un mot de passe?
if(!isset($_POST['password']))
{
//oui, on récupère donc les variable
$pseudo = $_POST['pseudo'];
$pass = $_POST['password'];
//On prépare la requête SQL
$sql = "SELECT user_level FROM utilisateur WHERE pseudo = '$pseudo' AND pass='$pass'";
//on l'execute
$db = mysql_connect('127.0.0.1', 'root', '');
$result = mysql_query($sql, $db);
//On récupère le résultat
$resultat = mysql_fetch_assoc($result);
mysql_free_result($result);
mysql_close($db);
//on donne son niveau à l'utilisateur
$_SESSION['user_level'] = $resultat['user_level'];
//On le redirige
header('location: admin.php');
} else {
//on affiche le formulaire
?>
<form method="POST" action="login.php">
Pseudo: <input name="pseudo"><br>
Mot de passe: <input type="password" name="password"><br>
<input type="submit" value="envoyer"></form>
<?php } ?> |
Ce petit exemple est très simple, il sert juste à récupérer le niveau de l'utilisateur. Maintenant, voyons comment un pirate pourrait l'utiliser pour faire croire qu'il est administrateur. Pour cela, examinons la requête SQL qui permet de savoir à quel utilisateur on à affaire:
| Code: | | SELECT user_level FROM utilisateur WHERE pseudo = '$pseudo' AND pass='$pass' |
Cela semble assez normal. Mais comment faire pour faire croire qu'on à tous les droits? Pour cela, il faudrait se faire passer pour l'administrateur. Et bien soit, allons-y. Pour cela, il va nous falloir utiliser des valeurs particulières pour le pseudo et le mot de passe, bien sur.
Essayons par exemple avec ce couple de valeurs (pour l'exemple, nous supposerons que l'administrateur à pour pseudonyme "administrateur"):
pseudo: administrateur' OR ('1' = '1
mot de passe: test') AND '1' = '1
Que deviendrais alors notre requête? Simple à savoir, il suffit de remplacer:
| Code: | | SELECT user_level FROM utilisateur WHERE pseudo = 'administrateur' OR ('1' = '1' AND pass='test') AND '1' = '1' |
Amusant, non? Notre requête répond maintenant toujours le niveau de l'administrateur, sans se soucier du mot de passe. C'est ce qu'on appelle une injection sql
Bien entendu, des méthodes de protection existent également contre ceci. Nous les verrons dans la prochaine partie.
4) Le vol de session
Vous êtes toujours là? Vous êtes courageux ^^ mais rassurez-vous, la théorie est bientôt terminée. Le dernier point que nous allons étudier est le suivant: lorsqu'un utilisateur se connecte à un espace membre de votre site web, il utilise une session. En PHP, cette session est identifiée par un numéro unique, l'id de session. Cet identifiant permet de retrouver l'utilisateur tant que la session n'est pas détruite.
Imaginons maintenant un cas simple: un lycéen visite votre site depuis son lycée. Il passe sur l'espace membre, puis ferme le navigateur et éteint l'ordinateur. Quelques minutes plus tard, un autre lycéen ré-allume l'ordinateur, et retourne sur le site. Et là, horreur! En récupérant l'id de session, il peut se faire passer pour le premier élève, qui a imprudemment oublié de se déconnecter. Et donc, avoir accès à toutes les parties privées du site.
Et il y à pire: imaginons que votre visiteur se connecte depuis une salle de jeux. Il part un instant au toilettes, instant durant lequel son voisin récupère son id de session (visible généralement dans l'url ou dans le code-source des formulaires). Il n'a plus alors qu'à utiliser cet id de session pour se connecter, et le problème précédent réapparais.
Une fois encore, il existe des méthodes préventives très simple pour éviter le vol de session. Nous allons les exposer dans la...
Partie III: Se protéger
Pour cette troisième (et dernière) partie, nous allons voir, en suivant le plan de la petite présentation précédente (sic), comment se protéger au mieux des différents types d'attaque.
Note: Nous ne reviendrons pas sur les algorithmes de cryptage/hachage, qui sont expliqués dans la première partie de la section précédente. En revanche, nous les utiliserons régulièrement, aussi, si vous avez sauté directement à cette partie, considérez simplement qu'il s'agit de fonction permettant de cacher des données.
1) Sécuriser vos fichiers
Les attaques par le biais des URL peuvent venir de trois biais:
1) Utilisation de variables masquées
2) Utilisation de register_global = ON
3) Inclusion de fichiers interdite
Pour palier au premier risque, le plus simple est d'utiliser une fonction de filtrage des variables. Il y en à deux, très importantes, à noter:
htmlspecialchars($texte) renverra une chaîne où tous les caractères spéciaux de l'HTML sont remplacés par leur code. Par exemple, "<" sera remplacé par "<". Cela permet d'éviter qu'un petit malin ne modifie l'affichage qu'aura, par exemple, votre forum. Cette fonction peut (et doit) d'ailleurs également être utilisée dans les cas de données acquises par la méthode POST, car elles sont soumises au même risque.
Attention! Ne faites pas aveuglément confiance à vos <input type="hidden"> et à vos <select>. Ce n'est pas parce qu'une valeur n'est pas sensé apparaître qu'elle n'apparaîtra pas: rien de plus simple que de copier la source de votre formulaire et de l'adapter à son gré sur son disque dur, pour faire ensuite pointer le formulaire en question vers votre fichier de traitement.
str_replace($recherche, $remplacement, $chaine) va remplacer toutes les occurrences de $recherche par $remplacement dans $chaine. L'intérêt? Très simple: vous pouvez par exemple l'utiliser pour remplacer toutes les occurrences d'un ; (symbole d'une fin d'instruction en php, et donc susceptible d'être utilisé dans le but de modifier vos variables dans votre dos, par son code hexadécimal, à savoir ceci: ; . Cela peut sembler inutile, étant donné que le ; est toujours présent; en fait, cela produira une erreur, si le but du pirate est réellement d'utiliser une faille de ce genre.
Voici donc une petite fonction permettant de traiter simplement les chaînes:
| Code: | <?php
function securise_string($chaine)
{
$chaine = htmlspecialchars($chaine);
$chaine = str_replace(';', ';', $chaine);
return $chaine;
}
?> |
Au niveau de l'utilisateur, le changement sera invisible; pour vous, la sécurité sera renforcée.
Pour palier au second risque, en revanche, il n'y à pas réellement de solution. Il peut néanmoins être proposé:
- de demander à l'hébergeur le passage à register_global = Off au plus tôt
- de ne jamais utiliser une variable non initialisée: toujours utiliser $variable = ''; avant de considérer qu'elle ne contient rien
- utiliser (si la fonction n'est pas désactivée) ceci:
| Code: | | @ini_set('register_global', 'Off'); |
Enfin, la protection contre le troisième risque est la plus embêtante. La première chose qui nous viendrait à l'esprit serait de vérifier, avec fopen ou file_exists, la présence du fichier à ouvrir. Mais cela pose un problème: si le fichier n'existe pas, et qu'on affiche par exemple une erreur, il est alors simple pour le pirate de recuperer cette erreur pour pénétrer dans notre site.
La manière de protection qui me semble la plus adaptée (mais qui ne l'est peut-être pas; ce n'est que mon idée) est la suivante: elle consiste à assigner à chaque page un numéro. Ensuite, on passera ce numéro par URL, puis on utilisera la fonction intval() pour vérifier que le paramètre obtenu par URL n'est pas autre chose qu'un entier. Il ne nous restera plus qu'à utiliser un tableau pour récupérer le nom de la page correspondante, comme ceci:
| Code: | <?php
//Déclaration du tableau
$page_list = array('0' => 'index.php', '1' => 'news.php', '2' => 'moi.php');
/* Récupération de la variable passée en URL
* La fonction intval ne renvoi que la partie correspondant
* à un nombre entier de la variable. Si on essaye de passer une chaine
* ne contenant pas d'entier par l'URL, intval() retournera 0.
* De plus, l'utilisation de isset() permet d'éviter les notices et les bugs si aucune
* variable n'est passé par l'url */
$page = (isset($_GET['page'])) ? intval($_GET['page']) : 0;
/* Vérification de la valeur de $page.
* Cette valeur ne doit pas dépasser le nombre total d'entrée du tableau;
* si c'est le cas, on la remplacera simplement par 0. */
$page = ($page < 2) ? $page : 0;
/* Affichage de la page.
* On utilise ici un requiere plutôt qu'un include car cette fonction fait s'arrêter
* le script si la page ne peut être incluse; une sécurité supplémentaire, quoique
* théoriquement inutile. */
requiere($page_list[$page]);
?> |
2) Se protéger contre les injections SQL
Pour se protéger contre les injections SQL de manière efficace, la première chose à faire est de faire appel à une fonction; et pour être précis, la fonction addslahses($texte), qui aura pour effet de rajouter un \ devant tous les guillemets. Une protection nécessaire, et qui peut être suffisante si votre site ne prend pas trop d'ampleur.
Mais cela risque de ne pas être suffisant. Pourquoi? très simple: il existe un certain nombre de caractères assez embêtants, qui permettent en SQL d'ajouter, par exemple, des commentaires. Ce qui veut dire qu'il suffit de s'arranger pour qu'une ou l'autre partie de votre script passe en commentaire pour que votre script tombe à l'eau.
Pour plus de détails sur les injections SQL (ce cours risque de saturer à lui seul le forum si je les écris ici ^^) voici un excellent site dédié à ce genre de problèmes:
http://www.phpsecure.info/v2/article/InjSql.php
3) Sécuriser une session
Nous allons enfin passer à la dernière partie: la sécurisation des sessions.
Pour sécuriser une session, une manière simple consiste à vérifier si l'adresse ip du client correspond à l'adresse ip enregistrer sur la session, comme ceci:
| Code: | <?php
function session_start_secure()
{
//On démarre la session
session_start();
/* On va maintenant récupérer la valeur stockée dans la session.
* On verra plus tard dans ce tutorial l'utilisation de la fonction dechiffre().
* Pour l'instant, il nous suffit de savoir qu'elle renvoi un résultat sous forme de
* texte. */
if(!isset($_SESSION['user_ip']) || dechiffre($_SESSION['user_ip']) != $_SERVER['REMOTE_ADDR'])
{
/* Si nous sommes ici, c'est que l'ip ne correspond pas.
* Vous pouvez par exemple choisir d'enregistrer alors l'ip
* ou le pseudo qui à été piraté... la première chose à faire
* consiste tout de même à fermer la session */
session_unset();
session_destroy();
//Ici vos propres réactions....
die('Hacking Attempt!!');
}
//fin de la fonction
return true;
}
?> |
C'est une première chose, et une étape importante. Mais hélas, pas totalement suffisante. Pourquoi? Pour une raison simple: si quelqu'un, dans une salle de jeux par exemple, utilise une session laissée ouverte sans redémarrer l'ordinateur, l'ip n'aura pas changé... Pour assurer une plus grande fiabilité, on va donc coder/hacher les données.
Voyons donc les données à hacher, tout d'abord. Il y en à relativement peut, en général. Mais l'une d'entre elles doit l'être: le mot de passe!
Pour assurer la sécurité de celui-ci, pensez donc toujours à utiliser md5($pass) pour le hacher.
Maintenant, les autres données... Et bien, nous aimerions bien empêcher un pirate quelconque de les trouver trop facilement.
Pour cela, nous allons donc créer une fonction chiffre() et une autre dechiffre(); ces deux fonctions permettront de crypter un texte.
Note: La fonction que nous allons présenter ici n'est qu'une ébauche de fonction de cryptage. En effet, les connaissances mathématiques nécessaires à la création d'un véritable algorithme dépassent largement les objectifs de ce tutorial. En revanche, si votre serveur possède la librairie mcrypt, vous pouvez l'utiliser pour générer des cryptages bien plus complexes.
Notre cryptage sera basé sur ceci: pour chaque lettre de notre clé, nous additionnerons son code ascii à celui de la lettre de départ.
Voici donc notre fonction de cryptage:
| Code: | <?php
function chiffre($texte)
{
//Essayez de faire une clé plus complexe, bien sur....
$cle = 'cle';
//Cette variable contient le numéro actuel du caractère dans la clé
$clecar = 0;
//Et celle-ci contient la chaîne de retour
$return = '';
//Nous allons ici parcourir chaque caractère de la chaîne
for($t = 0; $t < strlen($texte); $t++)
{
/* La fonction chr() renvoi le caractère correspondant à un code ascii.
* A l'inverse, la fonction ord() renvoi le code ascii correspondant à un
* caractère. */
$return .= chr(ord($texte{$t}) + ord($cle{$clecar}));
/* On va maintenant tester si nous n'avons pas atteint la fin de la clé.
* Je rappelle que ++$clecar incrémente de 1 $clecar AVANT le test, tandis
* que $clecar++ l'incrémente après. */
if(++$clecar > strlen($cle))
$clecar = 0;
}
//On renvoi maintenant le texte codé
return $return;
}
?> |
La fonction correspondante, dechiffre(), se fait exactement de la même manière (merci, copier/coller )
| Code: | <?php
function dechiffre($texte)
{
//Essayez de faire une clé plus complexe, bien sur....
$cle = 'cle';
//Cette variable contient le numéro actuel du caractère dans la clé
$clecar = 0;
//Et celle-ci contient la chaîne de retour
$return = '';
//Nous allons ici parcourir chaque caractère de la chaîne
for($t = 0; $t < strlen($texte); $t++)
{
/* La fonction chr() renvoi le caractère correspondant à un code ascii.
* A l'inverse, la fonction ord() renvoi le code ascii correspondant à un
* caractère. */
$return .= chr(ord($texte{$t}) - ord($cle{$clecar}));
/* On va maintenant tester si nous n'avons pas atteint la fin de la clé.
* Je rappelle que ++$clecar incrémente de 1 $clecar AVANT le test, tandis
* que $clecar++ l'incrémente après. */
if(++$clecar > strlen($cle))
$clecar = 0;
}
//On renvoi maintenant le texte codé
return $return;
}
?> |
Et voila! Ce qui nous donne au final le fichier suivant:
| Code: | <?php
function session_start_secure()
{
//On démarre la session
session_start();
/* On va maintenant récupérer la valeur stockée dans la session.
* On verra plus tard dans ce tutorial l'utilisation de la fonction dechiffre().
* Pour l'instant, il nous suffit de savoir qu'elle renvoi un résultat sous forme de
* texte. */
if(!isset($_SESSION['user_ip']) || dechiffre($_SESSION['user_ip']) != $_SERVER['REMOTE_ADDR'])
{
/* Si nous sommes ici, c'est que l'ip ne correspond pas.
* Vous pouvez par exemple choisir d'enregistrer alors l'ip
* ou le pseudo qui à été piraté... la première chose à faire
* consiste tout de même à fermer la session */
session_unset();
session_destroy();
//Ici vos propres réactions....
die('Hacking Attempt!!');
}
//fin de la fonction
return true;
}
function chiffre($texte)
{
//Essayez de faire une clé plus complexe, bien sur....
$cle = 'cle';
//Cette variable contient le numéro actuel du caractère dans la clé
$clecar = 0;
//Et celle-ci contient la chaîne de retour
$return = '';
//Nous allons ici parcourir chaque caractère de la chaîne
for($t = 0; $t < strlen($texte); $t++)
{
/* La fonction chr() renvoi le caractère correspondant à un code ascii.
* A l'inverse, la fonction ord() renvoi le code ascii correspondant à un
* caractère. */
$return .= chr(ord($texte{$t}) + ord($cle{$clecar}));
/* On va maintenant tester si nous n'avons pas atteint la fin de la clé.
* Je rappelle que ++$clecar incrémente de 1 $clecar AVANT le test, tandis
* que $clecar++ l'incrémente après. */
if(++$clecar > strlen($cle))
$clecar = 0;
}
//On renvoi maintenant le texte codé
return $return;
}
function dechiffre($texte)
{
//Essayez de faire une clé plus complexe, bien sur....
$cle = 'cle';
//Cette variable contient le numéro actuel du caractère dans la clé
$clecar = 0;
//Et celle-ci contient la chaîne de retour
$return = '';
//Nous allons ici parcourir chaque caractère de la chaîne
for($t = 0; $t < strlen($texte); $t++)
{
/* La fonction chr() renvoi le caractère correspondant à un code ascii.
* A l'inverse, la fonction ord() renvoi le code ascii correspondant à un
* caractère. */
$return .= chr(ord($texte{$t}) - ord($cle{$clecar}));
/* On va maintenant tester si nous n'avons pas atteint la fin de la clé.
* Je rappelle que ++$clecar incrémente de 1 $clecar AVANT le test, tandis
* que $clecar++ l'incrémente après. */
if(++$clecar > strlen($cle))
$clecar = 0;
}
//On renvoi maintenant le texte codé
return $return;
}
?> |
Il suffit juste de penser à utiliser $_SESSION['variable'] = chiffre($variable) pour assigner une valeur. Simple, non?
Attention! L'utilisation d'une fonction de cryptage ne vous dispense pas d'utiliser la fonction md5() ou sha1() sur les données sensibles, comme le mot de passe.
Et pour ceux qui resteraient dubitatifs, voici pour terminer un petit exemple de chiffrage / déchiffrage utilisant les deux fonctions précédentes:
| Code: | <?php
function chiffre($texte)
{
//Essayez de faire une clé plus complexe, bien sur....
$cle = 'cle';
//Cette variable contient le numéro actuel du caractère dans la clé
$clecar = 0;
//Et celle-ci contient la chaîne de retour
$return = '';
//Nous allons ici parcourir chaque caractère de la chaîne
for($t = 0; $t < strlen($texte); $t++)
{
/* La fonction chr() renvoi le caractère correspondant à un code ascii.
* A l'inverse, la fonction ord() renvoi le code ascii correspondant à un
* caractère. */
$return .= chr(ord($texte{$t}) + ord($cle{$clecar}));
/* On va maintenant tester si nous n'avons pas atteint la fin de la clé.
* Je rappelle que ++$clecar incrémente de 1 $clecar AVANT le test, tandis
* que $clecar++ l'incrémente après. */
if(++$clecar > strlen($cle))
$clecar = 0;
}
//On renvoi maintenant le texte codé
return $return;
}
function dechiffre($texte)
{
//Essayez de faire une clé plus complexe, bien sur....
$cle = 'cle';
//Cette variable contient le numéro actuel du caractère dans la clé
$clecar = 0;
//Et celle-ci contient la chaîne de retour
$return = '';
//Nous allons ici parcourir chaque caractère de la chaîne
for($t = 0; $t < strlen($texte); $t++)
{
/* La fonction chr() renvoi le caractère correspondant à un code ascii.
* A l'inverse, la fonction ord() renvoi le code ascii correspondant à un
* caractère. */
$return .= chr(ord($texte{$t}) - ord($cle{$clecar}));
/* On va maintenant tester si nous n'avons pas atteint la fin de la clé.
* Je rappelle que ++$clecar incrémente de 1 $clecar AVANT le test, tandis
* que $clecar++ l'incrémente après. */
if(++$clecar > strlen($cle))
$clecar = 0;
}
//On renvoi maintenant le texte codé
return $return;
}
$variable = 'Mouche';
echo 'Variable: ' . $variable;
$variable = chiffre($variable);
echo '<br>Crypté: ' . $variable;
$variable = dechiffre($variable);
echo '<br>Décrypté: ' . $variable;
?> |
Note: un moyen simple pour générer une bonne clé consiste à utiliser la fonction md5() (si vous utilisez un algorithme qui limite le nombre de caractère de la clé, mcrypt par exemple) ou cha1() (pour les algorithme comme le nôtre qui ne limite pas la taille de la clé) sur une valeur qui change constamment (l'heure systeme par exemple: vous l'obtenez grâce à la fonction time()). Utilisez donc:
pour afficher votre clé
Une autre méthode, pour obtenir des clés plus sure, est d'utiliser une fonction simple choisissant pour chaque charactère un numéro entre 33 et 126 (donc un caractère ASCII au hasard). Cela se résume à ceci:
| Code: | <?php
function make_key($key_size = 8)
{
//On prépare une variable vide, qui sera remplie et retournée
$return = '';
//On initialise le générateur de nombre aléatoire. Cette étape n'est
//plus indispensable depuis PHP 4.2.0
mt_srand(make_seed());
//On tire un caractère pour chaque lettre de la chaine
for($t = 0; $t < $key_size; $t++)
{
$return .= chr(mt_rand(33, 126))
}
//Et on renvoi le resultat
return $return;
}
//Cette fonction est tirée du manuel PHP
function make_seed()
{
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}
?> |
Et voila
Et bien voila, c'est la fin de cette courte introduction à la sécurité. Si le sujet vous intéresse, je vous recommande la lecture du magazine misc, particulièrement intéressant à ce sujet. _________________
Jeu en ligne .:. Mon blog |
|
| Revenir en haut de page |
|
 |
Houram Fou du village

Inscrit le: 02 Jan 2005 Messages: 309 Localisation: Dingy-st-Clair, la campagne quoi !
|
Posté le: Jeu 28 Avr 2005 à 12:44 Sujet du message: |
|
|
Salut !
C'est vraiment un super tuto qui m'a fait prendre conscience de pleins de choses.
J'ai juste une question, peut t'on enchainer deux méthodes de hackages comme ceci :
| Code: | | sha1(md5($variable)) |
et si oui, est-ce que ceçi augmentera la sécurité ?
@++ |
|
| Revenir en haut de page |
|
 |
Alcazarfr Moddeurs

Inscrit le: 04 Nov 2004 Messages: 2408 Localisation: Dans le port d'Amsterdam, [...]
|
Posté le: Sam 30 Avr 2005 à 18:23 Sujet du message: |
|
|
Dans le train qui m'amenait en vacances (Ma Vie), je me le suis demandé aussi (je cherchais comment passer le md5)
Je ne pense pas que cela puisse faire du mal, tant que l'on respecte l'ordre d'utilisation de ces 2 fonctions... _________________ Je n'utilise en aucun cas MSN Messenger & je ne participe pas au projet de site
// En vacances |
|
| Revenir en haut de page |
|
 |
Super_Végéta74 Mangouste platonique
Inscrit le: 23 Fév 2006 Messages: 25
|
Posté le: Dim 26 Fév 2006 à 1:49 Sujet du message: |
|
|
bete que tu te soit fé chier a écrire tout sa
regarde le décryptere :
Edité par Alcazarfr pour le lien, il ne faudrait pas donner de mauvaise idée |
|
| Revenir en haut de page |
|
 |
Houram Fou du village

Inscrit le: 02 Jan 2005 Messages: 309 Localisation: Dingy-st-Clair, la campagne quoi !
|
Posté le: Dim 26 Fév 2006 à 20:05 Sujet du message: |
|
|
Je vois pas en quoi il decrypte, et encore moin ce qui rend inutile le tuto d'aramiil...
edit : si tu lis les infos de la page, tu vois que il ne fait que chercher dans une base de donné de mdp crypter, c'est donc nul je trouve^^ |
|
| Revenir en haut de page |
|
 |
Super_Végéta74 Mangouste platonique
Inscrit le: 23 Fév 2006 Messages: 25
|
Posté le: Dim 26 Fév 2006 à 23:15 Sujet du message: |
|
|
| Oui mais sa rend son tuto sur la sécuriter casé prk il sufit de tombé sur le patch du forum se qui est trés facil et on tombe sur le mdp qu'il ne nous reste plus uq'a décrypter |
|
| Revenir en haut de page |
|
 |
Houram Fou du village

Inscrit le: 02 Jan 2005 Messages: 309 Localisation: Dingy-st-Clair, la campagne quoi !
|
Posté le: Mer 01 Mar 2006 à 22:41 Sujet du message: |
|
|
Le lien que tu as donné est loin de permettre de tout décrypter...
De plus c'est un tutoriaux, pas un patch, il explique juste aux codeurs comment sécuriser, chacun peut et même doit ensuite le personaliser. |
|
| Revenir en haut de page |
|
 |
|
|
Vous ne pouvez pas poster de nouveaux sujets dans ce forum Vous ne pouvez pas répondre aux sujets dans ce forum Vous ne pouvez pas éditer vos messages dans ce forum Vous ne pouvez pas supprimer vos messages dans ce forum Vous ne pouvez pas voter dans les sondages de ce forum Vous ne pouvez pas joindre des fichiers Vous ne pouvez pas télécharger des fichiers
|
|