Aller au contenu

Failles de sécurité les plus fréquentes en relation directe/indirecte php


mars073
 Share

Recommended Posts

Bonjour à tous,

Aujourd'hui je fais essayer de faire un truc plus sérieux, les failles les plus courantes (sql, xss, csrf et exploit cookie).

 

Les failles SQL, c'est le fait que le client peut modifier une requête sql sur vote site, ses failles peuvent permettent de modifier, afficher, supprimer toutes les tables voir la base de donnée.

Contexte: J'affiche mes news avec une variable ?page dans l'url

<?php
	$query = mysql_query("SELECT * FROM `news` LIMIT ".$_GET['page'].",10");
	?>
normalement l'url va ressemble à: http://mars073.be/faille.php?page=2 .

mais si quelqu'un écrit : http://mars073.be/faille.php?page=2;TRUNCATE%20`news`#

bah... vous perdez toutes vos news, la requête sera double:

SELECT * FROM `news` LIMIT 2;
TRUNCATE `news`;
#,10
il existe des programmes pour exploiter plus facilement les failles ils permettent aussi de lister les autres tables ._.

solution:

1 - vérifier que la variable est un chiffre (numérique);

<?php
	$page = 0;
	if (isset($_GET['page'])&&is_numeric($_GET['page'])) $page = $_GET['page'];
	$query = mysql_query("SELECT * FROM `news` LIMIT $page,10");
	?>
étrangement cette erreur est très fréquente encore... mais bon parfois y a un pare-feu derrière et c'est pas marrant :(

2-dans le cadre où il s'agit d'un texte faites appel à la fonction: addslashes(). Exemple: $titre = addslashes($_GET['titre']);

3-Simplement coder en pdo mais ça peut-être dérangeant quand vous n'avez pas codé le site et que vous devez donc tout refaire...

Les failles xss, aussi très courantes c'est une faille qui permet au client d'afficher du code html ou javascript, ce qui permet de faire des forkbomb, redirections, voler les logins, etc.

Contexte: je débute et j'ai fais une chatbox avec une faille xss:

<?php
	$query = $cxn->query("SELECT * FROM `chat`");
	$query->execute();
	while ($msg = $query->fetch()) {
		echo $msg['user']." a dit:".$msg['content'];
	}
	?>
maintenant Jean-Kevin envoie le message suivant:

<meta http-equiv="refresh" content="0;url=http://JeanKevdu06.free.fr/">
ce qui aura pour effet de rediriger une fois la page charger sur un autre site.

pour pallier à ce problème il suffit de faire appel à une fonction: htmlspecialchars(), il existe d'autre fonction avec plus où moins le même effet, c'est à dire convertir le code en caractère lisible.

exemple avec le code au dessus:

<?php
	$query = $cxn->query("SELECT * FROM `chat`");
	$query->execute();
	while ($msg = $query->fetch()) {
		$msg['content'] = htmlspecialchars($msg['content']);
		// Dans le contexte le nom d'utilisateur ne peut pas comporter de caractères spéciaux.
		echo $msg['user']." a dit:".$msg['content'];
	}
	?>
je considère les failles "include" comme des failles xss mais si c'est pas totalement vrai, je suppose que vous connaissez tous la fonction include(), vu que c'est la base du php... Bref beaucoup de site utile utilise une variable $_GET (ex: $_GET['p']) et donc il font un code du genre:

<?php
	if (isset($_GET['p'])&&is_file($_GET['p'])) include("pages/".$_GET['p'].".php");
	?>
mais bon une fois de plus si le méchant utilisateur change l'url: en ?p=../includes/config bah... ça inclue le fichier config ._.

il y a beaucoup de façon différente pour résoudre cette faille mais dans le contexte ej vais utiliser le switch()

<?php
	if (isset($_GET['p'])) { //on test si la page est spécifiée
		switch (strtolower($_GET['p'])) { // test la valeur de la variable en minuscule pour avoir plus facile
		case 'home':
			include("pages/home.php"); //l'acccueil
		break;
		case 'contact':
			include("pages/contact.php");
		break;
		case 'machin':
			include("pages/machin.php"); // machin 
		break;
		default:
			include("pages/404.php"); //page d'erreur
		}
	} else {
		include("pages/home.php"); //si aucune page spécifiée on met l'accueil
	}
	?>
