Comment limiter l'impact et réduire le risque d'injection SQL pour les sites Web existants?

Notre site Web est basé à 100% sur des API (avec un client SPA). Récemment, un pirate informatique a réussi à obtenir le mot de passe de notre administrateur (haché avec SHA-256) via l'injection SQL (et le crack de pwd) comme ceci:

https://example.com/api/products?userId=3645&type=sqlinject here

C'est juste un exemple, mais c'est mortel pour nous. Heureusement, c’était un bon pirate informatique et il vient de nous envoyer un courrier électronique à propos du piratage. Heureusement pour un site web sous attaques constantes tout au long de ses 5 années d'existence.

Oui, nous savons que nous devons vérifier les entrées des utilisateurs partout et bien formater/échapper/préparer les instructions avant d’envoyer des données à MySQL. Nous savons et nous réglons le problème. Mais nous n'avons pas assez de développeurs/testeurs pour le rendre sûr à 100%.

Supposons maintenant que nous avons 0,1% de chances d’être injectés SQL d’une manière ou d’une autre. Comment pouvons-nous rendre la tâche du pirate informatique plus difficile et limiter les dommages autant que possible?

Ce que nous faisons jusqu’à présent comme solutions rapides/mesures supplémentaires:

  1. At the output "gate" shared by all APIs, we no longer send the raw PDOException and message like before. But we still have to tell the client that exception occurred:

    {type: exception, code: err643, message: 'contact support for err643'}
    

    I am aware that if hacker see exception, he will keep trying...

  2. The user PHP uses to connect to MySQL can only CRUD to tables. Is that safe enough?

  3. Rename all tables (we use open source so hacker can guess the tables name).

Que devrions-nous faire d'autre?

Update : since there are many comments, I would like to give some side info

  1. First of all, this is LEGACY app, developed by some student-like folks, not enterprise grade. The dev team is nowhere to be found, now only 1-2 hybrid dev-test guy handling hundreds of Data Access class.
  2. The password is hash with SHA-256, yes it sucks. And we are changing it to recommended PHP way.
  3. SQL injection is 17 years old. Why is it still around?
  4. Are prepared statements 100% safe against SQL injection?
34
Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacé pour discuter .
ajouté l'auteur Rory Alsop, source

11 Réponses

Ne passez pas trop de temps à trouver des solutions de contournement ou des solutions partielles. Chaque minute que vous passez à essayer de mettre en œuvre ce que vous suggérez ici est une minute que vous auriez pu mettre à mettre en œuvre des déclarations préparées. C’est la seule vraie solution.

Si vous avez une vulnérabilité SQLi, l'attaquant l'emportera probablement, peu importe ce que vous ferez pour essayer de la ralentir. Sachez donc que si vous apportez des améliorations, vous finissez par perdre, à moins que vous ne répariez la cause du problème.

En ce qui concerne ce que vous avez essayé jusqu’à présent: Cacher les messages d’erreur est un bon début. Je vous recommande d'appliquer des autorisations encore plus strictes (voir ci-dessous). Il est discutable de savoir si le changement de nom de table aide , mais cela ne fera probablement pas de mal.

Ok, alors qu'en est-il de ces autorisations? Limitez ce que l'utilisateur de base de données peut faire le plus possible, jusqu'au niveau de la table ou même des colonnes. Vous pouvez même créer plusieurs utilisateurs de base de données pour verrouiller encore plus les choses. Par exemple, utilisez uniquement un utilisateur de base de données autorisé à écrire lorsque vous écrivez réellement. Connectez-vous uniquement avec un utilisateur ayant le droit de lire la colonne de mot de passe lorsque vous devez réellement lire la colonne de mot de passe. De cette façon, si vous avez une vulnérabilité d'injection dans une autre requête, vous ne pouvez pas tirer parti des fuites de mots de passe.

Une autre option consiste à utiliser un pare-feu d'application Web (WAF), tel que mod_security pour Apache. Vous pouvez le configurer pour bloquer les demandes qui semblent suspectes. Cependant, aucun WAF n'est parfait. Et cela prend du temps et de l'énergie pour le configurer. Vous ferez probablement mieux d'utiliser ce temps pour implémenter les instructions préparées.

Encore une fois, ne laissez rien de cela vous attirer dans un faux sentiment de sécurité. Il n'y a pas de substitution pour résoudre la cause du problème.

