web-dev-qa-db-fra.com

Comment empêcher les attaques par injection de code en PHP?

Je suis un peu confus, il y a tellement de fonctions en PHP, et certaines utilisent ceci, d'autres utilisent cela. Certaines personnes utilisent: htmlspecialchars(), htmlentities(), strip_tags() etc.

Quelle est la bonne et qu'utilisez-vous habituellement?

Est-ce correct (conseillez-moi un meilleur, le cas échéant):

$var = mysql_real_escape_string(htmlentities($_POST['username']));

Cette ligne peut empêcher l'injection MySQL et les attaques XSS ??

Btw, y a-t-il d'autres choses auxquelles je dois faire attention à part l'attaque XSS et l'injection MySQL?

MODIFIER

De conclure:

Si je veux insérer une chaîne dans la base de données, je n'ai pas besoin d'utiliser htmlentities, il suffit d'utiliser le mysql_real_escape_string. Lors de l'affichage des données, utilisez htmlentities(), c'est ce que vous voulez dire ??

Résumer:

  • mysql_real_escape_string Utilisé lors de l'insertion dans la base de données
  • htmlentities() utilisé lors de la sortie de données dans une page Web
  • htmlspecialchars() utilisé quand?
  • strip_tags() utilisé quand?
  • addslashes() utilisé quand?

Quelqu'un peut-il remplir le point d'interrogation?

52
bbtang
  • mysql_real_escape_string Utilisé lors de l'insertion dans la base de données
  • htmlentities() utilisée lors de la sortie de données dans une page Web
  • htmlspecialchars() utilisé quand?
  • strip_tags() utilisé quand?
  • addslashes() utilisé quand?

htmlspecialchars () utilisé quand?

htmlspecialchars est à peu près la même chose que htmlentities. La différence: les encodages de caractères.

Les deux codent des caractères de contrôle comme <, >, & Et ainsi de suite, utilisés pour ouvrir des balises, etc. htmlentities codent également des caractères d'autres langues comme les trémas, l'euro -symboles et autres. Si vos sites Web sont en UTF, utilisez htmlspecialchars(), sinon utilisez htmlentities().

strip_tags () utilisé quand?

htmlspecialchars/entities codent les caractères spéciaux, donc ils sont affichés mais pas interprétés. strip_tags Les supprime.

En pratique, cela dépend de ce que vous devez faire.

Un exemple: vous avez codé un forum et donnez aux utilisateurs un champ de texte pour qu'ils puissent publier des trucs. Les malveillants essaient juste:

pictures of <a href="javascript:void(window.setInterval(function () {window.open('http://evil.com');}, 1000));">kittens</a> here

Si vous ne faites rien, le lien sera affiché et une victime qui cliquera sur le lien recevra de nombreuses fenêtres contextuelles.

Si vous htmlentity/htmlspecialchar votre sortie, le texte sera là tel quel. Si vous le supprimez, il supprime simplement les balises et l'affiche:

pictures of kittens here

Parfois, vous voudrez peut-être un mélange, laissez quelques balises dedans, comme <b> (strip_tags Peut laisser certaines balises là-dedans). Cela n'est pas sûr non plus, il vaut donc mieux utiliser une bibliothèque complète contre XSS.

ajoute des cils

Pour citer un ancienne version du PHP :

