SÉCURISATION DE FORMULAIRE

Arto_8000 Messages postés 1044 Date d'inscription lundi 7 mars 2005 Statut Membre Dernière intervention 13 juillet 2010 - 16 juin 2010 à 02:47
lighta971 Messages postés 1 Date d'inscription samedi 24 juillet 2010 Statut Membre Dernière intervention 3 août 2010 - 3 août 2010 à 11:52
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

lighta971 Messages postés 1 Date d'inscription samedi 24 juillet 2010 Statut Membre Dernière intervention 3 août 2010
3 août 2010 à 11:52
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é)
?>
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
21 juin 2010 à 19:37
Ah ben je savais pas. Je pensais que comme en ASP3, plusieurs requêtes pouvaient être exécutées.
Arto_8000 Messages postés 1044 Date d'inscription lundi 7 mars 2005 Statut Membre Dernière intervention 13 juillet 2010 7
21 juin 2010 à 19:28
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.
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
21 juin 2010 à 19:03
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;]
Arto_8000 Messages postés 1044 Date d'inscription lundi 7 mars 2005 Statut Membre Dernière intervention 13 juillet 2010 7
21 juin 2010 à 18:58
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
destinyfr Messages postés 106 Date d'inscription samedi 19 mai 2007 Statut Membre Dernière intervention 13 avril 2009
21 juin 2010 à 17:35
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
masternico Messages postés 487 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 1 septembre 2011
21 juin 2010 à 10:15
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é';
}
?>
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
16 juin 2010 à 20:28
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.
ultimacsplayer Messages postés 29 Date d'inscription mardi 1 février 2005 Statut Membre Dernière intervention 16 juin 2010
16 juin 2010 à 15:49
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é!
Arto_8000 Messages postés 1044 Date d'inscription lundi 7 mars 2005 Statut Membre Dernière intervention 13 juillet 2010 7
16 juin 2010 à 15:36
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.
destinyfr Messages postés 106 Date d'inscription samedi 19 mai 2007 Statut Membre Dernière intervention 13 avril 2009
16 juin 2010 à 12:31
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 ;)
ultimacsplayer Messages postés 29 Date d'inscription mardi 1 février 2005 Statut Membre Dernière intervention 16 juin 2010
16 juin 2010 à 08:13
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.
ultimacsplayer Messages postés 29 Date d'inscription mardi 1 février 2005 Statut Membre Dernière intervention 16 juin 2010
16 juin 2010 à 07:31
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.
Arto_8000 Messages postés 1044 Date d'inscription lundi 7 mars 2005 Statut Membre Dernière intervention 13 juillet 2010 7
16 juin 2010 à 02:47
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.
Rejoignez-nous