Découvrez comment la solution Parasoft Continuous Quality permet de contrôler et de gérer les environnements de test pour fournir des logiciels de haute qualité en toute confiance. Inscrivez-vous pour la démo >>

BLOG

Comment empêcher l'injection SQL

Comment empêcher l'injection SQL Temps de lecture : 10 minutes

Le SQL (Langage de requêtes structurées) est une des faiblesses logicielles et des vulnérabilités de sécurité bien connues, sinon l'une des plus connues. Malgré sa réputation, la prévention de l'injection SQL reste l'une des principales vulnérabilités, et les attaques continuent de croître.

Recherche d'injections SQL

Les vulnérabilités d'injection (dont les injections SQL sont une saveur) sont le problème de sécurité numéro un des applications Web selon le OWASP Top 10. Les injections SQL sont au numéro six sur le Top 25 CWE. D'autres exemples des mêmes types de vulnérabilités de sécurité sont:

  • Injection de commande (CWE-77)
  • Injection de commande du système d'exploitation (CWE-78)
  • Injection Hibernate (CWE-564)
  • Injection de langage d'expression (CWE-917)

Toutes ces vulnérabilités partagent un attribut commun. Ils sont exploités en utilisant des données extérieures au système, des entrées d'utilisateur ou de fichier, ou quoi que ce soit, dans des fonctions potentiellement dangereuses.

Obtenez le livre blanc gratuit: La valeur commerciale des logiciels sécurisés

Heureusement, les injections SQL sont détectables par des outils à la fois statiquement et dynamiquement. Cependant, vous ne pouvez jamais être sûr de les avoir tous attrapés. La prévention des injections SQL est également essentielle pour réduire la fréquence et l'impact de ces vulnérabilités. Un processus DevSecOps mature qui intègre la détection et la prévention des vulnérabilités est susceptible de détecter et d'empêcher ces types de vulnérabilités de pénétrer dans un produit commercialisé.

Qu'est-ce que SQL?

SQL est un langage spécifique à un domaine conçu pour la gestion de bases de données relationnelles. Les bases de données relationnelles présentent les données sous la forme d'un ensemble de tables en lignes et en colonnes. Chaque ligne a une clé qui fournit la relation avec les autres tables. Voici un exemple de table "utilisateur":

[table “1” non trouvée /]

SQL est le langage de choix pour la gestion, l'interrogation et la manipulation des données dans une base de données de relations. Il définit les tables et les relations lors de la création de la base de données. Pour la plupart des utilisations quotidiennes, les développeurs utilisent SQL pour «CRUD» - pour créer, lire, mettre à jour et supprimer des données.

Pourquoi SQL est-il exploitable?

Les langages de programmation généraux n'incluent pas la prise en charge de SQL. L'accès aux commandes de la base de données se fait via une API fournie par le fournisseur de la base de données. Dans de nombreux cas, les commandes SQL sont envoyées sous forme de chaînes que l'API interprète et applique à la base de données. Voici quelques requêtes SQL simples:

Une requête SQL typique prend la forme suivante:

Sélectionnez (quelque chose) de (quelque part) (condition facultative)

En utilisant les tableaux ci-dessus comme exemple pour récupérer l'e-mail à partir de la ligne où le nom de famille est «Smith», l'instruction SQL suivante est utilisée:

Sélectionnez l'email de l'utilisateur où lastname = 'Smith'

Le résultat serait le suivant:

Smith1234@mail.com John.smith@mail.net Smith1234@mail.com

Obtenir les commentaires des utilisateurs avec un formulaire Web (voir ci-dessous) est un cas d'utilisation courant dans les applications Web. Les données que les utilisateurs entrent dans le champ «Nom», par exemple, sont utilisées pour former des requêtes SQL basées sur les entrées reçues. Considérez le formulaire Web simple suivant:

Formulaire Web simple

Le logiciel traite le formulaire et attribue les valeurs aux variables quelque chose comme ceci:

String formName = request.getParameter (Nom);

La chaîne saisie comme "Nom" est utilisée pour assembler la requête à l'aide de cette entrée utilisateur:

