Question:
L'injection SQL est-elle possible avec LIMIT?
Ali
2014-12-23 17:04:30 UTC
view on stackexchange narkive permalink

Un de mes amis a créé une application Web que je teste pour le plaisir. J'ai remarqué qu'il permet à un utilisateur de définir la limite d'une certaine requête, et cette limite n'est pas nettoyée.

Par exemple, je peux choisir n'importe quel nombre ou chaîne que j'aime comme limite. Je me rends compte qu'il s'agit d'une injection SQL, et je peux facilement injecter des commandes SQL, mais est-il vraiment possible d'extraire des données ou de faire des dégâts avec un LIMIT ?

Exemple de la requête:

  SELECT * FROM messages WHERE non lus = 1 LIMIT ** USER INPUT ICI **  

I comprenez que si l'injection était dans la clause WHERE , j'aurais pu facilement faire un UNION SELECT pour extraire des informations, mais est-ce vraiment possible si l'entrée de l'utilisateur était après le limite?

Pour plus d'informations, mon ami utilise le SGBD MySQL, vous ne pouvez donc pas vraiment exécuter deux requêtes telles que:

  SELECT * FROM messages WHERE non lus = 1 LIMIT 10; DROP TABLE messages-- 

Ce n'est pas possible.

Les choses ont un peu changé. Je poste une mise à jour dans une nouvelle question et je ne change pas celle-ci compte tenu de toute l'attention qu'elle a reçue.
Ma recommandation lors de la recherche de telles failles de sécurité est de les corriger, qu'elles soient exploitables ou non. Bien sûr, cela ne rend pas votre question hors de propos. Il peut être très instructif de voir pourquoi une faille de sécurité apparemment inutilisable peut être exploitée de toute façon. Si jamais vous parvenez à en trouver un qui est vraiment inutilisable, il y a de fortes chances que vous ayez passé plus de temps à analyser l'exploitabilité que vous n'en auriez simplement fait réparer.
Chaque fois que vous avez une ambiguïté où les * données * peuvent être confondues avec la * commande *, vous avez un risque potentiel de problèmes, même si elles sont difficiles à trouver.
Transformez-le en un entier et assurez-vous qu'il est dans des limites acceptables. Ou, si votre client a la capacité de se lier par type (type int), faites-le.
«UNION» n'est pas la seule préoccupation que j'aurais. Qu'en est-il de `DROP TABLE` ou` TRUNCATE TABLE`?
L'injection SQL ne consiste pas seulement à extraire des données restreintes, mais également à endommager des données.
Six réponses:
PiTheNumber
2014-12-23 19:12:00 UTC
view on stackexchange narkive permalink

Vous pouvez créer un UNION SELECT ici. Le seul problème est de faire correspondre les colonnes des messages, mais vous pouvez les deviner en ajoutant des colonnes jusqu'à ce qu'elles tiennent:

  SELECT * FROM messages WHERE non lus = 1 LIMIT 1 UNION SELECT mail, mot de passe, 1 , 1,1 FROM utilisateurs  

Continuez simplement à ajouter , 1 jusqu'à ce que vous obteniez le nombre de colonnes correct. Vous devez également faire correspondre le type de colonne. Essayez null au lieu de 1.

Si vous voyez des erreurs MySQL qui pourraient aider beaucoup ici. Sinon, vous avez beaucoup essayé.

Voir également Test d'injection SQL sur owasp.org pour plus de détails.

Serait-ce possible s'il y avait une instruction ORDER BY avant la limite?
Cela ne fonctionnera pas dans MySQL 5.7+ car vous ne pouvez pas utiliser `UNION` après` LIMIT` à moins que toute la requête avant `UNION` ne soit placée entre parenthèses.Quelque chose comme `(SELECT * FROM table LIMIT 1) UNION SELECT ....`.
Dillinur
2014-12-23 20:35:43 UTC
view on stackexchange narkive permalink

Soit il n'y a presque pas de contraintes, et vous pouvez le faire de la manière habituelle (UNION ou '; XXX ---')

Parfois ce n'est pas possible, et vous devrez vous rabattre sur une expression booléenne dans LIMIT. C'est une injection SQL aveugle, et cela vous permettra de vider la base de données entière un bit à la fois.

Vous pouvez mettre une expression intégrale et extraire quelques bits de plus à la fois, à condition que la requête génère une liste que vous verrez, ce qui semble le faire.
Schwern
2014-12-24 10:27:23 UTC
view on stackexchange narkive permalink

MySQL prend en charge plusieurs instructions et depuis au moins 4.1 il y a dix ans. Par exemple, vous pouvez activer ceci dans le module mysql de Perl en utilisant mysql_multi_statements .

Bien que la bibliothèque cliente ne puisse pas prendre en charge plusieurs instructions pour le moment, vous Il ne s’agit que d’une mise à niveau ou d’un changement de configuration loin d’une faille de sécurité.

