1
votes

comportement bizarre de mysql agissant comme faux = la chaîne est vraie

Je testais quelques requêtes et j'ai obtenu un résultat bizarre.

J'ai testé la requête suivante

Select 1 from Persons where 1=1='a';//returns nothing
select 1 from Persons where 1=2='a';//returns 1

cela renvoie les crédits de l'administrateur (nom d'utilisateur et mot de passe) p>

Donc, si j'ai raison, password = username = 'a' est retourné true ..

mais comment?

alors J'ai testé plus de requêtes et j'ai obtenu le résultat suivant

SELECT * FROM Persons where username = 'admin' and password = username = 'a'

so true = 'a' is false and false = 'a' is true?

Merci ,


1 commentaires

AVERTISSEMENT : Vous ne devez jamais stocker les mots de passe sous forme de texte brut.


4 Réponses :


4
votes

Probablement ceci:

0 = 0 

renvoie false qui pour MySql est évalué comme 0 .
Puis ceci:

0 = 'a'

après MySql essaie implicitement de convertir 'a' en un nombre pour évaluer l'expression et parce que 'a' ne peut pas être converti en nombre, le résultat de la conversion est 0 .
Vous pouvez trouver tout ce que vous devez savoir sur les conversions implicites ici: 12.3 Conversion de type dans l'évaluation des expressions .
Donc:

password = username

renvoie true.


0 commentaires

1
votes

Mysql convertit les variables dans le type de variable de gauche. Ainsi, l'expression password = username = 'a' peut être exprimée comme ceci:

password = username // 0 (false)

0 = 'a' // 1 (true), car CAST ('a' AS INTEGER) = 0

Même chose pour 1 = 1 = 'a' code>: 1 = 1 // 1 (vrai) 1 = 'a' // 0 (false), car CAST ('a' AS INTEGER) = 0

Et pour 1 = 2 = 'a' :

1 = 2 // 0 (faux)

0 = 'a' // 1 ( true), car CAST ('a' AS INTEGER) = 0

Vous pouvez essayer la requête suivante pour vérifier ceci:

SELECT "string1" = "string2", 0 = "a", CAST('a' AS INTEGER);


0 commentaires

1
votes

tout d'abord, lorsque vous faites x = y = z , ce qui se passe réellement est (x = y) = z ce qui signifie que vous comparez password = username (false, pour chaque utilisation qui sait comment choisir un mot de passe fort ...) à 'a'.

Maintenant, le problème avec les booléens dans mySql est qu'ils sont représentés par tinyint - 1 est vrai , 0 est faux. vous pouvez le voir en exécutant select true - vous obtiendrez 1 comme résultat.
Cela fonctionne également avec des chaînes - '1' par rapport à booléen est vrai, toute autre chaîne est fausse, vous pouvez exécuter ces deux et voir que vous obtiendrez 1 comme résultat:

select true = 1;
select true = '1';
select false = 0;
select false = '0';
select false = 'any other string';


0 commentaires

1
votes

MySQL traite false comme 0 et true comme 1. Cela permet aux hacks spécifiques à MySQL comme

  SELECT 1 = 1 = 1, (1 = 1) = 1

de faire des rapports légers de style pivot.

Cela ressemble à Le traitement par MySQL des clauses WHERE contenant plus d'un comparateur s'exécute de gauche à droite. Donc

  SELECT 1 = 1

donne 1, tout comme ces deux expressions équivalentes.

 SELECT COUNT(*), SUM(active = 1) active, SUM(active <> 1)inactive FROM tbl
  

Maintenant, 0 = 'a' renvoie 1 (vrai) à cause d'une autre bizarrerie MySQL qui contraint les chaînes à des entiers en interprétant les premiers chiffres de la chaîne comme un entier. Ainsi, 7 = '7a' vaut 1 (vrai) tout comme 0 = '0a' (et 0 = 'a' ). Mais 6 = '7a' est faux (0).

La morale de l'histoire? Pour un code clair, évitez les clauses WHERE avec plus d'un comparateur.


0 commentaires