2010-03-01 6 views
55

Est-ce que mysql_real_escape_string suffit pour nettoyer les entrées de l'utilisateur dans la plupart des situations?PHP: mysql_real_escape_string est-il suffisant pour nettoyer les entrées utilisateur?

:: EDIT ::

Je pense surtout en termes de prévention de l'injection SQL, mais je veux finalement savoir si je peux faire confiance les données utilisateur après je demande mysql_real_escape_string ou si je devrais prendre des mesures supplémentaires pour nettoyer la données avant de le transmettre autour de l'application et des bases de données.

Je vois où le nettoyage des caractères HTML est important mais je ne le considérerais pas comme nécessaire pour faire confiance à l'entrée de l'utilisateur.

T

+3

XSS est un énorme problème, si vous l'ignorez vous demandez des problèmes de grandeur égale. Vous devez valider sur le chemin, mais si vous ne supprimez pas javascript lorsque vous affichez du contenu utilisateur, il est vraiment, vraiment trivial de faire des choses comme détournement de session et attaques XSS qui est franchement plus facile à utiliser que l'injection SQL, mais est un peu plus récent pour que les gens ne l'obtiennent pas encore. –

+1

'mysql_real_escape_string' est uniquement destiné à protéger contre les injections SQL. Pour les autres vulnérabilités, vous avez besoin d'autres outils. – Gumbo

+1

@Gumbo mysql_real_we_really_mean_it_this_time_escape_string couvrirait ces cas. Quand il est ajouté dans un proche avenir. – David

Répondre

33

mysql_real_escape_string n'est pas suffisant dans toutes les situations mais c'est définitivement un très bon ami.La meilleure solution utilise Prepared Statements

//example from http://php.net/manual/en/pdo.prepared-statements.php 

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)"); 
$stmt->bindParam(1, $name); 
$stmt->bindParam(2, $value); 

// insert one row 
$name = 'one'; 
$value = 1; 
$stmt->execute(); 

Aussi, ne pas oublier HTMLPurifier qui peut être utilisé pour rejeter tous les caractères non valides/suspects.

...........

Edit: Sur la base des commentaires ci-dessous, je dois poster ce lien (je l'aurais fait avant désolé pour créer de la confusion)

mysql_real_escape_string() versus Prepared Statements

cite:

mysql_real_escape_string() sujettes à le même type de problèmes affectant addslashes().

Chris Shiflett (Expert sécurité)

+3

Donnez un exemple où cela n'est pas suffisant, mais où les instructions préparées sont. – Marius

+0

@Marius: Particulièrement dans les situations où les caractères sont encodés avec UTF8, hex, etc. Si vous faites des recherches sur Internet, vous constaterez que la plupart des développeurs suggèrent d'utiliser Prepared statements sur mysql_real_escape_string si possible. Désolé pour le moment je ne me souviens pas du lien. Espérons que, désolé pour clarifie mauvais anglais :( – Sarfraz

+0

Je suis d'accord que les déclarations préparées sont supérieures, je serais également très intéressé à savoir quand mysql_real_escape_string() ne suffit pas pour échapper à des données utilisées dans une requête. – jasonbar

0

La meilleure façon d'aller serait d'utiliser Prepared Statements

+0

Lien brisé .... – Damien

+2

Il ya 2 ans, des tonnes d'autres réponses dans ce fil - est-ce vraiment important? –

5

la base de données, oui. Vous voudrez également considérer correctement l'échappement/l'encodage des données pour la sortie.

Vous devriez également considérer validant l'entrée contre ce que vous attendez qu'il soit.

Avez-vous envisagé d'utiliser prepared statements? PHP offre de nombreuses façons d'interagir avec votre base de données. La plupart sont meilleures que les fonctions mysql_ *.

PDO, MDB2 et le MySQL Improved devrait vous aider à démarrer.

+0

"Pour la base de données" - de sorte que serait alors sortie. Pas d'entrée. – symcbean

4

Dans quelles situations?

Pour les requêtes SQL, c'est génial. (Les instructions préparées sont mieux - je vote PDO pour cela - mais la fonction s'échappe juste bien.) Pour HTML et autres, ce n'est pas l'outil pour le travail - essayez un htmlspecialchars générique ou un outil plus précis comme HTML Purifier.

Pour corriger l'erreur: La seule autre couche que vous pouvez ajouter est la validation de données, par ex. confirmez que si vous placez un nombre entier dans la base de données et que vous attendez un nombre entier positif, vous renvoyez une erreur à l'utilisateur en tentant de placer un nombre entier négatif. En ce qui concerne l'intégrité des données, mysql_real_escape_string est le meilleur que vous ayez pour vous échapper (bien que, encore une fois, les instructions préparées soient un système plus propre qui évite d'échapper complètement).

+0

Encore une fois, la réponse est presque juste - mais la question était sur l'entrée - pas de sortie – symcbean