String myQuery = "sélectionner le message de l'utilisateur où email = '" + formName + "';"

En utilisant cette requête construite:

Sélectionnez le message de l'utilisateur où email = 'Smith1234@mail.com';

La sortie de ceci (en utilisant le tableau ci-dessus comme exemple) est la suivante:

Bonjour comment vas-tu

Espérons qu'il est facile de voir comment tout cela peut mal tourner. Étant donné l'utilisation de l'entrée utilisateur directement dans la chaîne, quelqu'un qui comprend la syntaxe SQL peut facilement la manipuler pour générer la requête SQL. Prenons l'exemple suivant:

En utilisant le même formulaire ci-dessus, quelqu'un entre «Smith1234@mail.com» ou «1» = «1» dans le champ de courriel.

Le même code assemblera la chaîne de requête SQL suivante:

Sélectionnez le message de l'utilisateur où email = 'Smith1234@mail.com' ou '1' = '1';

L'ajout de quelque chose qui semble anodin tel que «ou 1 = 1» modifie la logique de la requête et risque de fuir des données en renvoyant toutes les lignes de la table appelée «utilisateur». Dans ce cas, vous affichez les messages de chaque utilisateur du tableau. Un problème de confidentialité grave et, dans certaines juridictions ou contextes, un problème juridique potentiel, comme le RGPD, la HIPAA ou la CCPA.

La requête ci-dessus se termine par la sortie inattendue suivante:

Bonjour mot de passe 1234 Comment allez-vous ne le dites à personne Wassup

Comment fonctionne une injection SQL

L'essentiel d'une injection SQL (et d'autres types de vulnérabilités d'injection) est l'utilisation de données non vérifiées provenant de l'extérieur de l'application, telles que le texte d'entrée de l'utilisateur, dans une chaîne de requête SQL. La description de CWE 89: «Neutralisation incorrecte des éléments spéciaux utilisés dans une commande SQL ('injection SQL')» définit cela plus précisément:

«Sans une suppression ou une citation suffisante de la syntaxe SQL dans les entrées contrôlables par l'utilisateur, la requête SQL générée peut amener ces entrées à être interprétées comme SQL au lieu de données utilisateur ordinaires. Cela peut être utilisé pour modifier la logique de requête afin de contourner les contrôles de sécurité ou pour insérer des instructions supplémentaires qui modifient la base de données principale, y compris éventuellement l'exécution de commandes système. »

La même entrée dans la base de données CWE (CWE 89) fournit un autre exemple simple de cette attaque. En supposant que l'application effectue une requête au nom de l'utilisateur «wiley» et que l'utilisateur construit l'entrée de telle manière qu'elle contienne des instructions SQL, par exemple:

Nom'; SUPPRIMER DES éléments; -

Si cette application n'effectue aucune vérification de validité sur cette entrée, elle construit une requête comme celle-ci:

SELECT * FROM items WHERE owner = 'wiley' AND itemname = 'nom'; SUPPRIMER DES éléments; - '

Si cette attaque réussit, elle supprime toutes les données des éléments de la table - causant des ravages dans la base de données. Toute commande SQL valide pourrait potentiellement être exécutée de cette façon. Ceci est un exemple d'attaque d'écriture / modification où l'intention est de corrompre la base de données ou d'insérer des informations indésirables. L'exemple précédent («ou 1 = 1») est une attaque de lecture où l'intention est une fuite de données.

De nombreuses implémentations de serveurs de base de données acceptent le point-virgule comme séparateur de commandes, ce qui permet à de telles injections SQL d'être si dangereuses. Le «-» de fin signale que le reste du texte est un commentaire, forçant l'interpréteur SQL à ignorer le guillemet de fin, ce qui provoquerait autrement une erreur de syntaxe. Il existe plusieurs façons de tromper la chaîne de requête assemblée. Parfois, d'une manière jamais imaginée par les développeurs.

Atténuations pour se protéger contre les injections SQL