80
ajouté
En général, je suis d’accord avec cela et il ya beaucoup de bonnes choses ici. Je ne suis pas vraiment d'accord pour dire que consacrer du temps à une solution soustrait du temps à une autre. Un bon WAF peut être configuré par une personne qui n’a pas une connaissance spécifique de la base de code de l’application. Il en va de même pour les modifications de la base de données, qui peuvent être effectuées par un administrateur de base de données. Le fait est que les compétences des personnes varient considérablement et que chaque personne est adaptée à des tâches différentes. Si vous pouvez bien exploiter les compétences des personnes, vous pouvez mieux travailler en équipe.
ajouté l'auteur Steve Sether, source
Je ne peux pas souscrire à l’avis général de ne se connecter qu’à un utilisateur particulier lorsqu’une opération particulière est nécessaire. Cela devient impraticable trop rapidement. Si vous le souhaitez vraiment, une séparation modeste serait acceptable, comme l’écriture séparée dans les tables utilisateur de tout le reste. Mais vous devez avoir toutes les requêtes pour une requête unique dans une transaction unique. Essayer de faire en sorte que ce soit le cas pour tous les chemins de code possibles serait un fardeau énorme si vous avez beaucoup d'utilisateurs de bases de données différents.
ajouté l'auteur jpmc26, source
J'envisagerais également d'investir l'argent que vous êtes censé utiliser pour "... limiter l'impact et réduire le risque ..." afin de payer un pentest professionnel (évidemment, alors que vos développeurs sont raisonnablement sûrs ils ont fait leur travail)
ajouté l'auteur chandi.ma, source
@RobinK Je suis très sceptique sur le fait que l'utilisation d'instructions préparées est nettement plus "stressante" que la concaténation manuelle de chaînes partout ... et, franchement, peu importe que ce soit le minimum de responsabilité à assumer lors de la programmation avec SQL? Je ne suis pas sûr que d'abandonner et d'ajouter une bibliothèque tierce va faire beaucoup plus que compliquer les choses.
ajouté l'auteur underscore_d, source
"Il est discutable de changer les noms de table, mais cela ne fera probablement pas de mal." - Cela peut faire mal à vos propres développeurs, les surprenant chaque fois qu'ils doivent accéder à une table non nommée la façon dont ils s'attendent.
ajouté l'auteur marcelm, source
J'utilise AOP avec des instructions préparées depuis un certain temps déjà, mais cela devient stressant après un certain temps. J'ai récemment commencé à utiliser Medoo . C'est un wrapper simple, mais puissant pour PHP, utilisable pour MySQL, MSSQL, SQLite et plus. Vous devriez y jeter un coup d'œil, cela vous simplifie vraiment la vie puisque vous n'avez plus besoin de penser à des déclarations préparées.
ajouté l'auteur remyo, source

Le seul moyen correct consiste à utiliser des instructions préparées.

  1. Si vous dissimulez les messages d'erreur, c'est un peu plus difficile, mais cela n'arrêtera pas les attaquants.
  2. Vous pouvez restreindre les droits, mais tous les droits accordés à l'utilisateur pourraient être obtenus par l'attaquant. Il est également possible d'exécuter des commandes shell à partir d'une injection SQL dans certains cas.
  3. Renommer les tables ne vous aidera pas. L'outil sqlmap va forcer brutalement les noms de table char par char. Cela n'a pas besoin de beaucoup de temps.

Vous pouvez également limiter le nombre d'appels afin de compliquer la tâche des attaquants ou émettre des alertes sur les appels suspects et arrêter ce manuel, mais le seul moyen correct de résoudre ce problème consiste à utiliser des instructions préparées. Il suffit de passer par votre code source et de regarder les instructions SQL avec un contenu dynamique et de les remplacer.