Renvoie une chaîne avec des barres obliques inverses avant les caractères qui doivent être entre guillemets dans les requêtes de base de données, etc. Ces caractères sont les guillemets simples ('), les guillemets doubles ("), les barres obliques inverses () et NUL (les [~ # ~] null [~ # ~] octet).

Un exemple d'utilisation de addlashes () est lorsque vous saisissez des données dans une base de données. Par exemple, pour insérer le nom O'reilly dans une base de données, vous devrez l'échapper. Il est fortement recommandé d'utiliser la fonction d'échappement spécifique au SGBD (par exemple, mysqli_real_escape_string () pour MySQL ou pg_escape_string () pour PostgreSQL), mais si le SGBD que vous utilisez n'a pas de fonction d'échappement et que le SGBD utilise\pour échapper des caractères spéciaux, vous peut utiliser cette fonction.

version actuelle est libellé différemment.

64
stefs

J'ai pensé à cette liste de contrôle rapide:

  • Utilisez toujours HTTPS, sans HTTPS votre site est totalement non chiffré . Et non, le chiffrement côté client et son envoi ne fonctionneront pas, pensez-y. Les certificats HTTPS non valides vous rendent également vulnérable à une attaque MITM . Utilisez simplement Let's Encrypt si vous ne pouvez pas vous permettre un certificat.
  • Utilisez toujours htmlspecialchars() sur toute sortie de votre code PHP, c'est-à-dire, ou contient une entrée utilisateur . La plupart des moteurs de modèles vous aident à le faire facilement.
  • Utilisez l'indicateur HTTP uniquement dans votre php.ini Pour empêcher les scripts d'accéder à vos cookies
  • Prévenir les problèmes liés à la session
    • N'exposez jamais PHPSESSID (ID de session) de l'utilisateur en dehors du cookie , si quelqu'un apprend un ID de session de quelqu'un d'autre, il peut simplement utilisez-le pour vous connecter à leur compte
    • Soyez très prudent avec la fonction Remember me, Montrez peut-être un petit avertissement.
    • Actualiser l'ID de session lorsque l'utilisateur se connecte (ou tout autre moyen approprié)
    • Délai d'expiration des sessions inactives
  • Jamais faites confiance à un cookie, il peut être changé, supprimé, modifié et créé par un script/utilisateur à tout moment
  • Prévention des problèmes liés à SQL
    • Utilisez toujours des instructions préparées . Les instructions préparées entraînent le passage séparé de l'entrée utilisateur et empêchent injection SQL
    • Faites que votre code lève une exception en cas d'échec. Parfois, votre serveur SQL peut être arrêté pour une raison quelconque, des bibliothèques comme PDO ignorent cette erreur par défaut et enregistrent un avertissement dans les journaux. Cela entraîne la nullité des variables que vous obtenez à partir de la base de données, selon votre code, cela peut entraîner un problème de sécurité.
    • Certaines bibliothèques comme PDO emulate ont préparé des instructions. Éteignez ça.
    • Utilisez l'encodage UTF-8 Dans vos bases de données, il vous permet de stocker pratiquement n'importe quel caractère et d'éviter les attaques liées à l'encodage
    • Ne concaténez jamais rien à votre requête . Des choses comme $myquery = "INSERT INTO mydb.mytable (title) VALUES(" . $user_input . ")" signifient à peu près que vous avez un énorme risque pour la sécurité d'une injection SQL.
  • Stockez les fichiers téléchargés dans des noms de fichiers aléatoires sans extension. Si un utilisateur télécharge un fichier avec l'extension de fichier .php, Chaque fois que votre code charge ce fichier, il l'exécute et lui permet d'exécuter du code backend
  • Assurez-vous que vous n'êtes pas vulnérable à une attaque CSRF .
  • Mettez toujours à jour votre PHP copie pour garantir les derniers correctifs de sécurité et améliorations de performances
10
OverCoder

N'encodez les données qu'au point où elles entrent dans le système pour lesquelles elles doivent être encodées - sinon vous rencontrerez des situations où vous voudrez manipuler les vraies données.

Pour l'injection SQL - utilisez des variables liées comme décrit dans Comment puis-je empêcher l'injection SQL en PHP? (il parle des instructions préparées, mais c'est la liaison qui vous protège, pas la préparation).

Pour XSS - si vous écrivez en HTML au point où HTML ou texte est spécifié. Utilisez htmlentities au point où vous générez votre document. J'éviterais de stocker les données sous cette forme dans la base de données (sauf possible dans un système en écriture-rare-lecture-fréquente où les performances du processeur/les temps d'accès au disque devenaient et posaient des problèmes - alors j'aurais une version raw_ et html_ de la colonne … Ou utilisez simplement memcached ou similaire).

Si vous autorisez les utilisateurs à saisir des URL, vous devez être plus prudent, car javascript:do_evil() est un URI valide qui s'exécutera (par exemple en tant que href pour un lien cliqué ou (dans certains navigateurs) le src d'un image qui vient d'être chargée).

6
Quentin

htmlspecialchars() transforme &, ', ", < et > dans un format d'entité HTML (&amp;, &quot;, etc.)

htmlentities() transforme tous les caractères applicables dans leur format d'entité HTML.

strip_tags() supprime toutes les balises HTML et PHP.

htmlspecialchars() et htmlentities() prennent tous deux un paramètre facultatif indiquant comment les guillemets doivent être traités. Voir le manuel PHP pour les détails.

La fonction strip_tags() prend un paramètre facultatif indiquant quelles balises ne doivent pas être supprimées.

 $var = strip_tags ($var, '<p><br />');

La fonction strip_tags() supprimera même les balises HTML non valides, ce qui peut provoquer des problèmes. Par exemple, strip_tags() supprimera tout le code qu'il pense être une balise HTML, même s'il est mal formé, comme

<b I forgot to close the tag.
4
Faraz Kelhini

Vous avez seulement besoin d'utiliser mysql_escape_string () lors de l'insertion dans une base de données et htmlentites lors de l'affichage du HTML. Cela suffit si vous voulez empêcher une simple attaque par injection, mais il y a sans aucun doute de nombreux autres problèmes de sécurité que vous devez connaître lors du développement d'une application Web, un autre problème majeur étant les falsifications de demandes intersites.

3
Sam152

Je n'utiliserais pas htmlentities () pour insérer des données dans la base de données ou interroger la base de données. Si les données de votre base de données sont stockées en tant qu'entités, ces données ne sont alors utiles qu'à quelque chose qui comprend les entités html.

Vous devez utiliser différents mécanismes d'échappement pour différents types de sortie, par exemple SQL - mysql_real_escape_string () , HTML - htmlentities () ou htmlspecialchars () , Shell - escapeshellarg () . En effet, les caractères qui sont "dangereux" sont différents pour chacun - il n'y a pas de moyen magique de sécuriser des données pour n'importe quel support de sortie.

2
Tom Haigh

Je sais que c'est une vieille question, mais de nos jours la réponse la plus votée peut être trompeuse pour les débutants.

À partir de 2017

  1. Vous ne devriez jamais utiliser mysql_real_escape_string. Même mysqli_real_escape_string est trop faible pour protéger votre base de données contre les injections SQL. Au lieu de cela, vous devez utiliser PDO et des techniques similaires. (voir ce guide )

  2. XSS (ici je veux dire: strip_tags(), addslashes(), htmlspecialchars(), htmlentities()) - ici la réponse la plus votée est toujours correcte, mais je suggérerait de lire cet article

1
Tomasz Durda

Jetez un œil à ce site PHP Security Consortium . J'ai trouvé que c'était un bon site pour une vue d'ensemble sur PHP Security (SQL Injection et XSS inclus).

1
Henrik P. Hessel