Il existe plusieurs mesures d'atténuation que les développeurs devraient implémenter. En premier lieu, la position de sécurité doit prendre en compte toutes les données provenant de l'extérieur de l'application qui ne sont pas approuvées. Voici des stratégies d'atténuation typiques:

  • Utilisez des instructions préparées avec des requêtes paramétrées.
  • Utilisez des procédures stockées.
  • Validation d'entrée de la liste blanche.
  • Échappez à toutes les entrées fournies.

Ceux-ci sont décrits plus en détail dans l'OWASP aide-mémoire pour les injections SQL.

Test des injections SQL

Une approche typique de la sécurité consiste à effectuer divers types de tests de sécurité dans le cadre des opérations régulières d'assurance qualité lorsque le logiciel intégré est en cours d'exécution. Malheureusement, les tests fonctionnels n'essaient pas d'insérer des exploits dans les champs de saisie utilisateur car la plupart des testeurs ne pensent pas comme de mauvais acteurs.

Outre le fait qu'ils n'ont traditionnellement ni le temps ni la direction pour le faire. Il est également difficile de tester manuellement les vulnérabilités de type injection car cela nécessite d'essayer de nombreuses combinaisons d'entrées différentes. C'est là qu'intervient le test de fuzzing ou de fuzz. Il crée des données aléatoires, inattendues et invalides en tant qu'entrées de l'application testée. Les tests Fuzz font partie des tests d'intrusion car l'objectif est d'exposer les vulnérabilités de sécurité via les interfaces exposées.

Tests de pénétration

Les tests de pénétration (et par extension, les tests fuzz) sont bénéfiques car ils peuvent découvrir des problèmes de sécurité qui se sont glissés dans le processus et révéler des problèmes de sécurité importants. Cependant, comme tous les tests dynamiques, cela dépend de la quantité de test, de code et de couverture d'API pour tester complètement toutes les permutations et combinaisons possibles. Les tests de pénétration dépendent de la rigueur des tests fonctionnels, généralement effectués au niveau de l'interface utilisateur. Il est donc important de soutenir vos efforts de test d'intrusion avec des tests API et SAST pour vous assurer que vous êtes minutieux.

Test d'API

Les tests d'API aident à déplacer vers la gauche les tests fonctionnels et de sécurité en supprimant la dépendance aux tests d'interface utilisateur fragiles et chronophages. La couche API est l'endroit où une grande partie des fonctionnalités de l'application réside et les tests sont plus résilients au changement à ce niveau et plus faciles à automatiser et à maintenir.

Test de pénétration au niveau de l'API

Des tests de pénétration au niveau de l'API pour exposer des injections SQL sont possibles avec des outils tels que Parasoft SOAtest où des tests fuzz automatisés sont créés à partir de tests fonctionnels existants, exercent la logique métier de l'application. Parasoft SOAtest s'intègre à Suite Burp qui est un outil de test de pénétration bien connu.

Lors de l'exécution de scénarios de test fonctionnel avec Parasoft SOAtest, les appels d'API définis dans le test sont capturés avec le trafic de demande et de réponse. L'outil d'analyse Burp Suite sur chaque test transmettra les données de trafic à une instance en cours d'exécution distincte de l'application Burp Suite, qui effectuera des tests de pénétration sur l'API en fonction des paramètres d'API qu'elle observe dans les données de trafic, en utilisant sa propre heuristique.

L'outil d'analyse Burp Suite prendra alors toutes les erreurs trouvées par Burp Suite et les signalera comme des erreurs dans SOAtest, associées au test qui a accédé à l'API. Les résultats de Parasoft SOAtest sont rapportés dans le tableau de bord de reporting et d'analyse de Parasoft. Pour des fonctionnalités de reporting supplémentaires.

Pour en savoir plus sur cette intégration, consultez notre post précédent sur les tests de pénétration. Pour plus d'informations de Portswigger sur l'utilisation de Burp pour les injections SQL, consultez leur message. Vous trouverez ci-dessous une représentation du fonctionnement de cette intégration avec Burp:

Empêcher les injections SQL à l'aide de Burp et Parasoft DTP