65
ajouté
" La seule manière correcte " Je suis fortement en désaccord avec "uniquement la manière correcte". Il y a plusieurs façons de corriger les manières. (Ils finissent par faire quelque chose d'équivalent.)
ajouté l'auteur curiousguy, source
@phresnel Quel type de base de données devrait être utilisé à la place?
ajouté l'auteur curiousguy, source
Faites attention avec les restrictions, car cela peut rapidement affecter les utilisateurs légitimes, sachant que le problème concerne une requête GET , et pourrait donc être injecté dans une balise pour que tous les utilisateurs qui voient la page avec cette balise déclenchent une demande et risquent de se retrouver bloqués par le site Web.
ajouté l'auteur Xenos, source
@curiousguy, ... vous ne recevez pas d'injection SQL dans une base de données Datalog . Là encore, cela a tendance à être dû aux implémentations récemment populaires ( DataScript , Datomic ) prennent les infrastructures de données LISPy en tant que spécifications de requête - pas de chaînes - il n'y a donc aucune tentation d'essayer de construire ces requêtes via la concaténation de chaînes.
ajouté l'auteur Charles Duffy, source
Cela pourrait également être une bonne idée de faire de la révision de code une partie de votre processus, par exemple. examinez tout ce qui est fusionné avec la branche principale ou de production. Ayez des directives de codage qui définissent comment les choses doivent être codées et ce qui est interdit (par exemple, il ne devrait pas être autorisé à concaténer des chaînes de caractères dans une requête SQL). Cela empêchera l'introduction de nouvelles vulnérabilités après avoir corrigé les vulnérabilités actuelles.
ajouté l'auteur LanceW, source
Ok, il y a peut-être d'autres options, mais si le temps de programmation du PO est déjà trop court, les autres moyens seront simplement plus lents. Les déclarations préparées sont probablement le moyen le plus pratique de fermer le trou.
ajouté l'auteur erdem, source
@curiousguy: Cela dépend de l'ensemble de la plate-forme et de ses exigences. Pour les exigences d'authentification de base et quelques dizaines de milliers d'utilisateurs, une carte/dictionnaire/tableau associatif chargé dans la mémoire d'un démon/service et stocké dans un fichier CSV, xml ou JSON peut constituer un bon choix. Une implémentation de ceci serait simple, ou utiliserait CouchDB, par exemple. Possibilités illimitées: il s’agit en fait d’une structure de données et d’un choix d’algorithmes, même si je réalise que même les «Bachelors»/«Masters» en Allemagne semblent avoir oublié les structures de données et les algorithmes. Pour les débutants: bit.ly/2lEy9GL
ajouté l'auteur Kyle, source
Je trouve "la seule manière correcte" un peu grandiose, ou au mieux ambiguë. Peut-être que l'utilisation d'une base de données SQL était incorrecte depuis le début?
ajouté l'auteur Kyle, source

Nous savons, mais nous n'avons pas assez de développeurs/testeurs pour le rendre à 100%.   sûr.

This is the real problem. Until you hire more people or reassign priorities, you're not safe. Stopping 99.9% of attackers means that your data has been compromised. Band-aid solutions are a bad thing, and they do not work. Don't waste time refactoring your SQL access pattern while you could be fixing actual problems.

En ce qui concerne la solution de code, utiliser des instructions préparées, comme beaucoup de personnes le suggèrent ici, est le moyen le plus simple d’utiliser SQL en toute sécurité.

C'est beaucoup plus facile que d'essayer d'utiliser PHP pour nettoyer les arguments vous-même, et coûte beaucoup moins de temps. Il suffit de grep toute votre base de code pour tout ce qui concerne SQL et de le réparer.

25
ajouté
@xDaizu et Jacco: merci de votre intérêt. nous avons comme des milliers de classes d'accès aux données héritées mais juste un ou deux développeurs pour corriger les problèmes, nous ferons des "déclarations préparées" mais nous ne sommes tout simplement pas sûrs à 100%
ajouté l'auteur jl., source
Il est généralement difficile d’embaucher beaucoup de personnes en retard, mais comme @wedstrom l’a dit, le simple fait de traduire en déclarations préparées devrait être quelque chose que les personnes qui répondent à une offre d’emploi de PHP peuvent se passer sans trop d’introduction. Les introductions appropriées pourraient être après cela. Par exemple, refactorisez le code jusqu'à ce que vous ayez ces milliers de classes d'accès aux données héritées avec une super-classe commune contenant tout le travail de base de SQL.
ajouté l'auteur Blrfl, source
Je ne pense pas que l'embauche de plus de personnes aiderait solution à court terme . Et les problèmes de sécurité nécessitent des solutions immédiates. Vos autres suggestions sont sur place.
ajouté l'auteur Ray, source
@xDaizu Bien que je soutienne normalement l'idée qu'il est impossible d'amener plus de personnes dans un projet en retard à l'accélérer, il est relativement facile de trouver des personnes capables de traduire SQL en instructions préparées, car il s'agit d'une compétence assez fondamentale et universelle pour: la plus grande partie.
ajouté l'auteur user108131, source

Purger tout le code SQL de votre code pour toujours

La meilleure solution à ce problème consiste à supprimer de votre code tout le code SQL sous forme de chaînes littérales et à ne plus l'introduire à nouveau. Utilisez plutôt le logiciel ORM comme Hibernate ou Entity Framework. De toute façon, ce logiciel est beaucoup plus agréable à utiliser que le SQL brut, et il paramètre automatiquement votre SQL quand il va finalement dans la base de données. Si c'est possible pour vous, ayez cette politique.

Si vous n'avez pas le temps d'apprendre et d'implémenter ces paquetages, ou si vous ne pouvez pas les utiliser pour une autre raison, la réponse de trietend est la deuxième meilleure chose, utilisez instructions préparées . Cela vous permettra d'être à l'abri de l'injection SQL. Autrement dit, jusqu'à ce que vous exerciez une pression sur vos développeurs pour qu'ils apportent des solutions rapides, ils risquent alors de ne plus pouvoir paramétrer une seule variable, vous laissant ainsi à votre point de départ.

9
ajouté
@AndrolGenhald Est-ce l'argument le plus fort pour ne pas bouger? Peut-être pas, mais l'OP a déjà SQL. Passer à un ORM a peu de chances d’être une solution de remplacement si l’on passe plus ou moins aux déclarations préparées. Dans mon estimation (en grande partie uniforme), il est beaucoup plus probable que le PO introduise des modifications dans les plans d'exécution lors du passage à un ORM plutôt que lors d'une refactorisation pour utiliser des instructions de préparation.
ajouté l'auteur nikky, source
@ AndrolGenhald Mon expérience avec les ORM de poids lourd est qu'il est problématique d'essayer de les utiliser avec une base de données qui n'a pas été conçue pour fonctionner avec eux. Il est vraiment difficile d’en implémenter un sans un niveau ou un refactoring du code, des structures de base de données et/ou des requêtes. Le refactoring pour utiliser des instructions préparées peut certainement être effectué sans modifier la structure de ces opérations, mais le niveau d’effort varie.
ajouté l'auteur nikky, source
@Nacht Voici un meilleur exemple de la façon dont un ORM n'est pas une solution miracle pour une injection SQL: il explique comment cela peut se produire: cwe.mitre.org/data/definitions/564.html
ajouté l'auteur nikky, source
@AndrolGenhald Le refactoring en instructions préparées ne nécessite pas de refactoring le code SQL. Cela peut souvent améliorer les performances car les instructions ne sont pas recompilées sur la base de données à chaque exécution. Ce qui devient délicat, c’est lorsque la logique est complexe pour essayer de générer dynamiquement différentes instructions (par exemple, ajouter différentes clauses where) en fonction de différentes conditions. Ibatis a une solution appropriée pour cela en utilisant des modèles et génère une instruction préparée pour chaque requête distincte exécutée.
ajouté l'auteur nikky, source
@Nacht La plupart des ORM ont leur propre langage de requête, par exemple. HQL. Voici un exemple CVE pour une attaque par injection HQL. "Les attaques par injection HQL (Hibernate Query Language) et obtenir des informations sensibles via le paramètre entityName. ". Si tout ce que vous faites est de changer SQLi en HQLi, je ne suis pas sûr que cela résolve vraiment quelque chose.
ajouté l'auteur nikky, source
@MatthieuM. ne pas savoir utiliser une technologie n'est pas une excuse pour ne jamais l'utiliser. Les ORM, comme tout autre outil, sont sujets à des mises en garde et à une courbe d'apprentissage, et je peux vous assurer qu'ils sont parfaitement utilisables dans des "applications peu sérieuses" s'ils sont utilisés correctement.
ajouté l'auteur ghempton, source
@BgrWorker: Il s'agit plus d'un problème d'abstraction qui fuit que d'un problème de connaissance. Il est en fait très facile d’utiliser un ORM et, dans la plupart des situations, cela fonctionnera parfaitement. Puis, tout à coup, une refactorisation "innocente" introduira un problème de performances pour diverses raisons ... mais les tests fonctionnels réussiront car ils sont toujours corrects (il suffit de faire beaucoup de travail inutile). C'est pourquoi je suis favorable à un bon framework SQL: il souligne la différence entre un getter bon marché et une requête SQL coûteuse, ainsi que la délimitation claire des parties du code qui s'appuient sur une connexion SQL.
ajouté l'auteur mkuse, source
@ AndrolGenhald: Oui, tout comme les différences dans la structure des tables entre les environnements de développement/test/production et une multitude de variables. Cependant, l’avantage principal d’un framework SQL au lieu d’un ORM est qu’il est immédiatement visible dans l’examen du code que vous touchez SQL: quelles tables, quelles requêtes, etc ... contrairement aux ORM où, puisque cela ressemble tellement à du code c'est facile à négliger.
ajouté l'auteur mkuse, source
@Nacht: Les ORM ne sont pas une solution miracle du point de vue du développement . Ils peuvent résoudre le problème particulier de l'injection SQL, mais ne résolvent pas tous les problèmes. Pour ce qui est de votre question, les deux problèmes sont réglables et aucun n’est inévitable. Un bon framework SQL permet également d’éviter les injections SQL (car les requêtes SQL ne sont pas des chaînes) tout en rendant évident le lieu où les interactions de base de données se produisent et quelles requêtes sont exécutées.
ajouté l'auteur mkuse, source
C’est peut-être un bon conseil de sécurité, mais c’est un terrible conseil de développement. Les ORM ne sont PAS une solution miracle, et l’utilisation de ORM peut facilement entraîner des problèmes de performances. J'ai vu un ORM extraire une table complète en mémoire et exécuter les filtres en mémoire car il ne parvenait pas à les réduire en SQL. J'ai également vu des utilisateurs d'un ORM effectuer par inadvertance une requête dans une boucle (parce que cela ressemblait à du code!). Donc, non, les ORM ne sont pas une solution miracle ... et pour toutes les applications peu sérieuses, je recommanderais d'utiliser un bon framework SQL.
ajouté l'auteur mkuse, source
@MatthieuM. En quoi les ORM ne sont-ils pas une solution miracle pour l’injection SQL, l’objet de cette question?
ajouté l'auteur Francisco Corrales Morales, source
De plus, préféreriez-vous avoir une page Web à télécharger en 30 secondes ou des données divulguées sur Internet? L'un de ces problèmes est réparable; l'autre n'est pas.
ajouté l'auteur Francisco Corrales Morales, source
@MatthieuM. Un refactoring innocent de SQL peut également entraîner des problèmes de performances s'il empêche l'utilisation d'index.
ajouté l'auteur AndrolGenhald, source
@JimmyJames nous a laissé continuer dans le chat
ajouté l'auteur AndrolGenhald, source
@ JimmyJames Je n'essayais pas de laisser entendre que le refactoring SQL serait requis, je fournissais un contrepoint à l'argument de MatthieuM selon lequel un refactoring innocent pouvait causer des problèmes de performances lors de l'utilisation d'un ORM.
ajouté l'auteur AndrolGenhald, source
@ JimmyJames Encore une fois, pas ce que je disais. Je disais simplement qu'expliquer contre l'utilisation d'un ORM parce que "cela causerait des problèmes de performances" n'est pas nécessairement un argument valable, car des problèmes de performances peuvent également survenir avec SQL directement.
ajouté l'auteur AndrolGenhald, source
Si le PO a du mal à utiliser correctement sa technologie actuelle, le passage à une nouvelle technologie prendra encore plus de temps. Tout d’abord, sécurisez le site le plus rapidement possible. Deuxièmement, quand vous aurez plus de temps, cherchez quelle est la meilleure technologie pour l’avenir. Toutes les solutions technologiques ont des avantages et des inconvénients. Quiconque dit le contraire essaie de vous vendre quelque chose.
ajouté l'auteur erdem, source
Je pense que "le meilleur" est trop absolu. Peut-être que SQL n'est pas du tout justifié?
ajouté l'auteur Kyle, source

Nous savons, mais nous n'avons pas assez de développeurs/testeurs pour le rendre sûr à 100%.

Ce que vous entendez par cette déclaration n’est pas tout à fait clair, car les instructions préparées sont triviales dans tous les langages Web populaires (PHP, Python, Java, node.js, etc.) et sont plus ou moins une mesure efficace contre l’injection SQL. .

Voulez-vous dire que vous sous-traitez le développement et que vous ne pouvez pas vous permettre de contrôler le code qu'ils écrivent pour vous à contrat? Vous ne pouvez pas vous permettre de ne pas le faire: vous êtes toujours le responsable ici.

Voulez-vous dire que vos développeurs sont trop occupés par la mise en œuvre de fonctionnalités pour prendre quelques heures à mettre à jour le code? Tous les éléments, à l'exception des instructions préparées, prendront plus de temps et coûteront plus cher (par exemple, ORM, obsolescence, autorisations détaillées, etc.).

Voulez-vous dire que vos développeurs ne sont pas assez compétents pour effectuer cette tâche simple? C'est un gros problème (ou plus précisément, l'injection SQL ne devrait pas être votre plus grande préoccupation à ce stade).