+0

Parfois, l'entrée va directement à la sortie, par exemple. ' '. – Matchu

1

Il existe deux façons, l'une consiste à utiliser des instructions préparées (comme mentionné dans d'autres réponses), mais cela ralentira votre application, car vous devez envoyer deux requêtes à la base de données au lieu d'une. Si vous pouvez vivre avec la performance réduite, alors allez-y; Les déclarations préparées rendent votre code plus joli et plus facile à traiter.

Si vous choisissez d'utiliser mysql_real_escape_string, assurez-vous d'avoir échappé à toutes les chaînes qui ne sont pas fiables. Une chaîne d'échappement (mysql_real_escape_string) est une injection SQL sécurisée. Si vous n'échappez pas à toutes les cordes, alors vous n'êtes pas en sécurité. Vous devriez vraiment combiner mysql_real_escape_string avec la validation d'entrée; vérifier qu'une variable que vous prévoyez contenir un nombre est vraiment un nombre et dans la fourchette attendue. Rappelez-vous, ne faites jamais confiance à l'utilisateur.

2

mysql_real_escape_string() est utile pour la prévention des attaques par injection SQL seulement. Cela ne vous aidera pas à empêcher les attaques par script intersite. Pour cela, vous devez utiliser htmlspecialchars() juste avant de sortir les données collectées à l'origine à partir de l'entrée de l'utilisateur.

+1

L'injection SQL est si facile à comprendre, XSS est un énorme problème en ce moment. Merci de le mentionner. –

1

Il existe différents types de "nettoyage".

mysql_real_escape_string est suffisant pour les données de base de données, mais sera toujours évalué par le navigateur lors de l'affichage s'il s'agit de HTML.

Pour supprimer le code HTML de l'entrée utilisateur, vous pouvez utiliser strip_tags.

Je suggérerais que vous envisagiez d'utiliser PDO à la place de MySQL standard, car il prend en charge les instructions préparées dès la sortie de la boîte, et celles qui gèrent l'échappement des données invalides pour vous.

10

La réponse à votre question est Non. Mysql_real_escape_string() ne convient pas à toutes les entrées utilisateur et mysql_real_escape_string() n'arrête pas toutes les injections sql. addslashes() est une autre fonction populaire à utiliser dans PHP, et il a le même problème.

code vulnérable:

mysql_query("select * from user where id=".mysql_real_escape_string($_GET[id])); 

poc exploit:

http://localhost/sql_test.php?id=1 or sleep(500) 

Le patch est d'utiliser des guillemets autour id:

mysql_query("select * from user where id='".mysql_real_escape_string($_GET[id])."'"); 

vraiment la meilleure approche est d'utiliser des requêtes paramétrées qu'un certain nombre de personnes ont souligné. Pdo fonctionne bien, adodb est une autre bibliothèque populaire pour PHP.

Si vous utilisez mysql_real_escape_string, cela ne devrait être utilisé que pour l'injection sql, et rien d'autre.Les vulnérabilités dépendent fortement de la façon dont les données sont utilisées. On devrait appliquer des mesures de sécurité fonction par fonction. Et oui, XSS est un PROBLEME TRES GRAVE. Ne pas filtrer pour html est une erreur grave qu'un pirate utilisera pour vous pw3n. Veuillez lire le xss faq.

+2

Qu'est-ce que cela a à voir avec la capacité de mysql_real_escape_string() à empêcher l'injection? Citez ou exprimez correctement votre valeur en entier. – jasonbar

+0

@jasonbar Vous pouvez le lancer, vous pouvez également oublier de le lancer. Si vous utilisez des cahiers paramétrés, vous savez que c'est toujours sûr, même si vous avez 15 singes ivres qui travaillent sur le projet. – rook

+2

droit, mais cela ne convient pas pour '' fait pas mysql_real_escape_string() * * pour échapper à des chaînes SQL. Edit: Oui, les déclarations préparées sont meilleures. – jasonbar

0

Je pensais que j'ajouterais que PHP 5.2+ a des fonctions de filtre d'entrée qui peuvent désinfecter l'entrée de l'utilisateur de différentes façons.

Voici le manual entry ainsi qu'un blog post [par Matt Butcher] à propos de pourquoi ils sont géniaux.

+0

sachez que cela ne vous aide pas contre les injections sql, mais contre XSS! – Alfred

1

Vous pouvez aussi, comme dans

function clean_input($instr) { 

    // Note that PHP performs addslashes() on GET/POST data. 
    // Avoid double escaping by checking the setting before doing this. 
    if(get_magic_quotes_gpc()) { 
     $str = stripslashes($instr); 
    } 
    return mysql_real_escape_string(strip_tags(trim($instr))); 
} 
+0

J'ai utilisé cette technique. Merci @crafter. –

Questions connexes