Les failles csrf, déjà plus rare, ça consiste dans le faire exécuter par le biais d'une image comme une signature sur un forum, je vais prendre pour exemple un forum.

Contexte: Je fais une signature qui va vous déconnecter automatiquement quand vous l'afficherait:

je mets le lien pour se déconnecter comme le lien d'une image.
[img=http://forum.mars073.be/deconnect.php]
Dans ce cas ci il faut utiliser un token, c'est une variable qui va contenir une suite aléatoire.

Exemple dans votre script de connexion vous allez surement utiliser des variables $_SESSION, donc il suffit d'ajouter dans votre script de connexion:

<?php
	// ...
	$_SESSION['token'] = dechex(rand(0, 999999))."-".dechex(rand(0, 999999));
	?>
votre bouton déconnexion:

<a href="deconnect.php?t=<?=$_SESSION['token']?>">Déconnexion</a>
et le script deconnect.php:

<?php
	session_start();
	if (isset($_GET['t'])&&$_GET['t']==$_SESSION['token']) {
		session_unset();
		session_destroy();
		echo "Vous avez bien été déconnecté";
	} else {
		echo "La requête est incorrect";
	}
	?>
Le forum Melinyel a un système similaire mais en plus n'autorise que certaines extensions mais le systèmes d'extension ne sert à rien vu qu'il peut être trompé avec le ".htaccess".

Nous arrivons donc au dernier type de faille les voles de cookies, miam miam...

Contexte: mon script php camouflé en "cookie.png" doit voler le cookie du nom de "autolog" qui permet que le compte se connecter automatiquement.

/!\Rappel: le cookie est stocké du coté client il y a un risque de modification, donc cryptait le un maximum pour pas qu'il puisse détourner sa connexion sur un autre compte, comme pour les variables caché html ou js.

donc nous allons créer votre cookie avec une protection correcte:

$crypt = $user['id']."|".md5(sha1($user['name']).$user['haspass']);
setcookie( "autolog", $crypt, time()+60*60*24*31, "./marsLogin", "mars073.be", false, true);
donc $crypt dans mon exemple est composé de l'id de l'utilisateur et le cumule crypté du nom d’utilisateur crypté et de son mot de passe crypté, même crypté normalement on ne met pas le mot de passe dans le cookie je dis bien normalement.

paramètres de mon cookie:

1 - Son nom: "autolog"

2 - sa valeur: $crypt

3 - sa date d'expiration en seconde: 31jours après création

4 - dossier ou je vais le ranger

5 - le seul site (domaine) qui a le droit d'y accéder: "mars073.be"

6 - si le cookie ne peut être utilisé que par des site en https:// : non (si votre site à le https:// mettez "true" si vous voulez)

7 - Interdit la modification du cookie par du javascript par exemple (ne fonctionne pas tout le temps).

mais comment faire maintenant pour vérifier l'utilisateur?

Comme ça:

<?php
	if (isset($_COOKIE['autolog'])) {
		$data = explode("|", $_COOKIE['autolog'];	// On sépare l'id du reste
		if (isset($data[1])&&is_numeric($data[0])) {	// On vérifie la structure du cookie
			$query = $db->query("SELECT * FROM `user` WHERE `id` = ".$data[0]." LIMIT 1");
			$query->execute();
			$user = $query->fetch();
			if ($data[1] == md5(sha1($user['name']).$user['haspass'])) {
				$_SESSION['login'] = $user;
				echo "Connexion réussite";
			} else {
				echo "cookie incorrect";
			}
		} else {
			echo "Cookie corrumpue";
		}
	}
	?>
Je pense avoir fait le tour des trucs les plus courant en php...

ps: exemple d'image en php qui passe à travers le filtre du forum avec un simple dossier, quand vous actualisez elle change:

mel.png

Bonne programmation à tous!

Cordialement,

Mars073

  • Upvote 4
Lien vers le commentaire
Partager sur d’autres sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Invité
Répondre à ce sujet…

×   Vous avez collé du contenu avec mise en forme.   Supprimer la mise en forme

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Chargement
 Share

×
×
  • Créer...