Voulez-vous dire que votre base de code est un tel désordre imbriqué de include imbriqués dans la logique spaghetti que même des développeurs compétents mettront toujours beaucoup à faire ce qui serait autrement une simple tâche de quelques heures? De même, plus gros problème.

Quelle que soit la solution choisie, la solution consiste à utiliser des déclarations préparées, environ hier.

9
ajouté
Je veux dire que nous avons comme des milliers de classes d'accès aux données héritées mais juste un ou deux développeurs pour corriger les problèmes, nous ferons des "instructions préparées" mais nous ne sommes tout simplement pas sûrs à 100%. Comme Facebook, même Facebook a un trou de sécurité
ajouté l'auteur jl., source
@ PhungD.An Le gros problème avec le passage de la concaténation de chaînes dans des instructions SQL préparées est généralement qu'il faut un certain temps pour comprendre ce que fait le désordre existant. Le temps consacré à la résolution de ce problème va: améliorer la sécurité, améliorer les performances et rendre le code plus facile à comprendre. Essayer de nettoyer les entrées est une tâche sans fin qui ne résoudra jamais le problème fondamental et n'améliorera pas la base de code.
ajouté l'auteur nikky, source
@ PhungD.An Des failles de sécurité peuvent et vous coûteront très cher si elles sont exploitées. Bien plus cher que n'importe quel temps ou argent, vous pensez économiser en ne faisant pas ce qui est juste.
ajouté l'auteur tehvan, source
@ PhungD.An Je suis désolé, c'est rude. 1000 endroits pour changer pour 1-2 devs n'est pas aussi trivial qu'avec une architecture plus saine. Mais c'est toujours faisable, juste en jours (comme 1-2) au lieu de plusieurs heures. Pour ce qui est de la certitude à 100%, vous devriez être assez sûr de simplement exécuter grep sur votre base de code, mais si vous êtes poursuivi en justice, "nous étions occupés et cela sonnait dur" ne sera pas une défense très crédible. Beaucoup plus que "un type d'une université a demandé toutes nos données d'utilisateur et nous lui avons simplement donné ces informations et nous lui avons fait confiance pour ne pas les vendre" va être pour fb.
ajouté l'auteur user97065, source

