Question

Arrière-plan

On m'a demandé d'analyser un fournisseur de données existant et je sais que le code suivant est défectueux; mais pour pouvoir dire à quel point c'est mauvais, je dois prouver qu'il est sujet à l'injection SQL.

Question

Qu'est-ce que " Clé " Ce paramètre peut interrompre la fonction PrepareString et me permettre d’exécuter une instruction DROP ?

Extrait de code

Public Shared Function GetRecord(ByVal Key As String) As Record
    Dim Sql As New StringBuilder()

    With Sql
        .Append("SELECT * FROM TableName")
        If String.IsNullOrEmpty(Agency) Then
            .Append(" ORDER BY DateAdded")
        Else
            .Append(" WHERE Key = '")
            .Append(PrepareString(Key))
            .Append("'")
        End If
    End With

    Return ExecuteQuery(Sql.ToString())
End Function

Public Shared Function PrepareString(ByVal Value As String) As String
    Return Value.Replace("''", "'") _
                .Replace("'", "''") _
                .Replace("`", "''") _
                .Replace("´", "''") _
                .Replace("--", "")
End Function
Était-ce utile?

La solution

En réponse à votre question directe: Ce code empêche-t-il l'injection SQL: Non

En voici la preuve: transmettez cette chaîne par la méthode PrepareString:

Dim input = "'" & Chr(8) & "; Drop Table TableName; - " & Chr(8) & "-"
Dim output = PrepareString(input)

Console.WriteLine(input)
Console.WriteLine(output)

J'ai modifié la méthode GetRecord que vous avez publiée pour renvoyer la chaîne SQL entièrement préparée plutôt que d'extraire l'enregistrement de la base de données:

Console.WriteLine(GetRecord(output))

Et ceci est la sortie

Input  = ; Drop Table TableName; --
Output = '; Drop Table TableName; --
Query  = SELECT * FROM TableName WHERE Key = ''; Drop Table TableName; --'

Ajouter une ligne de code supplémentaire:

My.Computer.Clipboard.SetText(input)

Et vous avez la chaîne dont vous avez besoin copiée directement dans votre presse-papiers à coller dans votre champ de saisie sur le site Web pour compléter votre injection SQL:

'; Drop Table TableName; - -

[Notant que les caractères de contrôle ont été omis de la publication de StackOverflow, vous devrez donc suivre l'exemple de code pour créer votre sortie]

Une fois que la méthode PrepareString est exécutée, le résultat obtenu est identique: le code ASCII Chr (8) est l’arrière-plan qui supprime le """ 'supplémentaire ". que vous ajoutez à la mienne qui ferme votre chaîne et que je suis libre d'ajouter ce que je veux à la fin. Votre PrepareString ne voit pas mon - parce que j'utilise réellement - - avec un caractère de retour arrière pour supprimer l'espace.

Le code SQL résultant que vous créez va ensuite exécuter mon instruction Drop Table sans entrave et ignorer rapidement le reste de votre requête.

L’intéressant est que vous pouvez utiliser des caractères non imprimables pour contourner toute vérification de caractère que vous pouvez inventer. Il est donc plus sûr d’utiliser des requêtes paramétrées (ce qui n’est pas ce que vous avez demandé, mais le meilleur chemin pour éviter cela).

Autres conseils

Pour répondre à votre question douteuse, non, cela ne fonctionnerait pas.

.Replace ("" "", "" "" empêcherait les requêtes légitimes avec "" '

.Replace ("& # 180;", "" "" empêcherait les requêtes légitimes avec "& # 180; '

.Remplacer ("-", "") empêcherait les requêtes légitimes contenant le signe "-"

.Remplacer ("" "", "" ") modifierait de manière incorrecte les requêtes légitimes contenant" ""

et ainsi de suite.

De plus, l'ensemble des caractères d'échappement peut varier d'un SGBDR à un autre. Requêtes paramétrées FTW.

Je pense que c’est impossible si vous ne remplacez que «par». J'ai entendu dire qu'il est possible de changer le caractère de citation d'échappement, ce qui pourrait éventuellement le casser, mais je n'en suis pas sûr. Je pense que vous êtes en sécurité cependant.

Je pense que c'est sûr (du moins sur SQL Server) et que la seule chose que vous devez réellement faire est de s = s.Replace ("quot", "", "") . Vous devez bien sûr utiliser des requêtes paramétrées, mais vous le savez déjà.

Cet article MSDN couvre la plupart des éléments dont vous avez besoin. attention (j’ai peur de tout dire en matière d’injection SQL).

Mais je ferai écho au sentiment des autres paramètres.

En ce qui concerne votre exemple, quelques pièges [Edit: les a mis à jour]:

  • ne contient pas la chaîne "1 OU 1 = 1" permettre à l'utilisateur de tout récupérer

  • ou pire "1; déposer table nom sometabl "

Selon l'article que vous souhaitez vérifier:

  

; - Délimiteur de requête.

     

'- Délimiteur de chaîne de données de caractère.

     

- - Délimiteur de commentaire.

     

/ * ... / - Délimiteurs de commentaires. Texte   entre / et * / n'est pas évalué par   le serveur.

     

xp_ - Utilisé au début du nom de   procédures stockées étendues de catalogue,   comme xp_cmdshell.

Vous essayez de placer des caractères de la liste noire pour implémenter votre propre version de SQL Escaping. Je suggère de consulter cette URL - L'échappement SQL n'est pas nécessairement le pire choix (c'est-à-dire corriger les applications existantes), mais il faut le faire correctement pour éviter les vulnérabilités.

Cette URL renvoie à une autre page pour s’échapper dans SQL Server où l’auteur donne des suggestions pour vous aider à éviter les vulnérabilités sans limiter les fonctionnalités.

Si cela peut aider, les articles suggèrent aussi des accolades d'échappement (je les appelle des crochets - mais []).

Si vous essayez d'utiliser votre code, une personne peut passer une clé (; sélectionnez * dans la table; et obtenez la liste de toutes les tables de votre choix.

Dans votre code, vous ne vérifiez pas le point-virgule qui vous permet de terminer une instruction t-sql et d'en commencer une autre.

J'irais avec une requête paramétrée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top