SÉCURISATION DE FORMULAIRE

Signaler
Messages postés
1044
Date d'inscription
lundi 7 mars 2005
Statut
Membre
Dernière intervention
13 juillet 2010
-
Messages postés
1
Date d'inscription
samedi 24 juillet 2010
Statut
Membre
Dernière intervention
3 août 2010
-
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/51917-securisation-de-formulaire

Messages postés
1
Date d'inscription
samedi 24 juillet 2010
Statut
Membre
Dernière intervention
3 août 2010

Autre méthode...

<?php
$erreur = null;
$success = null;
if(!preg_match('#^[a-z0-9\-_]+$#i'$_POST['value1'])) // 1er variable: caractères autorisés, lettres - chiffres - underscores - tirets
{
$erreur = 0;
}
else if(!preg_match('#^[a-z]+$#i'$_POST['value2'])) //2eme variable: caracteres autorisés, lettres
{
$erreur = 0;
}
// else if...
if(empty($erreur)) { // si $erreur toujours null, alors il n'y a pas eu d'erreur donc les variables sont clean
$success = 1
//si requete sql, aouter mysql_real_escape_string
}
echo $success.$erreur; // affichage des resultats, null (si le script n'a pas été exécuté)
?>
Messages postés
3983
Date d'inscription
jeudi 14 juillet 2005
Statut
Membre
Dernière intervention
30 juin 2013
12
Ah ben je savais pas. Je pensais que comme en ASP3, plusieurs requêtes pouvaient être exécutées.
Messages postés
1044
Date d'inscription
lundi 7 mars 2005
Statut
Membre
Dernière intervention
13 juillet 2010
6
ghuysmans99 -> mysql_query ne permet pas d'avoir plusieurs requêtes en même temps, ça va juste de sortir un exception si tu essaies de faire ça.
Messages postés
3983
Date d'inscription
jeudi 14 juillet 2005
Statut
Membre
Dernière intervention
30 juin 2013
12
Et pas que des SELECT. Tu entres ça sans les crochets ['or 'a'='a';DELETE * FROM Users WHERE 'a'='a] et ça te fout en l'air ta table (là ça marchera avec du MySQL si la requête du script est [SELECT * FROM Users WHERE user=$user AND pass=$pass;]
Messages postés
1044
Date d'inscription
lundi 7 mars 2005
Statut
Membre
Dernière intervention
13 juillet 2010
6
masternico -> Le problème c'est que les injections SQL ne servent pas juste à contourner un login. Tu laisse carrément un accès à n'importe qui de faire des requêtes select. Tout dépendant de la base de données que tu utilises, ça laisse la possibilité d'avoir une fuite de ta base de données au complet.

Exemple d'entrée qui pose problème :

' UNION ALL SELECT * FROM INFORMATION_SCHEMA INTO OUTFILE 'chemin/Accessible/Du/Net.txt
Messages postés
106
Date d'inscription
samedi 19 mai 2007
Statut
Membre
Dernière intervention
13 avril 2009