Une fois que le conseil initial "instruction préparée" a été mis en œuvre, je recommanderais un peu de lecture sur l'injection SQL. Demander "comment puis-je empêcher l'injection de SQL" est une question assez large! La sécurité est un sujet que vous (plutôt que l'ensemble de votre équipe de développement) devez connaître très bien pour réduire le risque de compromission. Un trou mine tous vos autres efforts.

Visit the Open Web Application Security Project (OWASP) here: https://www.owasp.org/index.php/SQL_Injection

En particulier le matériel supplémentaire:

  • Aide-mémoire de prévention d'injection SQL
  • Aide-mémoire de paramétrage de requête
  • Article de guide sur la manière d'éviter les vulnérabilités d'injection SQL

Et aussi

  • How to Review Code for SQL Injection Vulnerabilities.
5
ajouté
En fait, comment empêcher l'injection SQL est une question très étroite avec une réponse très simple: ne construisez pas de chaînes de requête à partir de données contrôlées par l'utilisateur. Éviter cela en premier lieu est assez facile, mais bien sûr, trouver des endroits qui le font dans un grand code existant peut être délicat.
ajouté l'auteur tehvan, source
@Cubic Fair assez, la question de l'OP elle-même était étroite. Je lisais peut-être au-delà de la question elle-même: si quelqu'un pose ce type de question, il semble alors que ce dont il a réellement besoin, c'est d'acquérir une compréhension générale des meilleures pratiques. (et, comme le dit Guy Schalat ci-dessus, les meilleures pratiques pour votre technologie )
ajouté l'auteur stewsha, source
J'aime OWASP pour comprendre pourquoi vous faites la bonne chose, mais il existe de nombreuses autres ressources spécifiques à la pile de technologies du PO qui sont plus faciles à utiliser. Comme pour de nombreux problèmes de sécurité, le mieux est de ne pas réinventer la roue. Les pratiques de sécurité de base de la technologie que vous avez choisie constituent le meilleur départ.
ajouté l'auteur erdem, source