Les bibliothèques clientes ont * délibérément supprimé * la prise en charge de plusieurs instructions pour des raisons de sécurité.
Citation @Mark? DBD :: mysql de Perl l'a désactivé par défaut, mais facilement disponible. PHP [mysqli] (http://php.net/manual/en/mysqli.multi-query.php) nécessite un appel spécial. [ADO] de .NET (http://www.codeproject.com/Articles/306722/Executing-multiple-SQL-statements-as-one-against-S) semble ne nécessiter aucun code spécial.
user45139
2014-12-23 17:41:58 UTC
view on stackexchange narkive permalink

La requête de votre ami ne serait pas d'une grande utilité aujourd'hui, mais ce sera peut-être plus tard, mais à mesure que les technologies évoluent et que le SGBD MySQL est en constante amélioration comme beaucoup d'autres technologies, votre ami doit nettoyer l'entrée dans le cas du L'instruction code> LIMIT serait modifiée pour qu'il soit possible d'utiliser UNION juste après. Votre ami peut également envisager le cas où l'architecture du SGBD MySQL serait modifiée de manière à ce qu'il soit possible d'exécuter plusieurs instructions SQL contrairement à ce qu'il est actuellement.

Ce que je veux dire, c'est que votre ami doit nettoyer l'entrée: c'est la meilleure pratique: vous ne voyez peut-être pas cela trop important aujourd'hui, mais à l'avenir, vous ne le saurez jamais, et rappelez-vous qu'il y a toujours des gens qui peuvent être plus expérimentés que votre ami.

Alors que certains clients mysql peuvent être contraints de n'autoriser qu'une seule instruction par invocation (cela empêche l'attaque décrite ci-dessus), je considérerais qu'il est mauvais de s'appuyer sur cela comme le seul mécanisme de protection - de même alors qu'actuellement, mysqld attend un entier littéral après LIMIT il est possible que cela autorise une fonction ou une sous-requête à l'avenir.
-1 un vrai exploit serait bien.
@Rook Il a dit que l'entrée de `LIMIT` n'est pas nettoyée, donc il peut exécuter cette commande sur l'interface du site Web depuis qu'il a réussi à exécuter quelque chose. Aussi, pourquoi demandez-vous un véritable exploit à 100%? Je ne sais même pas quel site Web est concerné par cela
Query stacking? Dans MySQL? Avez-vous déjà exploité SQL Injection sur MySQL ??? PiTheNumber a eu la bonne réponse.
@Rook la personne qui a posé la question sait déjà qu'elle peut utiliser `UNION SELECT quelque chose` (lire sa question). Si j'ai déjà fait des injections SQL? Comme vous le savez déjà, jamais (mais j'aime votre site Web)
Désolé mais, c'est une énorme bête noire à moi. Principalement parce que je souhaite vraiment que l'empilement de requêtes soit pris en charge par la majorité des bases de données SQL, mais dans le monde réel, il est très rare (MS-SQL, Access, SQLite). Je vois des articles parlant de l'empilement de requêtes comme de faux espoirs.
Damian Yerrick
2014-12-24 01:30:30 UTC
view on stackexchange narkive permalink

La définition d'une limite de 1 UNION SELECT ... permettra à l'attaquant d'extraire des informations de n'importe quelle autre table, tant que les colonnes ont (ou peuvent être CAST avoir) le même nombre et le même type que les colonnes du premier SELECT . Définir une limite en tant que valeur produite à partir d'un sous- SELECT permettra à l'attaquant de lire tout autre par exemple, le hachage du mot de passe d'un autre utilisateur peut être extrait 4 bits à la fois en effectuant à plusieurs reprises une sous-requête renvoyant un nombre entre 0 et 15 à différents décalages de sous-chaînes, puis en comptant les lignes dans chaque résultat.

Mais ces deux attaques peuvent être déjouées. De nombreux pilotes de base de données autorisent une LIMIT paramétrée. Si un pilote particulier interfère avec un paramétré LIMIT , vous pouvez nettoyer l'entrée en convertissant l'entrée en un entier avant de la remplacer par une chaîne dans la requête. Cela vous aidera également à vous assurer de ne pas renvoyer plus d'enregistrements que votre application peut gérer à partir d'une requête (comme LIMIT 12345678 ). En PHP, cela pourrait ressembler à ceci:

  <? php //...$ limit = intval ($ _ REQUEST ['numresults']); $ limit = min (max ($ limit, 10), 100); $ stmt = $ dbh->prepare ("SELECT ... FROM ... WHERE ... LIMIT $ limit ");  
Rick
2014-12-25 09:42:14 UTC
view on stackexchange narkive permalink

C'est le bon moment pour utiliser les instructions préparées par PDO et bindParam cette variable comme une entrée uniquement entière. Cela devrait annuler toute tentative de ce que vous essayez de faire en injectant du SQL.

J'envisagerais également de laisser l'utilisateur choisir parmi une liste prédéfinie de nombres dans une liste déroulante. À moins que la page de résultats ne soit configurée pour paginer, vous pouvez potentiellement avoir un beau gâchis entre vos mains en essayant de charger 100000 enregistrements sur une page.



Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...