Question:
Comment limiter l'impact et réduire le risque d'injection SQL pour un site Web existant?
Phung D. An
2018-06-21 00:41:53 UTC
view on stackexchange narkive permalink

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

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

Ce n'est qu'un exemple, mais c'est mortel pour nous. Heureusement, c'était un bon hacker et il nous a juste envoyé un e-mail à propos du hack. Heureusement pour un site Web soumis à des attaques constantes tout au long de ses 5 ans d'existence.

Oui, nous savons que nous devons vérifier les entrées des utilisateurs partout et faire correctement les instructions de formatage / d'échappement / préparées avant d'envoyer des données à MySQL. Nous savons et nous sommes en train de le réparer. Mais nous n'avons pas assez de développeurs / testeurs pour le rendre sûr à 100%.

Maintenant, en supposant que nous ayons 0,1% de chance d'être injecté SQL d'une manière ou d'une autre. Comment pouvons-nous rendre plus difficile pour les hackers de les trouver et limiter les dégâts au maximum?

Que faisons-nous en ce qui concerne les solutions rapides / mesures supplémentaires:

  1. A la "porte" de sortie partagée par toutes les API, nous n'envoyons plus l'exception PDOException brute et le message comme avant. Mais nous devons encore informer le client qu'une exception s'est produite:

      {type: exception, code: err643, message: 'contacter le support pour err643'}  

    Je suis conscient que si le pirate voit une exception, il continuera d'essayer ...

  2. L'utilisateur que PHP utilise pour se connecter à MySQL ne peut CRUD qu'aux tables. Est-ce assez sûr?

  3. Renommez toutes les tables (nous utilisons l'open source pour que le pirate puisse deviner le nom des tables).

Que devons-nous faire d'autre?

Mise à jour: comme il y a beaucoup de commentaires, je voudrais donner quelques informations complémentaires

  1. Tout d'abord, c'est LEGACY application, développée par certains étudiants, pas de niveau entreprise. L'équipe de développement est introuvable, maintenant seulement 1 ou 2 gars de test de développement hybride gérant des centaines de classes d'accès aux données.
  2. Le mot de passe est haché avec SHA-256, oui ça craint. Et nous le changeons en mode PHP recommandé.
  3. L'injection SQL a 17 ans. Pourquoi est-ce toujours là?
  4. Les instructions préparées sont-elles 100% sûres contre l'injection SQL?
Les commentaires ne sont pas destinés à une discussion approfondie;cette conversation a été [déplacée vers le chat] (https://chat.stackexchange.com/rooms/79300/discussion-on-question-by-phung-d-an-how-to-limit-the-impact-of-et-réduire-le).
Onze réponses:
#1
+80
Anders
2018-06-21 01:08:04 UTC
view on stackexchange narkive permalink

Ne passez pas beaucoup de temps sur des solutions de contournement ou des demi-correctifs. Chaque minute que vous passez à essayer de mettre en œuvre tout ce qui est suggéré ici est une minute que vous auriez pu passer à mettre en œuvre des déclarations préparées. C'est la seule vraie solution.

Si vous avez une vulnérabilité SQLi, l'attaquant finira probablement par gagner quoi que vous fassiez pour essayer de la ralentir. Sachez donc que même si vous pouvez apporter des améliorations, vous jouez à un jeu perdant à moins que vous ne résolviez la cause du problème.

Quant à ce que vous avez essayé jusqu'à présent: masquer les messages bon départ. Je vous recommande d'appliquer des autorisations encore plus strictes (voir ci-dessous). Il est discutable de savoir si changer les noms de table aide, mais cela ne fera probablement pas de mal.

Ok, alors qu'en est-il de ces autorisations? Limitez autant que possible ce que l'utilisateur de la base de données peut faire, jusqu'au niveau de la table ou même de la colonne. 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 qui a le droit de lire la colonne de mot de passe lorsque vous avez réellement besoin de lire la colonne de mot de passe. De cette façon, si vous avez une vulnérabilité d'injection dans une autre requête, elle ne peut pas être exploitée pour fuir les 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 il faut du temps et de l'énergie pour le configurer. Vous feriez probablement mieux d'utiliser ce temps pour implémenter des déclarations préparées.

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

Je ne peux pas approuver le conseil général de ne se connecter qu'avec un utilisateur particulier lorsque vous avez besoin d'une opération particulière.Cela devient impossible trop rapidement.Si vous voulez vraiment, une séparation modeste serait acceptable, comme l'écriture séparée sur les tables utilisateur de tout le reste.Mais vous devez avoir toutes les requêtes pour une seule requête en une seule transaction.Essayer de s'assurer que c'est le cas pour chaque chemin de code possible serait un énorme fardeau si vous avez beaucoup d'utilisateurs de bases de données différents.
En général, je suis d'accord avec cela, et il y a 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 système qui n'a pas de connaissances spécifiques sur la base de code d'application.Il en va de même pour les modifications de base de données, qui peuvent être effectuées par un DBA.Le fait est que les compétences des gens varient considérablement et que chaque personne est adaptée à différentes tâches.Si vous pouvez bien exploiter les compétences des gens, vous pouvez mieux travailler en équipe.
_ "On peut se demander si changer les noms de table aide, mais ça ne fera probablement pas de mal." _ - Cela peut nuire à vos propres développeurs sur toute la ligne, les surprendre chaque fois qu'ils doivent accéder à une table qui n'a pas le nom prévu.
J'utilise PDO avec des déclarations préparées depuis un certain temps maintenant, mais cela devient stressant après un certain temps.J'ai récemment commencé à utiliser [Medoo] (http://medoo.in).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 facilite vraiment la vie puisque vous n'avez plus besoin de penser aux déclarations préparées.
@RobinK Je suis très sceptique sur le fait que l'utilisation d'instructions préparées soit beaucoup plus "stressante" que de concaténer manuellement des chaînes ensemble partout ... et, franchement, qui s'en soucie quand c'est simplement le strict minimum de responsabilité à avoir lors de la programmation en utilisant SQL?Je ne suis pas sûr que simplement abandonner et ajouter une bibliothèque tierce va faire beaucoup plus que compliquer les choses.
J'envisagerais également d'investir l'argent que vous êtes censé utiliser pour _ "... limiter l'impact et réduire le risque ..." _ pour payer un pentest professionnel (évidemment pendant que vos développeurs sont raisonnablement sûrs d'avoir fait leur travail)
#2
+65
trietend
2018-06-21 01:05:50 UTC
view on stackexchange narkive permalink

La seule manière correcte est d'utiliser des instructions préparées.

  1. Si vous masquez 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 acquis 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 forcera brutalement les noms de table pour vous char par char. Cela n'a pas besoin de beaucoup de temps.

Vous pouvez également limiter le nombre d'appels, pour rendre la tâche plus difficile pour les attaquants ou faire des alertes sur les appels suspects et arrêter ce manuel, mais la seule façon correcte de résoudre ce problème est d'utiliser des instructions préparées. Il suffit de parcourir votre code source et de jeter un œil aux instructions SQL avec un contenu dynamique et de les remplacer.

Faites attention aux restrictions, car cela peut rapidement impacter les utilisateurs légitimes sachant que le problème ici concerne une requête `GET`, donc pourrait être injecté dans une balise` `afin que tous les utilisateurs qui voient la page avec cette balise déclenchent une requête,et pourrait finir par être verrouillé par le site Web.
Il peut également être judicieux d'intégrer les révisions de code à votre processus, par exemple.examinez tout ce qui est fusionné dans la branche principale ou de production.Avoir 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 paramètres dans une requête SQL).Cela empêchera l'introduction de nouvelles vulnérabilités après la correction des vulnérabilités actuelles.
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?
Ok, il peut y avoir d'autres options, mais si l'OP court déjà trop peu de temps de programmation, ces autres méthodes seront simplement plus lentes.Les déclarations préparées sont probablement le moyen le plus pratique de fermer le trou.
@phresnel Quel type de base de données doit être utilisé à la place?
@curiousguy, ... vous n'obtenez pas d'injection SQL dans une base de données [Datalog] (https://en.wikipedia.org/wiki/Datalog).Là encore, cela tend à être dû au fait que les implémentations récemment populaires ([DataScript] (https://github.com/tonsky/datascript), [Datomic] (https://www.datomic.com/)) utilisent des structures de données LISPycomme des spécifications de requête - pas des chaînes - il n'y a donc pas de tentation d'essayer de construire ces requêtes via la concaténation de chaînes.
@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 simple carte / dictionnaire / tableau associatif chargé dans la mémoire d'un démon / service et stockée dans un fichier CSV, XML ou JSON pourrait être la bonne chose.Une implémentation de ceci serait simple, ou utiliserait CouchDB, par exemple.Possibilités infinies: c'est essentiellement juste une structure de données et un choix d'algorithme, même si je me rends compte que même les "Bachelors" / "Masters" en Allemagne semblent avoir oublié les structures de données et les algorithmes.Pour commencer: https://bit.ly/2lEy9GL
«La seule manière correcte» Je ne suis pas du tout d'accord avec «la seule manière correcte».Il existe de nombreuses façons de corriger les manières.(Ils finissent par faire quelque chose d'équivalent.)
#3
+26
Gloweye
2018-06-21 15:23:55 UTC
view on stackexchange narkive permalink

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

C'est le vrai problème . Jusqu'à ce que vous embauchiez plus de personnes ou que vous ne réaffectiez pas vos priorités, vous n'êtes pas en sécurité. Arrêter 99,9% des attaquants signifie que vos données ont été compromises. Les solutions de pansement sont une mauvaise chose, et elles ne fonctionnent pas . Ne perdez pas de temps à refactoriser votre modèle d'accès SQL pendant que vous pourriez résoudre des problèmes réels.

En ce qui concerne la solution de code, l'utilisation d'instructions préparées, comme beaucoup de gens ici le suggèrent, 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 cela coûte beaucoup moins de temps. Il suffit de grep toute votre base de code pour tout ce qui concerne SQL et de le corriger.

Je ne pense pas qu'embaucher plus de personnes serait une [solution à court terme] (https://softwareengineering.stackexchange.com/questions/14968/why-does-adding-more-resource-to-a-late-project-make-it-later).Et les problèmes de sécurité nécessitent des solutions immédiates.Vos autres suggestions sont parfaites.
@xDaizu et Jacco: merci pour votre intérêt.nous avons comme des milliers d'anciennes classes d'accès aux données, mais juste 1-2 développeurs pour corriger les choses, nous ferons des «déclarations préparées» mais nous ne sommes tout simplement pas sûrs à 100%
@xDaizu Bien que je sois normalement un fervent partisan de l'idée que vous ne pouvez pas amener plus de personnes dans un projet tardif pour l'accélérer, trouver des personnes capables de traduire SQL en instructions préparées est relativement facile car c'est une compétence assez basique et universelle pour lela plupart.
embaucher beaucoup de gens en retard peut en général être mauvais, mais comme l'a dit @wedstrom, traduire simplement en déclarations préparées devrait être quelque chose que les personnes qui répondent à une opportunité d'emploi PHP peuvent faire sans beaucoup d'introduction.Les présentations appropriées pourraient être après cela.Par exemple, refactorisez le code jusqu'à ce que vous ayez ces mille classes d'accès aux données héritées avec une superclasse commune qui contient toutes les bases SQL.
#4
+9
Nacht
2018-06-21 10:37:33 UTC
view on stackexchange narkive permalink

Purgez définitivement tout SQL de votre code

La meilleure solution à ce problème est de supprimer tout le code SQL en tant que chaînes littérales de votre code et de ne plus jamais le réintroduire. À la place, utilisez un logiciel ORM comme Hibernate ou Entity Framework. De toute façon, ce logiciel est beaucoup plus agréable à utiliser que le SQL brut, et paramètre automatiquement votre SQL lorsqu'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 de mettre en œuvre ces packages, ou si vous ne pouvez pas les utiliser pour une autre raison, la réponse de trietend est la meilleure chose à faire, en utilisant des déclarations préparées. Cela vous permettra d'être à l'abri de l'injection SQL. Autrement dit, jusqu'à ce que vous mettiez la pression sur vos développeurs pour qu'ils fournissent des solutions rapides, auquel moment ils peuvent à nouveau oublier de paramétrer une seule variable, vous laissant là où vous avez commencé.

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 d'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 n'a pas réussi à les réduire en SQL.J'ai également vu des utilisateurs d'un ORM faire par inadvertance une requête dans une boucle (car cela ressemblait à du code!).Donc, non, les ORM ne sont pas une solution miracle ... et pour toutes les applications semi-sérieuses, je recommanderais d'utiliser un bon framework SQL.
@MatthieuM.ne pas savoir comment 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 adaptés à des «applications semi-sérieuses» s'ils sont utilisés correctement.
@BgrWorker: C'est plus une question d'abstraction qui fuit, qu'une question de connaissance.Il est en fait très facile d'utiliser un ORM, et dans la plupart des situations, cela fonctionnera très bien.Puis, soudainement, un refactoring "innocent" introduira un problème de performance pour diverses raisons ... mais les tests fonctionnels passeront parce que c'est toujours correct (juste faire beaucoup de travail inutile).C'est pourquoi je préfère un bon framework SQL: il met l'accent sur la différence entre un getter bon marché et une requête SQL coûteuse, et délimite clairement les parties du code qui reposent sur une connexion SQL.
Je pense que "le meilleur" est trop absolu.Peut-être que SQL n'est pas du tout justifié?
@MatthieuM.Un refactoring innocent de SQL peut également entraîner des problèmes de performances s'il empêche l'utilisation d'index.
@AndrolGenhald: Oui, tout comme les écarts dans la structure des tables entre les environnements de développement / test / production et une myriade de variables.Cependant, le principal avantage d'un framework SQL au lieu d'un ORM ici, c'est qu'il est immédiatement visible dans la revue de code que vous touchez SQL: quelles tables, quelles requêtes, etc ... contrairement aux ORM où puisque cela ressemble tellement à du codec'est facile à oublier.
Si l'OP 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, lorsque vous aurez plus de temps, recherchez 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.
@MatthieuM.En quoi les ORM ne sont-ils pas une solution miracle pour l'injection SQL, sur quoi porte cette question?
De plus, préférez-vous une page Web qui prend 30 secondes à charger, ou vos données fuites partout sur Internet?L'un de ces problèmes peut être résolu;l'autre ne l'est pas.
Les ORM @Nacht: ne sont pas une solution miracle d'un point de vue * développement *.Ils peuvent résoudre le problème particulier de l'injection SQL, mais ne résolvent pas tous les problèmes.Quant à votre question d'homme de paille: les deux problèmes peuvent être résolus et aucun n'est inévitable.Un bon framework SQL * également * évite les injections SQL (car les requêtes SQL ne sont pas des chaînes) tout en indiquant clairement où les interactions de base de données se produisent et quelles requêtes sont exécutées.
@Nacht La plupart des ORM ont leur propre langage de requête, par ex.HQL.Voici un exemple de CVE pour une attaque par injection HQL.["Les attaques par injection Hibernate Query Language (HQL) et obtenir des informations sensibles via le paramètre entityName."] (Https://nvd.nist.gov/vuln/detail/CVE-2016-1595).Si tout ce que vous faites est de changer SQLi en HQLi, je ne suis pas sûr que cela résout vraiment quoi que ce soit.
@AndrolGenhald La refactorisation en instructions préparées ne nécessite pas la refactorisation du 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 quand il y a une logique complexe en essayant de générer dynamiquement différentes instructions (par exemple en ajoutant différentes clauses where) en fonction de différentes conditions.Ibatis a une solution décente pour cela en utilisant des modèles et génère une instruction préparée pour chaque requête distincte qui est exécutée.
@Nacht Voici un meilleur exemple de la façon dont un ORM n'est `` pas une solution miracle pour l'injection SQL '' qui explique comment cela peut se produire: https://cwe.mitre.org/data/definitions/564.html
@JimmyJames Je n'essayais pas d'impliquer que le refactoring de SQL serait nécessaire, je fournissais un contrepoint au point de MatthieuM selon lequel un refactoring innocent pouvait causer des problèmes de performances lors de l'utilisation d'un ORM.
@AndrolGenhald Mon expérience avec les ORM lourds est que d'essayer de les utiliser avec une base de données qui n'a pas été conçue pour fonctionner avec eux est problématique.Il est vraiment difficile d'en implémenter un sans un certain niveau ou une refactorisation du code, des structures de base de données et / ou des requêtes.La refactorisation pour utiliser des instructions préparées * peut * certainement être effectuée sans modifier la structure de l'une d'elles, mais le niveau d'effort variera.
@JimmyJames Encore une fois, pas ce que je disais.Je disais simplement que s'opposer à l'utilisation d'un ORM parce que "cela causera des problèmes de performances" n'est pas nécessairement un bon argument car des problèmes de performances peuvent également survenir en utilisant SQL directement.
@AndrolGenhald Est-ce l'argument le plus fort pour ne pas bouger?Peut-être pas mais l'OP a déjà SQL.Il est peu probable que le passage à un ORM soit une baisse de remplacement lorsque le passage à des instructions préparées en fait plus ou moins.Dans mon estimation (largement uniforme), il est beaucoup plus probable que l'OP introduise des changements dans les plans d'exécution lors du passage à un ORM que lors de la refactorisation pour utiliser des instructions de préparation.
@JimmyJames laissez-nous [continuer dans le chat] (https://chat.stackexchange.com/rooms/79246/)
#5
+9
Jared Smith
2018-06-21 19:18:37 UTC
view on stackexchange narkive permalink

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

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

Voulez-vous dire que vous sous-traitez développement et ne peut pas se permettre de QA le code qu'ils écrivent pour vous sur contrat? Vous ne pouvez pas vous permettre de ne pas le faire: vous êtes toujours la partie responsable ici.

Voulez-vous dire que vos développeurs sont trop occupés à mettre en œuvre des fonctionnalités pour prendre quelques heures pour mettre à jour la base de code? Tout autre que les instructions préparées prendra plus de temps et coûtera plus cher (par exemple ORM, obsfucation, autorisations précises, etc.).

Voulez-vous dire que vos développeurs ne sont pas assez compétents pour effectuer cette tâche simple? C'est un plus gros problème (ou pour être plus précis, 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 de logique spaghetti au format fusil de include s que même les développeurs compétents mettront une éternité à effectuer ce qui serait autrement une simple tâche de quelques heures? De même, un problème plus grave.

Quelle que soit celle-ci, la solution est d'utiliser des déclarations préparées, vers hier.

Je veux dire que nous avons des milliers d'anciennes classes d'accès aux données, mais juste 1-2 développeurs pour réparer les choses, nous ferons des «déclarations préparées» mais nous ne sommes tout simplement pas sûrs à 100%.Comme allez, même Facebook a une faille de sécurité
@PhungD.An Je suis désolé, c'est difficile.1000 endroits à changer pour 1 à 2 développeurs ne sont pas aussi triviaux qu'avec une architecture plus saine.Mais c'est toujours faisable, juste en jours (comme 1-2) au lieu d'heures.Pour être sûr à 100%, vous devriez être à peu près 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 ... pas plus que"un gars dans une université a demandé toutes nos données d'utilisateur et nous l'avons juste donné et lui avons fait confiance pour ne pas le vendre "va être pour fb.
@PhungD.An Le gros problème avec le passage de la concaténation de chaînes en SQL aux instructions 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é à résoudre ce problème: améliorera la sécurité, améliorera les performances et rendra 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 racine et n'améliorera pas la base de code.
@PhungD.An Les failles de sécurité peuvent et _seront_ vous coûter très cher si jamais elles sont exploitées.Beaucoup plus cher que le temps ou l'argent que vous pensez économiser en ne faisant pas la bonne chose.
#6
+5
Nicolas
2018-06-21 23:02:45 UTC
view on stackexchange narkive permalink

Une fois que le conseil initial "instruction préparée" a été implémenté, je recommanderais quelques lectures sur l'injection SQL. Se demander "comment éviter l'injection SQL" est une question assez large! La sécurité est un sujet avec lequel vous (plutôt que toute votre équipe de développement) devez être très familier afin de réduire le risque de compromis. Un trou sape tous vos autres efforts.

Visitez le projet Open Web Application Security (OWASP) ici: https://www.owasp.org/index.php/SQL_Injection

En particulier le matériel supplémentaire:

  • Aide-mémoire sur la prévention des injections SQL
  • Aide-mémoire sur le paramétrage des requêtes
  • Article de guide sur la façon d'éviter les vulnérabilités d'injection SQL

Et aussi

  • Comment vérifier le code pour les vulnérabilités d'injection SQL .
J'adore OWASP pour comprendre pourquoi vous faites la bonne chose, mais il existe de nombreuses autres ressources spécifiques à la pile technologique de l'OP qui sont plus faciles à démarrer.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 choisie sont le meilleur départ.
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 une grande base de code existante peut être délicat.
@Cubic Très bien, la question du PO 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 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_)
#7
+4
CoderTao
2018-06-22 02:17:28 UTC
view on stackexchange narkive permalink

Une mesure provisoire serait de se pencher sur un pare-feu d'application Web (WAF) - il existe quelques entreprises qui fournissent cela en tant que service et quelques fournisseurs de cloud qui proposent également des offres. CloudFlare semble en offrir un, j'ai eu un client qui utilise Incapsula, et je sais que l'offre AWS WAF a 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 les serveurs, soit en définissant DNS pour qu'il pointe vers le WAF comme vous le feriez pour un CDN), et il recherche des choses qui ressemblent à des tentatives d'injection SQL dans les paramètres. Il ne détecte pas toutes les attaques et peut bloquer le trafic légitime, mais il s'agit d'un correctif de pansement disponible.

+1 pour avoir répondu à Q et ne pas répéter ce qui a déjà été dit à propos de l'assainissement des entrées utilisateur.Bien sûr, les déclarations préparées doivent être implémentées, mais en fonction du s / w, il peut être beaucoup plus rapide de faire fonctionner WAF, ce n'est peut-être pas la solution parfaite, mais cela aidera probablement dans la situation immédiate.
#8
+2
Concrete Gannet
2018-06-22 08:28:22 UTC
view on stackexchange narkive permalink

Par "je n'ai pas assez de développeurs", je suppose que vous voulez dire que certaines personnes influentes de votre organisation pensent qu'il y a des priorités plus élevées, donc quelles que soient les ressources dont vous disposez sont consacrées à ces choses. Donc, résoudre votre problème de sécurité, c'est perdre d'autres choses dans une analyse coûts-avantages.

Votre tâche ici est de changer d'avis, autant que d'implémenter 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 certaines lois de votre juridiction vous obligent à signaler les compromissions des données de vos utilisateurs. Cela serait-il embarrassant? Peut-il y avoir des reportages médiatiques sur les mauvaises pratiques de votre organisation?

Pensez à l'investissement pour fixer la sécurité comme une assurance. Rétrospectivement, une fois que vous savez que votre bâtiment n'a pas brûlé pendant une période de dix ans, vous pourriez soutenir que vos primes étaient un gaspillage. Mais vous et votre organisation payez une assurance, car votre avenir est incertain. C'est la gestion du risque.

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

#9
+1
LUser
2018-06-23 16:53:53 UTC
view on stackexchange narkive permalink

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

Vous pouvez apporter les correctifs de votre choix à un mur, mais tant que le mur ne sera pas construit correctement, tous les correctifs seront un problème de saignement.

Toute autre suggestion pour nettoyer le code est ce que Linus Torvalds appellerait masterbation.

  • Corrigez votre code (à partir des points d'injection les plus évidents au dernier IE Get params) et utilisez des instructions préparées. comment puis-je empêcher l'injection SQL dans PHP

    • Vous pouvez essayer un WAF (IE ModSecurity ) temporairement jusqu'à ce que vous soyez en mesure de réparer les choses.

    • Essayez Peut-être une sorte d'interdiction de la propriété intellectuelle sur les «personnes testant le site» ou le blocage des requêtes non sécurisées.

    • Si vous avez la possibilité de créer un écran de connexion temporaire (sécurisé) devant jusqu'à ce que cela soit résolu.

    • Essayez un service tiers jusqu'à ce que cela soit résolu, quelque chose comme cloudflare ou tout autre élément

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

En tout cas, les PDO sont une chose facile à mettre en œuvre. Si vos développeurs ne sont pas en mesure de fournir une meilleure qualité, alors je suggérerais une purge ...

#10
  0
bobflux
2018-06-24 00:05:31 UTC
view on stackexchange narkive permalink

La règle la plus importante est:

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

Nacht dit "il suffit d'utiliser un ORM "qui est un sous-ensemble de cette règle.

Les instructions préparées enfreignent cette règle, car elles sont lourdes à utiliser, entraînent un gonflement du code, elles peuvent également être souvent plus lentes que les instructions non préparées en fonction de votre base de données. C'est 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, donc le programmeur l'utilise par intérêt personnel et par paresse. Nous voulons que le programmeur doive réellement faire tout son possible et investir quelques efforts pour utiliser l'option unsafe! ...

Une bien meilleure solution est une API comme Python dbapi. J'ai écrit un équivalent php il y a des années, qui était comme:

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

C'est plus pratique que les déclarations préparées. Juste une ligne à taper. Il renvoie également le résultat sous une forme que foreach () peut utiliser, donc il est beaucoup plus facile à utiliser que fetch () et tout. Plus important encore, le code caché derrière cette API gérera correctement l'échappement. Cela rend les injections SQL inutiles. Cela gère environ 99% des requêtes si vous n'utilisez pas d'ORM. Les requêtes dynamiques (généralement la recherche) nécessiteront cependant un traitement spécial, mais c'est toujours facile.

Si vous gardez cette règle à l'esprit, alors à un moment donné, vous devrez vous demander pourquoi vous devez utiliser htmlspecialchars (), et pourquoi le langage n'a pas de fonctionnalité qui rendrait le paramètre sûr (c'est-à-dire pas de vulns XSS) le plus facile à utiliser? Pourquoi oh pourquoi? Et c'est là que vous abandonnez PHP.

#11
  0
Tom
2018-07-06 15:17:25 UTC
view on stackexchange narkive permalink

En plus de toutes les excellentes réponses à ce jour, si vous souhaitez résoudre le problème spécifique de l'extraction des informations d'identification des utilisateurs, vous pouvez refactoriser votre base de données pour avoir les mots de passe dans une table séparée avec des droits d'accès stricts , similaire à la façon dont les systèmes Unix les placent 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 saisi (ou hachage) comme paramètre et renvoie un booléen. En d'autres termes, vous déchargez la tâche 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 une refactorisation minimale et résout votre problème immédiat à la racine, au lieu d'une injection SQL spécifique pendant vous laissant vulnérable au prochain.

Bien que cela semble être une bonne idée au début, la plupart des bases de données ne prennent pas en charge les bonnes fonctions de hachage de mot de passe et les requêtes de base de données sont souvent enregistrées.Je suppose que vous récupérez _just_ le sel et les paramètres, le hachage, puis faites une autre requête pour comparer le hachage, mais cela semble trop compliqué pour en valoir la peine pour la plupart des sites.
il y a pgcrypto pour PostgreSQL, par exemple.Je ne connais pas les autres bases de données.Je ne peux pas imaginer des trucs comme Oracle n'a pas d'équivalents.


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 4.0 sous laquelle il est distribué.
Loading...