SQL Injection
Se prendi l'input di un utente tramite una pagina Web e lo inserisci in un database SQL, è possibile che ti sia lasciato aperto un problema di sicurezza noto come SQL Injection. Questo capitolo ti insegnerà come evitare che ciò accada e ti aiuterà a proteggere i tuoi script e le istruzioni SQL negli script lato server come uno script PERL.
L'iniezione di solito si verifica quando chiedi un input a un utente, come il suo nome e invece di un nome ti danno un'istruzione SQL che eseguirai inconsapevolmente sul tuo database. Non fidarsi mai dei dati forniti dall'utente, elaborare questi dati solo dopo la convalida; di regola, questo viene fatto daPattern Matching.
Nell'esempio seguente, il file name è limitato ai caratteri alfanumerici più il trattino basso e ad una lunghezza compresa tra 8 e 20 caratteri (modificare queste regole secondo necessità).
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
$result = mysql_query("SELECT * FROM CUSTOMERS
WHERE name = $matches[0]");
} else {
echo "user name not accepted";
}
Per dimostrare il problema, considera questo estratto:
// supposed input
$name = "Qadir'; DELETE FROM CUSTOMERS;";
mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");
La chiamata di funzione dovrebbe recuperare un record dalla tabella CUSTOMERS in cui la colonna del nome corrisponde al nome specificato dall'utente. In circostanze normali,$nameconterrebbe solo caratteri alfanumerici e forse spazi, come la stringa ilia. Ma qui, aggiungendo una query completamente nuova a $ name, la chiamata al database si trasforma in un disastro; la query DELETE inserita rimuove tutti i record dalla tabella CUSTOMERS.
Fortunatamente, se usi MySQL, il file mysql_query()la funzione non consente lo stacking delle query o l'esecuzione di più query SQL in una singola chiamata di funzione. Se si tenta di impilare le query, la chiamata non riesce.
Tuttavia, altre estensioni di database PHP, come SQLite e PostgreSQL eseguire tranquillamente query in pila, eseguendo tutte le query fornite in una stringa e creando un serio problema di sicurezza.
Prevenire SQL injection
Puoi gestire tutti i caratteri di escape in modo intelligente nei linguaggi di scripting come PERL e PHP. L'estensione MySQL per PHP fornisce la funzionemysql_real_escape_string() per sfuggire ai caratteri di input che sono speciali per MySQL.
if (get_magic_quotes_gpc()) {
$name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");
Il dilemma LIKE
Per risolvere il dilemma LIKE, un meccanismo di escape personalizzato deve convertire i caratteri "%" e "_" forniti dall'utente in letterali. Usoaddcslashes(), una funzione che consente di specificare un intervallo di caratteri di cui eseguire l'escape.
$sub = addcslashes(mysql_real_escape_string("%str"), "%_");
// $sub == \%str\_
mysql_query("SELECT * FROM messages
WHERE subject LIKE '{$sub}%'");