Un palliatif consisterait à utiliser un pare-feu pour applications Web (WAF): certaines sociétés fournissent ce service en tant que service et quelques fournisseurs de cloud proposent également des offres. CloudFlare semble en proposer un, un seul client utilisant Incapsula, et je sais que l'offre AWS WAF contient des ensembles de règles gérés pour l'injection SQL.

La façon dont cela fonctionne est que tout le trafic est envoyé vers/via le WAF (soit en l'incluant sur des serveurs, soit en configurant DNS pour qu'il pointe vers le WAF comme vous le feriez pour un CDN), et il recherche les éléments qui ressemblent à des tentatives d'injection SQL dans Les paramètres. Il ne détectera pas toutes les attaques et bloquera le trafic légitime, mais il s'agit d'un correctif de bandaid disponible.

4
ajouté
+1 pour répondre réellement à Q et ne pas répéter ce qui a déjà été dit sur l'assainissement des entrées de l'utilisateur. Bien sûr, les déclarations préparées doivent être mises en œuvre, mais selon le client, il peut être beaucoup plus rapide de lancer WAF, ce n’est peut-être pas la solution parfaite, mais cela aidera probablement à résoudre le problème dans l’immédiat.
ajouté l'auteur Bob Dizzle, source

Par "n’a pas assez de développeurs", je suppose que vous voulez dire que certaines personnes influentes de votre organisation pensent qu’elles ont des priorités plus élevées. Par conséquent, toutes les ressources dont vous disposez sont consacrées à ces tâches. Résoudre votre problème de sécurité revient donc à perdre du temps par rapport à une analyse coûts-avantages.

