Domanda

Quindi sono uno sviluppatore di php un po 'stagionato e ho fatto' dannatamente la cosa 'dal 2007; tuttavia, sono ancora relativamente banale quando si tratta di proteggere le mie applicazioni. Nel modo in cui non so davvero tutto quello che so che potrei e dovrei.

Ho raccolto Protezione di applicazioni Web PHP e sto leggendo la mia procedura sta testando le cose lungo la strada. Ho alcune domande per il gruppo SO generale relativo alle query del database (principalmente sotto mysql):

Quando si creano app che inseriscono dati in un database è mysql_real_escape_string e il controllo generale (is_numeric ecc.) sui dati di input è sufficiente? Che dire di altri tipi di attacchi diversi dall'iniezione sql.

Qualcuno potrebbe spiegare le procedure memorizzate e le dichiarazioni preparate con un po 'più di informazioni di - le fai e le fai chiamate. Vorrei sapere come funzionano, quale validazione procede dietro le quinte.

Lavoro in un ambiente associato a php4 e php5 non è un'opzione per il momento. Qualcun altro è mai stato in questa posizione prima, cosa hai fatto per proteggere le tue applicazioni mentre tutti i ragazzi fantastici usano quella nuova e dolce interfaccia mysqli?

Quali sono alcune buone pratiche generali che le persone hanno trovato vantaggiose, enfasi sulla creazione di un'infrastruttura in grado di resistere agli aggiornamenti e alle possibili migrazioni (come spostare php4 in php5).

Nota: una ricerca in giro non ha trovato nulla di simile a questo che ha colpito la sicurezza di php-mysql.

È stato utile?

Soluzione

I miei consigli:

  1. elimina mysqli a favore di PDO (con driver mysql )
  2. usa dichiarazioni preparate paremeterizzate DOP

Puoi quindi fare qualcosa del tipo:

$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 );

Pro:

  1. Niente più escape manuali poiché DOP fa tutto per te!
  2. È relativamente facile cambiare improvvisamente i back-end del database.

Contro:

  • non riesco a pensare a nessuno.

Altri suggerimenti

La risposta di Javier che ha il link owasp è un buon inizio.

Ci sono alcune altre cose che puoi fare di più:

  1. Per quanto riguarda gli attacchi SQL injection, puoi scrivere una funzione che rimuoverà le comuni istruzioni SQL dall'input come " DROP " o " DELETE * DOVE " ;, in questo modo:

    * $ sqlarray = array (" DROP ", " o 1 = 1 ", " union select ", " SELECT * FROM ", " seleziona host ", " crea tabella ", " DA parte degli utenti ", " utenti DOVE "); *

    Quindi scrivi la funzione che controllerà il tuo input rispetto a questo array. Assicurati che le cose all'interno di $ sqlarray non siano input comuni dai tuoi utenti. (Non dimenticare di usare strtolower su questo, grazie lou).

  2. Non sono sicuro che memcache funzioni con PHP 4 ma puoi mettere in atto un po 'di protezione antispam con memcache consentendo solo un certo accesso IP remoto alla pagina process.php X quantità di volte nel periodo di tempo Y .

  3. I privilegi sono importanti. Se hai solo bisogno di inserire i privilegi (diciamo, elaborazione degli ordini), allora dovresti accedere al database nella pagina di processo dell'ordine con un utente che ha solo inserire e forse selezionare i privilegi. Ciò significa che anche se un'iniezione SQL è riuscita, possono solo eseguire query INSERT / SELECT e non eliminare o ristrutturare.

  4. Metti importanti file di elaborazione php in una directory come / include. Quindi non consentire a tutti gli IP di accedere a quella / include directory.

  5. Metti un MD5 salato con l'agente dell'utente + remoteip + il tuo sale nella sessione dell'utente e verifica che ad ogni caricamento della pagina sia presente l'MD5 corretto nei loro cookie.

  6. Non consentire determinate intestazioni ( http://www.owasp.org/index.php / Testing_for_HTTP_Methods_and_XST ). Non consentire intestazioni PUT (se non hai bisogno di caricare file) / TRACE / CONNECT / DELETE.

Di solito non lavoro con PHP, quindi non posso fornire consigli specifici per le tue esigenze, ma ti suggerisco di dare un'occhiata alla pagina OWASP, in particolare il rapporto sulle 10 principali vulnerabilità: http://www.owasp.org/index.php/Top_10_2007

In quella pagina, per ogni vulnerabilità ottieni un elenco delle cose che puoi fare per evitare il problema in diverse piattaforme (.Net, Java, PHP, ecc.)

Per quanto riguarda le istruzioni preparate, funzionano facendo sapere al motore di database quanti parametri e quali tipi aspettarsi durante una particolare query, usando queste informazioni il motore può capire quali caratteri fanno parte del parametro effettivo e non qualcosa che dovrebbe essere analizzato come SQL come un '(apostrofo) come parte dei dati anziché un' come delimitatore di stringa. Spiacenti, non posso fornire ulteriori informazioni mirate su PHP, ma spero che questo ti aiuti.

AFAIK, PHP / mySQL di solito non hanno query con parametri.

L'uso di sprintf () con mysql_real_escape_string () dovrebbe funzionare abbastanza bene. Se usi stringhe di formato appropriate per sprintf () (ad es. & Quot;% d " per numeri interi) dovresti essere abbastanza sicuro.

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

   <?php
    if (isset(

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

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

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

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

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

<*>
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(

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

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

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

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

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

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

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

<*>
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),

Potrei sbagliarmi, ma non dovrebbe essere sufficiente usare mysql_real_escape_string sui dati forniti dall'utente?

a meno che quando siano numeri, nel qual caso dovresti assicurarti che siano in realtà numeri usando ad esempio ctype_digit o is_numeric o sprintf (utilizzando % d o % u per forzare l'inserimento in un numero).

Inoltre, avere un utente mysql separato per i tuoi script php che può solo SELEZIONARE, INSERIRE, AGGIORNARE e CANCELLARE è probabilmente una buona idea ...


Esempio da php.net

  

Esempio n. 3 A "Best Practice" interrogazione

     

L'uso di mysql_real_escape_string () attorno a ciascuna variabile impedisce l'iniezione di SQL. Questo esempio dimostra la "migliore pratica" metodo per eseguire query su un database, indipendentemente dall'impostazione Quotes magiche.

     

La query ora verrà eseguita correttamente e gli attacchi SQL Injection non funzioneranno.

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

Utilizza le procedure memorizzate per qualsiasi attività che comporta la scrittura nel DB e usa i parametri di bind per tutte le selezioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top