Arto_8000
Messages postés1044Date d'inscriptionlundi 7 mars 2005StatutMembreDernière intervention13 juillet 2010
-
16 juin 2010 à 02:47
lighta971
Messages postés1Date d'inscriptionsamedi 24 juillet 2010StatutMembreDerniè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.
lighta971
Messages postés1Date d'inscriptionsamedi 24 juillet 2010StatutMembreDerniè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és3983Date d'inscriptionjeudi 14 juillet 2005StatutMembreDernière intervention30 juin 201316 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és1044Date d'inscriptionlundi 7 mars 2005StatutMembreDernière intervention13 juillet 20107 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és3983Date d'inscriptionjeudi 14 juillet 2005StatutMembreDernière intervention30 juin 201316 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és1044Date d'inscriptionlundi 7 mars 2005StatutMembreDernière intervention13 juillet 20107 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és106Date d'inscriptionsamedi 19 mai 2007StatutMembreDernière intervention13 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és487Date d'inscriptiondimanche 5 octobre 2003StatutMembreDerniè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és3983Date d'inscriptionjeudi 14 juillet 2005StatutMembreDernière intervention30 juin 201316 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és29Date d'inscriptionmardi 1 février 2005StatutMembreDernière intervention16 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és1044Date d'inscriptionlundi 7 mars 2005StatutMembreDernière intervention13 juillet 20107 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és106Date d'inscriptionsamedi 19 mai 2007StatutMembreDernière intervention13 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és29Date d'inscriptionmardi 1 février 2005StatutMembreDernière intervention16 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és29Date d'inscriptionmardi 1 février 2005StatutMembreDernière intervention16 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és1044Date d'inscriptionlundi 7 mars 2005StatutMembreDernière intervention13 juillet 20107 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.
3 août 2010 à 11:52
<?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é)
?>
21 juin 2010 à 19:37
21 juin 2010 à 19:28
21 juin 2010 à 19:03
21 juin 2010 à 18:58
Exemple d'entrée qui pose problème :
' UNION ALL SELECT * FROM INFORMATION_SCHEMA INTO OUTFILE 'chemin/Accessible/Du/Net.txt
21 juin 2010 à 17:35
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
21 juin 2010 à 10:15
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é';
}
?>
16 juin 2010 à 20:28
16 juin 2010 à 15:49
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é!
16 juin 2010 à 15:36
<?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.
16 juin 2010 à 12:31
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 ;)
16 juin 2010 à 08:13
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.
16 juin 2010 à 07:31
#
# 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.
16 juin 2010 à 02:47
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.