Votre tâche ici est de changer d'avis, tout autant que de mettre en œuvre le correctif. Quantifier ce qui est en jeu - quels seraient les dommages, en termes d'argent et de réputation, d'une autre violation? Il se peut que des lois de votre juridiction exigent de que vous signaliez des compromis concernant les données de vos utilisateurs. Cela serait-il embarrassant? Peut-il y avoir des reportages dans les médias sur les mauvaises pratiques de votre organisation?

Pensez à l’investissement pour réparer la sécurité en tant qu’assurance. Rétrospectivement, une fois que vous savez que votre immeuble n’a pas été détruit pendant 10 ans, vous pourriez faire valoir que vos primes étaient un gaspillage. Mais vous et votre organisation payez les assurances, car vous faites face à un avenir incertain. C'est la gestion des risques.

Le risque a deux facteurs: probabilité et impact. La probabilité d'une autre violation est élevée - vous savez que cela est possible et l'a été au moins une fois. Si les conséquences potentielles sont également mauvaises, augmentez la priorité de la correction de vos vulnérabilités de sécurité.

2
ajouté

En plus de toutes les bonnes réponses apportées jusqu'à présent, si vous souhaitez résoudre le problème spécifique de l'extraction des informations d'identification de l'utilisateur, vous pouvez restructurer votre base de données pour que les mots de passe soient stockés dans une table distincte avec des droits d'accès stricts. la façon dont les systèmes Unix les mettent dans/etc/shadow.

Pour vérifier les informations d'identification, vous avez besoin d'une procédure stockée qui prend le mot de passe entré (ou hachage) en tant que paramètre et renvoie un booléen. En d'autres termes, vous déchargez le travail de vérification des informations d'identification dans la base de données et le hachage réel ne quitte jamais la base de données.

