Question

Je suis donc un développeur php un peu expérimenté et je fais ce qui est sacré depuis 2007; Cependant, je suis encore relativement content de sécuriser mes applications. De la même manière que je ne sais pas vraiment tout ce que je sais, je pourrais et devrais.

J'ai récupéré Sécurisation des applications Web PHP et je lis mon chemin. il teste les choses en cours de route. J'ai quelques questions pour le groupe général SO sur les requêtes dans les bases de données (principalement sous mysql):

Lors de la création d'applications qui mettent des données dans une base de données, mysql_real_escape_string et une vérification générale (is_numeric, etc.) des données d'entrée suffisent? Qu'en est-il des autres types d'attaques différents de l'injection SQL.

Quelqu'un pourrait-il expliquer les procédures stockées et les instructions préparées avec un peu plus d'informations que celles que vous créez et appelez-les? Je voudrais savoir comment ils fonctionnent, quelle validation se passe dans les coulisses.

Je travaille dans un environnement lié à php4 et php5 n’est pas une option pour le moment. Quelqu'un d'autre a-t-il déjà occupé ce poste auparavant, qu'avez-vous fait pour sécuriser vos applications pendant que tous les enfants cools utilisent cette nouvelle interface mysqli?

Quelles sont certaines des bonnes pratiques générales que les gens ont trouvées avantageuses, en mettant l'accent sur la création d'une infrastructure capable de résister aux mises à niveau et aux migrations possibles (comme le déplacement de php4 vers php5).

Note: avoir fait une recherche dans les environs, je n'ai rien trouvé de tel qui ait touché la sécurité php-mysql.

Était-ce utile?

La solution

Mes recommandations:

  1. abandonne mysqli en faveur de PDO (avec le pilote mysql) )
  2. utiliser des instructions préparées paramétrisées PDO

Vous pouvez ensuite faire quelque chose comme:

$pdo_obj = new PDO( 'mysql:server=localhost; dbname=mydatabase', 
                    $dbusername, $dbpassword );

$sql = 'SELECT column FROM table WHERE condition=:condition';
$params = array( ':condition' => 1 );

$statement = $pdo_obj->prepare( $sql, 
    array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) );
$statement->execute( $params );
$result = $statement->fetchAll( PDO::FETCH_ASSOC );

Pros:

  1. Plus d’échappement manuel puisque PDO fait tout pour vous!
  2. Il est relativement facile de changer subitement de base de données.

CON:

  • Je ne peux en penser à personne.

Autres conseils

La réponse de Javier qui a le lien owasp est un bon début.

