Guida [PHP / SQL]Protezione dei dati - Funzioni anti SQL-Injection

Stato
Discussione chiusa ad ulteriori risposte.

SubSilence

Utente Electrum
4 Novembre 2009
276
29
85
154
Ultima modifica da un moderatore:
SQL Injection consiste in un attacco informatico che sfrutta la cattiva pratica di molti sviluppatori nel concatenare le stringhe destinate ad un database server. La concatenazione delle stringhe SQL viene solitamente associata a problemi di sicurezza e, sebbene questo sia sicuramente vero, affligge anche performance e provoca subdoli errori di runtime in relazione ai separatori numerici e delle date.

C'è da dire che sono molti i PHP Developer che non ritengono necessario mettere protezioni ai proprio script, credendo che i dati immessi dell'utente possano rispecchiare i soliti canoni alfanumerici.

Bene, ciò non sempre avviene e oggi capiremo come funziona L'injection dei dati SQL e come bloccarla!

Esempio di query:
PHP:
<?
$post=$_POST['id'];
mysql_select_db(account); 
//nel caso di metin per esempio, il database account racchiude info sugli account dei giocatori
$select=mysql_query("Select * from account where id='$post'");
?>

Diciamo che bene o male la maggior parte di voi saprà leggere e interpretare questa query.
Sappiamo che $_POST sono le variabili globali trasemme al server mediante dei form.

Se nella nostra casella di testo dovessimo inserire qualcosa che vada ben oltre semplici lettere.. ecco che le cose si complicano.

Es:
PHP:
//riprendendo il codice di prima
$post="root ' or 1!=2  ";
//ed ecco il tragico!
Purtroppo, come voi sapete, uno diverso da 2 viene vista come una condizione sempre vera e quindi l'autenticazione avverrà in un modo o nell'altro.
Nel $post è stata inserita una virgoletta (un apice per meglio intenderci), per cui la query sarà interpretata in questo modo:

PHP:
mysql_query("Select * from account where id='root' or 1!=2");

Come evitare ciò voi direte???
Beh fortunatamente PHP mette a disposizione moltissime funzioni utili nella sostituzione di determinati caratteri considerati "pericolosi" (per noi), e addirittura all'eliminazione di questi ultimi.


Incominciamo con qualcuna base:
strip_tags
La funzione strip_tags rimuove i tag HTML e PHP presenti in una stringa.
La funzione in oggetto ammette due argomenti:


  • stringa da pulire
  • tag ammessi (facoltativo)
Prendiamo come esempio:
PHP:
$testo = "<b>SubSilence</b> è un utente di <i>inforge</i>";
echo strip_tags($testo);

Il risultato sarebbe:
Codice:
SubSilence è un utente di inforge


addslashes
Questa funzione del linguaggio Php aggiunge automaticamente uno slash in presenza del carattere apice e, come abbiamo visto prima, gli apici sono le principali cause dell' SQL-Injection.

Non credo ci sia molto da spiegare.
PHP:
$stampa=" mi chiamo 'ciccio' ";
print (strip_tags($stampa)); //stamperà mi chiamo ciccio senza gli apici

Ovviamente possiamo far interagire assieme le due funzioni descritte sopra :
PHP:
$stampa="SubSilence e' un <b>PHP Developer</b>";
print (strip_tags(addslashes($stampa)));// stamperà SubSilence e un PHP Developer (e senza accento )

Oltra a queste semplici funzioni, possiamo anche sostituire all'interno di intere stringe caratteri che infastidiscono noi e che magari per PHP, sono innoqui.

ci viene in contro la funzione:
str_replace

Infatti quest'ultima prevede la sostituzione di un carattere con un altro .

es:
PHP:
$testo=" [email protected]  ";
$testo=str_replace('@','$',$testo); 
// nell'argomento della funzione mettiamo prima il carattere da sostituire, poi il carattere che andrà a sostituire il 1°, e per ultimo la stringa in cui deve avvenire la sostituzione.
print $testo; // restituirà ciao$live.it :D