if($login_to_test == $this->login) => théoriquement oui car l'utilisateur que tu as récupéré via ta requête correspond à l'utilisateur envoyé par la personne (d'où le where login).
Le cas contraire tu auras une erreur que tu auras déjà détecté via ta requête (ça pourrait d'ailleurs être plus safe..).

Pourquoi faire autant de choses inutiles :o ? Ou alors c'est que j'ai rien compris à ce que tu veux faire avec ta classe XD
Messages postés
494
Date d'inscription
dimanche 5 octobre 2003
Statut
Membre
Dernière intervention
1 septembre 2011

Perso, je préfère une autre approche.
D'abord, je recherche l'utilisateur à partir du login fourni.
dans un deuxième temps, je regarde si le login récupéré et celui fourni correspondent et si oui, alors je regarde si le mot de passe récupéré par la requette correspond à celui entré par l'utilisateur.

<?
class utilisateurs
{
public $login;
public $pass;
public $error_string;
private $connected;

private $user_row;

public function __construct()
{
$this->connected = FALSE;
}

private function get_user_row()
{
// recuperer les infos de l'utilisateur
$login=mysql_real_escape_string($this->login);
$sql = 'SELECT login,password FROM login WHERE login=\'' . $login . '\'';
$sql2=mysql_query($sql);
$slq3=mysql_num_rows($sql2);
$errno = mysql_errno($sql2);
if(($errno == 0) AND ($sql3==1)){
$this->user_row = mysql_fetch_assoc($sql2);
return(TRUE);
}else{
$this->error_string = mysql_error();
return(FALSE);
}
}
public function test_login()
{
// vérifier si le login correspond
if(isset($this->user_row['login']))
{
$login_to_test = $this->user_row['login'];
if($login_to_test == $this->login)
{
return(TRUE);
}
else
{
$this->error_string = 'Tentative d\'injection?';
return(FALSE);
}
}
else
{
$this->error_string = 'Login inconnu';
return(FALSE);
}
}

public function test_pass()
{
// vérifier si le mot de passe correspond
$pass_to_test = $this->user_row['password'];
if($pass_to_test == $this->pass)
{
return(TRUE);
}
else
{
$this->error_string = 'Mot de passe incorrecte';
return(FALSE);
}
}

public function connect()
{
if(!$this->get_user_row())
{
$return(FALSE);
}
if(!$this->test_login())
{
$return(FALSE);
}
if(!$this->test_pass())
{
$return(FALSE);
}
$this->connected = TRUE;
}

public function is_connected()
{
return($this->connected == TRUE);
}
}

$utilisateur = new utilisateurs();
$utilisateur->login = $login;
$utilisateur->pass = $pass;
if(!$utilisateur->connect())
{
// pas de bol
echo $this->error_string;
}
else
{
echo 'connecté';
}
?>
Messages postés
3983
Date d'inscription
jeudi 14 juillet 2005
Statut
Membre
Dernière intervention
30 juin 2013
12
Je ne vois pas l'utilité de procéder comme ça : par défaut, PHP échape les chaines de caractères. Pour les nombres, il suffit (à mon sens) de les caster dans leur type respectif.
Messages postés
29
Date d'inscription
mardi 1 février 2005
Statut
Membre
Dernière intervention
16 juin 2010

Merci pour vos informations, et surtout pour la derniere requete de Arto, il est clair que l'injection sql ne se limite pas à bannir certains champs.

Je pensais bien faire en partageant un bout de code anti injection, et grace à vous, il y a une meilleur solution que celle que j'ai proposé!
Messages postés
1044
Date d'inscription
lundi 7 mars 2005
Statut
Membre
Dernière intervention
13 juillet 2010
6
Exemple de problème :

<?php
$sql = 'SELECT * FROM Infos WHERE id="' . $tonChampFiltrer . '"';
?>

Si j'envois comme valeur : 1" AND 1 LIKE 0 UNION ALL SELECT * FROM Users WHERE "1" LIKE "1, ton truc n'a absolument rien filtrer et la requête passe.

Aussi des entrées avec des caractères spéciaux peuvent être normal, il faut simplement bien les prendre en charge. Ce genre de contrôle peut exaspéré les utilisateurs d'un site, les caractères spéciaux que tu «bannis» peuvent quand même être utiliser de façon normal par des utilisateurs.

L'idéale comme solution c'est d'utiliser les requêtes paramètrées avec PDO ou d'utiliser des librairies qui prennent en charge des requêtes paramètrées pour mysql (si PDO n'est pas disponible). Le problème, à la source, est que les données sont mises directement dans la requête et qu'ils peuvent la modifier, il faut donc essayer qu'il passe ailleurs que directement dans la requête. C'est pour ça que les requêtes paramètrées restent et resteront toujours la meilleur solution à envisager pour sécurisé une requête SQL.
Messages postés
106
Date d'inscription
samedi 19 mai 2007
Statut
Membre
Dernière intervention
13 avril 2009

Salut,

Pourquoi réinventer la chose (en bien moins performant d'ailleurs), alors qu'il existe déjà plein de fonctions pour sécuriser les données ? (Par exemple : filter_*).
De plus, ton code n'est pas vraiment adapté pour une réutilisation...

Bye ;)
Messages postés
29
Date d'inscription
mardi 1 février 2005
Statut
Membre
Dernière intervention
16 juin 2010

J'ai corrigé ce qui te posais probleme, il y a maintenant la requete sql et le soucis injection.
Il y a aussi mysql_real_escape_string()

C'est peut etre suffisant d'avoir juste mysql_real_escape_string pour éviter l'injection sql, mais mieux vaut avoir le maximum de sécurité.

Par contre Arto_8000, je veux bien que tu me donne des solutions ou exemple pour me montrer que le code ci-dessus est exploitable, afin que je l'améliore.
Messages postés
29
Date d'inscription
mardi 1 février 2005
Statut
Membre
Dernière intervention
16 juin 2010

En fait, a la place de

#
# if($_POST['pseudo']=="Chris" && $_POST['pass']=="test"){
# echo "Bienvenue ".$_POST['pseudo'].", votre mot de pass est ".$_POST['pass']."!";
# }

c'est là qu'on met le code qui se connecte a la base de donnée et qui regarde si le pseudo et pass est correct.
Messages postés
1044
Date d'inscription
lundi 7 mars 2005
Statut
Membre
Dernière intervention
13 juillet 2010
6
Honnêtement c'est très mauvais comme approche, parce qu'au lieu d'essayer de régler le problème à la source, tu fais simplement quelque chose qui va être un peu plus dur à exploiter, mais qui est tout de même exploitable.

Pour régler un problème en sécurité informatique il faut regarder pourquoi un code est exploitable et non pas quelles sont les entrées qui peuvent exploiter la faille.

Aussi le problème des caractères spéciaux ' et ", s'applique pratiquement uniquement lors de requête SQL. Dans l'exemple que tu montres il n'y a aucune requête SQL qui est effectuée avec les paramètres entrées par l'utilisateur, donc il n'y a aucune raison de se méfier des caractères spéciaux.