Il y a encore quelques choses à faire:

  1. En ce qui concerne les attaques par injection SQL, vous pouvez écrire une fonction qui supprimera les instructions SQL courantes de l'entrée, comme par exemple " DROP " ou "SUPPRIMER * O", comme ceci:

    * $ sqlarray = array ("DROP", "or 1 = 1", "union select", "SELECT * FROM", "select host", "create table", "create table", " FROM utilisateurs "," utilisateurs WHERE "); *

    Ensuite, écrivez la fonction qui vérifiera votre entrée par rapport à ce tableau. Assurez-vous que tout ce qui se trouve dans $ sqlarray ne sera pas commun à vos utilisateurs. (N'oubliez pas d'utiliser strtolower pour cela, merci lou).

  2. Je ne suis pas sûr que memcache fonctionne avec PHP 4, mais vous pouvez mettre en place une protection anti-spam avec memcache en permettant uniquement un certain accès IP distant à la page process.php X nombre de fois dans la période Y .

  3. Les privilèges sont importants. Si vous n'avez besoin que de privilèges d'insertion (par exemple, traitement de la commande), vous devez vous connecter à la base de données sur la page de traitement de la commande avec un utilisateur disposant uniquement des privilèges d'insertion et éventuellement de sélection. Cela signifie que même si une injection SQL aboutissait, ils ne pourraient exécuter que des requêtes INSERT / SELECT et non supprimer ou restructurer.

  4. Placez les fichiers de traitement php importants dans un répertoire tel que / include. Puis interdire à toutes les adresses IP d'accéder à ce répertoire / include.

  5. Placez un MD5 salé avec l'agent de l'utilisateur + le remoteip + votre sel dans la session de l'utilisateur et vérifiez-le à chaque chargement de page que le MD5 correct se trouve dans son cookie.

  6. Interdire certains en-têtes ( http://www.owasp.org/index.php / Testing_for_HTTP_Methods_and_XST ). Interdire les en-têtes PUT (si vous n'avez pas besoin de télécharger des fichiers) / TRACE / CONNECT / DELETE.

Je ne travaille généralement pas avec PHP, je ne peux donc pas vous fournir de conseils spécifiques, mais je vous suggère de consulter la page OWASP, en particulier le rapport sur les 10 principales vulnérabilités: http://www.owasp.org/index.php/Top_10_2007

Dans cette page, vous obtenez pour chaque vulnérabilité une liste des mesures à prendre pour éviter le problème sur différentes plateformes (.Net, Java, PHP, etc.)

En ce qui concerne les instructions préparées, elles permettent au moteur de base de données de savoir combien de paramètres et quels types sont attendus lors d’une requête donnée. Le moteur peut ainsi comprendre quels caractères font partie du paramètre réel et non quelque chose qui devrait être analysé en tant que SQL comme une '(apostrophe) dans le cadre des données au lieu d'un' comme un délimiteur de chaîne. Désolé, je ne peux pas fournir plus d'informations ciblées sur PHP, mais j'espère que cela aidera.

Pour autant que je sache, PHP / MySQL n'a généralement pas de requêtes paramétrées.

Utiliser sprintf () avec mysql_real_escape_string () devrait plutôt bien fonctionner. Si vous utilisez des chaînes de format appropriées pour sprintf () (par exemple, "% d" pour les entiers), vous devriez être assez sûr.

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

   <?php
    if (isset(

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['product_name']) && isset(

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['product_description']) && isset(

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['user_id'])) { // Connect $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password'); if(!is_resource($link)) { echo "Failed to connect to the server\n"; // ... log the error properly } else { // Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON. if(get_magic_quotes_gpc()) { $product_name = stripslashes(

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['product_name']); $product_description = stripslashes(

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['product_description']); } else { $product_name =

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['product_name']; $product_description =

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['product_description']; } // Make a safe query $query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)", mysql_real_escape_string($product_name, $link), mysql_real_escape_string($product_description, $link),

Je me trompe peut-être, mais cela ne devrait pas être suffisant d'utiliser mysql_real_escape_string sur les données fournies par l'utilisateur?

Sauf s'il s'agit de nombres, auquel cas vous devez vous assurer qu'ils le sont bien en utilisant par exemple ctype_digit ou is_numeric ou sprintf (en utilisant % d ou % u pour forcer la saisie d'un nombre).

Aussi, avoir un utilisateur mysql serarate pour vos scripts php qui ne peut que SELECT, INSERT, UPDATE et DELETE est probablement une bonne idée ...

Exemple tiré de php.net

  

Exemple # 3 A "Meilleure pratique" requête

     

L'utilisation de mysql_real_escape_string () autour de chaque variable empêche l'injection SQL. Cet exemple illustre la "meilleure pratique". méthode d’interrogation d’une base de données, indépendante du paramètre Magic Quotes.

     

La requête va maintenant s'exécuter correctement et les attaques par injection SQL ne fonctionneront pas.

<*>
POST['user_id']); mysql_query($query, $link); if (mysql_affected_rows($link) > 0) { echo "Product inserted\n"; } } } else { echo "Fill the form properly\n"; }

Utilisez des procédures stockées pour toute activité impliquant l'écriture dans la base de données et utilisez des paramètres de liaison pour toutes les sélections.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top