Optez pour une voie plus rapide et plus intelligente vers l'automatisation des tests C/C++ pilotée par l'IA. Découvrez comment >>
Comment empêcher l'injection SQL
L'injection SQL peut affecter la robustesse et les couches de sécurité de votre logiciel si elle n'est pas détectée et arrêtée tôt. Lisez la suite pour savoir comment l'injection SQL peut affecter votre logiciel et découvrez notre approche de la gestion de l'injection SQL.
L'injection SQL peut affecter la robustesse et les couches de sécurité de votre logiciel si elle n'est pas détectée et arrêtée tôt. Lisez la suite pour savoir comment l'injection SQL peut affecter votre logiciel et découvrez notre approche de la gestion de l'injection SQL.
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.
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:
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.
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é.
SQL est un langage spécifique conçu pour la gestion des bases de données relationnelles. Ces bases de données présentent les données sous forme d'un ensemble de tables en lignes et en colonnes. Chaque ligne possède une clé qui établit la relation avec les autres tables. Voici un exemple de table « utilisateur » :
[tableau "1" introuvable /]SQL est le langage de référence pour la gestion, l'interrogation et la manipulation des données dans une base de données relationnelle. Il définit les tables et les relations lors de la création de la base de données. Au quotidien, les développeurs utilisent SQL pour la création, la lecture, la mise à jour et la suppression de données.
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:
Select (something) from (somewhere) (optional condition)
En utilisant les tables ci-dessus comme exemple pour récupérer l'e-mail de la ligne où le nom de famille est « Smith », l'instruction SQL suivante est utilisée :
Select email from user where lastname = ‘Smith’
Le résultat serait le suivant:
Smith1234@mail.com
John.smith@mail.net
Smith1234@mail.com
La collecte des données des utilisateurs via un formulaire web (voir ci-dessous) est un cas d'utilisation courant dans les applications web. Les données saisies par les utilisateurs dans le champ « Nom », par exemple, sont utilisées pour générer des requêtes SQL basées sur les données reçues. Prenons le formulaire web simple suivant :

Le logiciel traite le formulaire et attribue les valeurs aux variables quelque chose comme ceci:
String formName = request.getParameter(Name);
La chaîne saisie comme « Nom » est utilisée pour assembler la requête à l'aide de cette entrée utilisateur :
String myQuery = "select message from user where email = ‘" + formName +"’;"
En utilisant cette requête construite:
Select message from user where email= ‘Smith1234@mail.com’;
La sortie de ceci (en utilisant le tableau ci-dessus comme exemple) est la suivante:
Hello
How are you
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 e-mail.
Le même code assemblera la chaîne de requête SQL suivante:
Select message from user where email = ‘Smith1234@mail.com’ or ‘1’=’1’;
L'ajout d'un élément apparemment anodin, comme « ou 1=1 », modifie la logique de la requête et risque de provoquer une fuite de données en renvoyant toutes les lignes de la table appelée « utilisateur ». Dans ce cas, les messages de chaque utilisateur de la table s'affichent. Il s'agit d'un grave problème de confidentialité et, dans certaines juridictions ou contextes, d'un problème juridique potentiel, notamment en vertu du RGPD, de la loi HIPAA ou du CCPA.
La requête ci-dessus se termine par la sortie inattendue suivante:
Hello
Password 1234
How are you
Don’t tell anyone
Wassup
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 CWE89: « Neutralisation incorrecte des éléments spéciaux utilisés dans une commande SQL (« Injection SQL ») » définit cela plus précisément :
Sans suppression ou citation suffisante de la syntaxe SQL dans les entrées contrôlables par l'utilisateur, la requête SQL générée peut entraîner l'interprétation de ces entrées comme du code SQL plutôt que comme des données utilisateur ordinaires. Cela peut permettre de modifier la logique de la requête afin de contourner les contrôles de sécurité ou d'insérer des instructions supplémentaires modifiant la base de données principale, y compris 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. Supposons que l'application effectue une requête pour le compte de l'utilisateur « wiley » et que celui-ci construise une entrée contenant des instructions SQL, par exemple :
name'; DELETE FROM items; --
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 = 'name';
DELETE FROM items;
--'
Si cette attaque réussit, elle supprime toutes les données des éléments de la table, perturbant ainsi la base de données. Toute commande SQL valide pourrait être exécutée de cette manière. Il s'agit d'une attaque en écriture/modification visant à corrompre la base de données ou à insérer des informations indésirables. L'exemple précédent (« ou 1=1 ») est une attaque en lecture visant à la fuite de données.
De nombreuses implémentations de serveurs de bases de données acceptent le point-virgule comme séparateur de commandes, ce qui rend ces injections SQL dangereuses. Le « – » final signale que le reste du texte est un commentaire, obligeant l'interpréteur SQL à ignorer le guillemet final, ce qui entraînerait une erreur de syntaxe. Il existe de nombreuses façons de tromper la chaîne de requête assemblée, parfois de manières inimaginables pour les développeurs.
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:
Ceux-ci sont décrits plus en détail dans l'OWASP aide-mémoire pour les 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.
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.
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.
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:

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.
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.
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.
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:
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:
…
final String sql = sb.toString();
rows = (nextId - lastId) / JdbcSequenceDao.OFFSET;
totalRows += rows;
getJdbcTemplate().update(sql);
…
Le rapport généré au moment de la construction par Jtest Parasoft est le suivant:

Dans le détail se trouve l'avertissement suivant:
Call to a dangerous method
StockDataInserter.java (96): getJdbcTemplate().update(sql); *** Tainted data: 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): return getJdbcTemplate().query(SQL, new
ResultSetExtractor<List<String>>() { *** Tainted data:
getJdbcTemplate().query(SQL, new ResultSetExtractor<List<Str...return
symbols; } })
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 devraient valider toutes les données externes à l'application afin de garantir leur conformité au format et au contenu attendus. Adopter une philosophie de « validation systématique » et un processus reposant sur un codage sécurisé plutôt que sur des tests de sécurité renforce considérablement la sécurité de votre application. Commencez par renforcer le code pour prévenir les injections 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.

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.
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.