Vediamo di studiare qualcosa di più complesso che raccolga quello che abbiamo appreso sino ad ora .
Una bella funzzione in php che faccia un return di tutte le funzioni:
PHP:
//Blind SQL-INJECTION Sequenze di Escape. Linee di codice utili per un anti SQL-Injection
    function anti_injection($input){
    $pulito=strip_tags(addslashes(trim($input)));
    $pulito=str_replace("'","\'",$pulito);
    $pulito=str_replace('"','\"',$pulito);
    $pulito=str_replace(';','\;',$pulito);
    $pulito=str_replace('--','\--',$pulito);
    $pulito=str_replace('+','\+',$pulito);
    $pulito=str_replace('(','\(',$pulito);
    $pulito=str_replace(')','\)',$pulito);
    $pulito=str_replace('=','\=',$pulito);
    $pulito=str_replace('>','\>',$pulito);
    $pulito=str_replace('<','\<',$pulito);
    
   
        
    
    return $pulito;
}
    //FINE BLIND
ed ecco che per avere un input pulito dovremmo solo scrivere:
PHP:
$post=$_POST['id'];
$post_pulito=anti_injection($post); //$post_pulito sarà la nostra stringa pulita e sicura


Guida in completo aggiornamento, spero di esservi stato utile
 
o_O sei dio, perchè cercavo una guida dettagliata cm questa !! :D grazie mille ^_^
 
Il post è in rilievo quindi non è necropost...

$pulito=str_replace("'","\'",$pulito);

Questo codice non mi convince, basterà mettere: \' per far diventare la prima \ un commento....
 
Essendo una guida non lo considero necropost.

Codice:
class secure{    function secureSuperGlobalGET($key)
    {
        $_GET[$key] = str_ireplace("script", "blocked", $_GET[$key]);
        $_GET[$key] = strip_tags($_GET[$key]);
        return $_GET[$key];
    }


    function secureSuperGlobalPOST($key)
    {
        $_POST[$key] = str_ireplace("script", "blocked", $_POST[$key]);
        $_POST[$key] = strip_tags($_POST[$key]);
        return $_POST[$key];
    }



    function secureVar($key){
        $key = str_ireplace("script", "blocked", $key);
        $key = strip_tags($key);
        return $key;
    }
}

Questo è completamente bunkerato da XSS sia html che javascript.

Si potrebbe anche aggiungere

Codice:
$_GET[$key] = htmlspecialchars(stripslashes($_GET[$key]));

che vi restituirà invece di:

<a href="http://www.inforge.net">Inforge.net</a> -> Inforge.net (non Inforge.net)

<a href="http://www.inforge.net">Inforge.net</a> -> <a href="http://www.inforge.net">Inforge.net</a> così com' è (se non erro, non ricordo bene).
 
Se si usano i PDOStatment l'sql injection non è piu un rischio, bisogna solo stare attenti in query pre-compilate con variabili esterne che non passano come array dopo il prepare
 
@Orcrux Carina la tua classe, ma secondo me, è meglio passare l'input per reference, è piu immediato, così si risparmia pure memora ;-)

PHP:
public static function sanitizeGeneralVar(&$var)     
{        
         $var = str_ireplace("script", "blocked", $var);        
         $var = strip_tags($var);    
}
 
Dite che le SQL injection sono cosa vecchia? voi non potete immaginare quante SQL Challenge ci siano nel web :\ siti web che seppur con codici SQL molto complicati, si riesce a prelevare l'intero DB , di certo non saranno siti governativi o bancari però...
Comunque consiglio di usare Mysqli STMT o PDO STMT, io uso quelli e poi utilizzo un htmlentities o altro per stampare i dati
 
Guida obsoleta, MySql è stato sostituito dall'estensione MySqli e il mysql risulta non più sicuro.
Per poter ovviare eventuali injection è consigliato utilizzare i prepared statement o la funzione mysqli_real_escape_string (esistono altri modi ma i più comuni e comodi sono questi).
 
  • Mi piace
Reazioni: Dazorn
Stato
Discussione chiusa ad ulteriori risposte.