L'intégration de ce type de test de pénétration dans votre processus CI / CD est une partie importante de la défense contre les injections SQL et d'autres types de vulnérabilités.

La pénétration et le fuzzing sont certainement un processus important et critique dans DevSecOps. Cependant, cela pose des questions.

  • Que se passe-t-il lorsque les tests détectent des vulnérabilités de sécurité?
  • Que se passe-t-il lorsqu'une équipe logicielle découvre qu'une grande partie de la gestion des entrées utilisateur n'est pas sécurisée?
  • Il doit certainement être réparé, mais à quel prix?

La découverte de problèmes de sécurité graves à ce stade avancé du développement entraîne des coûts et des retards importants. La prévention et la détection sont essentielles pour déplacer les opérations de sécurité plus vers la gauche, là où elles sont moins chères et plus faciles à réparer.

Décaler la détection et l'élimination des injections SQL vers la gauche

Adopter une approche DevSecOps pour le développement de logiciels signifie intégrer la sécurité dans tous les aspects du pipeline DevOps. Tout comme les équipes poussent des processus de qualité comme l'analyse de code et tests unitaires le plus tôt possible dans le SDLC, il en va de même pour la sécurité.

Les injections SQL pourraient appartenir au passé si les équipes adoptaient cette approche plus largement. La montée des attaques signifie que cela ne se produit pas encore. Quoi qu'il en soit, décrivons une approche pour empêcher les injections SQL le plus tôt possible.

Trouver et corriger des injections SQL potentielles (et d'autres vulnérabilités d'injection) est rentable par rapport à l'application de correctifs (et aux excuses pour!) Une application publiée. Un seul incident significatif peut entreprises de coûts 200,000 XNUMX $ ou plus. De nombreux incidents se produisent dans les petites entreprises. Une seule attaque peut entraîner de graves tensions financières, sans parler des problèmes réglementaires potentiels concernant les divulgations de violation et la protection des PII.

L'approche de détection et de prévention décrite ci-dessous est basée sur le passage à gauche de l'atténuation des injections SQL aux premiers stades de développement et sur le renforcement de cela avec la détection via l'analyse de code statique.

Comment détecter les injections SQL

La détection des injections SQL repose sur l'analyse statique pour trouver ces types de vulnérabilités dans le code source. La détection se produit sur le bureau du développeur et dans le système de construction. Il peut inclure du code existant, hérité et tiers.

La détection continue des problèmes de sécurité garantit la détection de tous les problèmes qui:

  • Les développeurs ont raté l'IDE.
  • Existe dans un code antérieur à votre nouvelle approche de détection et de prévention.

L'approche recommandée est un modèle de confiance mais de vérification. L'analyse de sécurité se produit au niveau de l'EDI où les développeurs prennent des décisions en temps réel en fonction des rapports qu'ils reçoivent. Ensuite, vérifiez au niveau de la construction. Idéalement, l'objectif au niveau de la construction n'est pas de trouver des vulnérabilités. C'est pour vérifier que le système est propre.

À titre d'exemple, considérons l'application de démonstration de Parasoft, Parabanque. Il y a une injection SQL potentielle dans le fichier StockDataInserter.java dans com.parasoft.parabank.dao.jdbc.internal:

… Chaîne finale sql = sb.toString (); lignes = (nextId - lastId) / JdbcSequenceDao.OFFSET; totalRows + = lignes; getJdbcTemplate (). update (sql); …

Le rapport généré au moment de la construction par Jtest Parasoft est le suivant:

Recherche d'injections SQL: rapport Parasoft Jtest

Dans le détail se trouve l'avertissement suivant:

Appel à une méthode dangereuse StockDataInserter.java (96): getJdbcTemplate (). Update (sql); *** Données corrompues: SQL

Avec un suivi vers un point précédent où se trouvent les données corrompues à la source (décocher, entrée non validée de l'extérieur de l'application):