Cela nécessite un minimum de refactoring et résout votre problème immédiat à la racine, au lieu d'une injection SQL spécifique tout en vous laissant vulnérable à la suivante.

0
ajouté
Bien que cela semble une bonne idée au début, la plupart des bases de données ne prennent pas en charge de bonnes fonctions de hachage des mots de passe et les requêtes de base de données sont souvent consignées. Je suppose que vous récupérez seulement le sel et les paramètres, hash, puis effectuez une autre requête pour comparer le hachage, mais cela semble trop compliqué pour en valoir la peine pour la plupart des sites.
ajouté l'auteur AndrolGenhald, source
Il y a pgcrypto pour PostgreSQL, par exemple. Je ne sais pas sur d'autres bases de données. Je ne peux pas imaginer que des choses comme Oracle n’ait pas d’équivalent.
ajouté l'auteur Tom, source

La règle la plus importante est:

Utilisez des bibliothèques, des outils et des API qui font de l'option sécurisée l'option la plus simple.

Nacht dit "juste utiliser un ORM" qui est un sous-ensemble de cette règle.

Les instructions préparées enfreignent cette règle, car leur utilisation est fastidieuse et entraîne un gonflement du code. Elles peuvent aussi être souvent plus lentes que des instructions non préparées, en fonction de votre base de données. Ils constituent une solution valable. Je ne critiquerai personne qui les utilise, mais ce n’est pas nécessairement la solution la meilleure et la plus pratique.

Et… nous voulons que l’option sûre soit simple et pratique, ainsi le programmeur l’utilise par intérêt personnel et paresse. Nous voulons que le programmeur doive réellement faire des efforts et investir des efforts afin d'utiliser l'option non sécurisée! ...

Une meilleure solution est une API comme Python dbapi. J'ai écrit il y a quelques années un équivalent en PHP, qui ressemblait à:

db_query( "SELECT * FROM mytable WHERE id=%s", $id )

Ceci est plus pratique que les déclarations préparées. Juste une ligne à taper. De plus, il retourne le résultat sous une forme que foreach() peut utiliser. Il est donc beaucoup plus facile à utiliser que fetch() et d'autres choses. Plus important encore, le code caché derrière cette API gérera correctement l'échappement. Cela rend les injections SQL non pertinentes. Cela gère environ 99% des requêtes si vous n'utilisez pas d'ORM. Les requêtes dynamiques (généralement les recherches) nécessiteront un traitement spécial, mais cela reste simple.

Si vous gardez cette règle à l'esprit, vous vous demanderez peut-être pourquoi vous devez utiliser htmlspecialchars (), et pourquoi la langue ne dispose pas d'une fonctionnalité qui rendrait le paramètre sûr (c'est-à-dire, aucune vulnérabilité XSS) plus facile à utiliser? Pourquoi oh pourquoi? Et c'est à ce moment-là que vous abandonnez PHP.

0
ajouté

Comme tout le monde l’a mentionné, corrigez le code sur le site.

Vous pouvez créer n'importe quel patch sur un mur, mais jusqu'à ce que le mur soit correctement construit, tout patch sera un problème de saignement.

Toute autre suggestion visant à nettoyer le code correspond à ce que Linus Torvalds appellerait masterbation.

  • Fix your code (from most obvious injection points to the last I.E Get params) and use prepared statements. how can i prevent sql injection in php

    • You can try a WAF (I.E ModSecurity) temporarily until you're able to get things fixed.

    • Try Perhaps some sort of IP ban on 'people testing the site' or blocking unsafe queries being made.

    • If you have the ability make a temporary (safe) login screen in front until this is resolved.

    • Try a third party service until this is resolved something like cloudflare or whatever else is out there.

Les PDO sont disponibles depuis la sortie de PHP 5.1 le 24 novembre 2005 ... Les développeurs doivent comprendre qu'ils sont la conséquence de leurs mauvaises habitudes de codage et je pense personnellement qu'il devrait y avoir une responsabilité vis-à-vis de la qualité du travail fourni.

Quoi qu'il en soit, les PDO sont faciles à mettre en œuvre. Si vos développeurs ne sont pas en mesure de fournir une meilleure qualité, je suggérerais une purge ...

0
ajouté