Tainting point StockDataInserter.java (47): retourne getJdbcTemplate (). Query (SQL, nouveau ResultSetExtractor  > () {*** Données corrompues: getJdbcTemplate (). Query (SQL, nouveau ResultSetExtractor

Dans la bataille en cours contre les injections SQL, les développeurs doivent prendre ces avertissements au sérieux. Toute utilisation de données non validées dans les requêtes SQL est un risque sérieux. Même si un avertissement spécifique peut ne pas être un problème dans la forme actuelle, il est possible qu'une refactorisation ultérieure puisse exposer ces vulnérabilités. Vérifiez toutes les données utilisées dans les chaînes de requête!

En fait, les développeurs doivent valider toutes les données provenant de l'extérieur d'une application pour s'assurer qu'elles sont conformes au format et au contenu attendus. Le passage à une philosophie de «toujours valider» et à un processus reposant sur un codage sécurisé plutôt que sur des tests de sécurité augmente considérablement la sécurité de vos applications. Commencez par durcir le code pour empêcher les injections SQL de se produire en premier lieu.

Quand et comment empêcher l'injection SQL

Le moment et le lieu idéaux pour empêcher les injections SQL sont lorsque les développeurs écrivent du code dans leur IDE. Les équipes qui adoptent des normes de codage sécurisé telles que SEI CERT C pour C et C ++ et OWASP Top 10 pour Java et .NET ou CWE Top 25, ont toutes des directives qui avertissent des entrées non validées dans les requêtes SQL.

L'exécution d'une analyse statique sur du code nouvellement créé est rapide et simple et s'intègre facilement dans le processus CI / CD. Il est recommandé d'enquêter sur les avertissements de sécurité et les pratiques de codage non sécurisées à ce stade pour empêcher ce code de pénétrer dans la construction.

Utiliser l'analyse de code statique pour empêcher les injections SQL

Un élément tout aussi important de la détection des mauvaises pratiques de codage est l'utilité des rapports. Il est important de pouvoir comprendre la cause première des violations de l'analyse statique afin de les corriger rapidement et efficacement. C'est là que les outils commerciaux tels que Parasoft Test C / C ++, pointTESTet Jtest éclat.

Les outils de test automatisés de Parasoft donnent des traces complètes des avertissements, les illustrent dans l'EDI et collectent en permanence des informations de construction et d'autres informations. Ces données collectées ainsi que les résultats des tests et les mesures fournissent une vue complète de la conformité avec la norme de codage de l'équipe. Il montre également l'état général de la qualité et de la sécurité.

Les rapports incluent les modèles de risque qui font partie des informations fournies par OWASP, CERT et CWE. De cette façon, les développeurs comprennent mieux l'impact des vulnérabilités potentielles signalées par l'outil et lesquelles de ces vulnérabilités à prioriser. Toutes les données générées au niveau IDE sont en corrélation avec les activités en aval décrites ci-dessus.

Résumé

La tristement célèbre vulnérabilité d'injection SQL continue d'affliger les applications Web. Malgré la connaissance de la façon dont cela fonctionne et peut être exploité, il reste répandu. Voir le Salle de la honte IoT pour des exemples récents.

Nous proposons une approche de prévention et de détection pour compléter les tests de sécurité actifs. Cette approche empêche les injections SQL le plus tôt possible dans le SDLC - avant d'écrire dans le code. Empêcher les injections SQL au niveau de l'EDI et les détecter dans le pipeline CI / CD est essentiel pour les acheminer hors de votre logiciel. Enfin, recherchez et corrigez ces bogues lors des tests à l'aide de techniques de test d'intrusion.

La bataille contre les injections SQL (ainsi que d'autres exploits de données corrompues) continue. Les équipes intelligentes peuvent inverser la tendance avec le bon processus, les bons outils et l'automatisation dans leurs flux de travail existants.

Regardez Parasoft en action: demandez un essai

Écrit par

Arthur Hicken

Arthur est impliqué dans la sécurité logicielle et l'automatisation des tests chez Parasoft depuis plus de 25 ans, aidant à la recherche de nouvelles méthodes et techniques (dont 5 brevets) tout en aidant les clients à améliorer leurs pratiques logicielles.

Recevez les dernières nouvelles et ressources sur les tests de logiciels dans votre boîte de réception.