Newsgroup: it.comp.www.php
Titolo: SQL injection - come evitarle...

per limitare le sql injection sto facendo una bozza in php, mi aiutate a 
migliorarla...
function sqlInjectionPrevent($string) {
$string = str_replace("'", "",$string);
$string = str_replace(";", "",$string);
$string = str_replace("--", "",$string);
$string = str_replace("/*", "",$string);
$string = str_replace("/*", "",$string);
$string = str_replace("*/", "",$string);
$string = str_replace("xp_", "",$string);
$string = str_replace("*", "",$string);
$string = str_replace("%", "",$string);
$string = str_replace("?", "",$string);
return $string;
}
non ricordo più il comando per poter fare tutte le n conversioni in una riga 
sola...

$string = str_replace("'", "",$string);
Qui sembra che tu voglia ripulire i parametri (altrimenti, per dirti, robe
come "SELECT * FROM articoli WHERE codice = '80-486'" ti diventerebbero un
"SELECT * FROM articoli WHERE codice = 80-486", e potresti trovarti magari
a cercare il codice -406 :-) ).
Ma a quel punto, intanto mysql_escape e mysql_real_escape funzionano assai
meglio, e poi... se chiedo "B'elanna", quello mi cerca "Belanna" e con una
buona probabilita' non mi trova proprio niente.
Leonardo
-- 
And where the black and corkscrew towers climb,
Lost and athirst the ragged pack abides,
Old as the aeons, trapped in tombs of time,
Sailing the tortuous temporal tides

 migliorarla...
Usa mysql_real_escape e vivi tranquillo :)
Ciao,
luigi
-- 
/
+--[Luigi Rosa]--
\
A little ignorance can go a long way... in the direction of maximum harm.


Se esiste il supporto al tuo database direi che usare i prepared
statement è la soluzione piu giusta.
Per postgresql i prepared statement sono supportati (anche se non
proprio benissimo..) .. per mysql credo di no.
GG


foreach($_POST as $param)
     mysql_query(mysql_real_escape_string($param));

_POST e _GET indistintamente.
Diciamo "mentre assemblo la query", si'. Li' comunque c'e' il rischio - ed
ho visto anche questo - di ritrovarsi magari "Bat\\\'telh" escapato di due
volte :-)
Finche' c'è una sola mano a gestire tutto il codice le cose si controllano
bene, quando si comincia a lavorare in piu' d'uno io trovo piu' pratico il
sistema Schengen: controllo alla frontiera, e dentro libera circolazione.
Oh, non che come dici tu non funzioni, anzi. A questo livello e' questione
di gusti, penso :-)
Leonardo
-- 
Linten addie toorin addie,
Linten addie toorin ee,
Linten lowrin lowrin lowrin,
The barnyards of Delgaty

ringrazio tutti per le vostre risposte.
era palese che la funzione che ho postato la uso per ripulire esclusivamente 
l'input utente...
es:
$REG=sqlInjectionPrevent($REG)
$query ="SELECT * FROM tableA WHERE cod='$REG'";
quindi non ripulisco l'intera query ma solo la parte che l'utente invia...

 ciao, f.
conosco il database e sono sicuro che non c'è nessun carattere particolare 
all'interno di quel codice.
ci sono solo lettere o numeri.
anzi rilancio la domanda... non c'è un modo per filtrare tutto tranne 
lettere e numeri in php? 

 lettere e numeri in php?
un'espressione regolare [A-Za-z0-9]

 ciao, f.
chiaro, concordo con te che nel caso generale non dev'essere utilizzato.
grazie per la completa risposta

Mi sembra che si stia un po' perdendo il senso e la via...
1- se esiste la funzione mysql_real_escape_string() e questa prende
l'id di risorsa del db c'è una ragione: tiene in conto il charset del
db dove andiamo ad operare. Per questo è più "sicuro" usare questa
invece che rifarsi una funzione ad hoc, sempre che siamo interessati a
rendere il codice portabile.
2- come dice anche la documentazione della funzione di cui sopra, i
caratteri di cui è "necessario" fare l'escape sono \x00, \n, \r, \, ',
" e \x1a  (
http://php.net/manual/en/function.mysql-real-escape-
string.php)
3- ci sono vari livelli di pulizia dell'input che vanno fatti: 3.1
controllo di presenza/tipo/validità 3.2 stripslashes() se
get_magic_quotes_gpc() 3.3 riformattazione a seconda dell'utilizzo. Mi
spiego meglio: se una variabile php è di tipo int, non c'è bisogno di
fargli nulla per inserirla in una query che prende un int. Se ho una
variabile di tipo string che rappresenta una data, magari devo
riformattarla. In quest'ottica nessuna possibile funzione generica e/o
procedura di pulizia sarà mai utile, perchè dipendente dai singoli e
specifici dati.
No?

lettere e numeri in php? 
Nel tuo caso particolare, io risolverei filtrando a monte i campi utente
in arrivo. Tu SAI che devono essere fatti in un certo modo, quindi:
<?php
	/*
		Per ogni campo utente metti il nome, e un array con
		due elementi: la sintassi che il campo deve avere e
		cosa fare se non ce l'ha.
		false = l'esecuzione si interrompe.
	*/
	if (!isset($VINCOLI)) $vincoli = array(
		'cod_art'	=> array('^[1-9][0-9]*$', ''),
		'descr'		=> array('^[A-Za-z0-9]*$', ''),
		...
	); else $vincoli = $VINCOLI;
	unset($bad);
	foreach($vincoli as $campo => $che_fare)
	{
		list($regexp, $default) = $che_fare;
		$greg	= '/' . preg_quote($regexp) . '/';
		if (isset($_GET[$campo]))
			if (!preg_match($greg, $_GET[$campo]))
				if (false === $default)
					$bad = $campo;
				else
					$_GET[$campo] = $default;
		if (isset($_POST[$campo]))
			if (!preg_match($greg, $_POST[$campo]))
				if (false === $default)
					$bad = $campo;
				else
					$_POST[$campo] = $default;
		if (isset($_REQUEST[$campo]))
			if (!preg_match($greg, $_REQUEST[$campo]))
				if (false === $default)
					$bad = $campo;
				else
					$_REQUEST[$campo] = $default;
	}
	if (isset($bad))
	{
		die("Spiacente, il campo $campo non rispetta la
sintassi");
	}
	unset($vincoli, $campo, $che_fare, $bad, $regexp, $default);
?>
Nel caso che la sintassi consentisse caratteri a rischio di SQL-injection,
allora quando vai a mettere i campi in questione "dentro" alla query, come
suggeriva Cujo, li schermi con un mysql_real_escape (o come minimo, con un
AddSlashes).
Il pezzo di PHP li' sopra lo chiami "ripulisci.php" - e lo includi ovunque
ti serva. Se definisci $VINCOLI prima dell'include, ha la precedenza:
<?php
	/*
		Ricerca nome.
		Ingresso:	nome (solo lettere non accentate e spazi)
	*/
	$VINCOLI = array(
		'nome'	=> '^[A-Za-z ]*$'
	);
	require 'ripulisci.php';
	...
?>
Leonardo S.E.&O.


futuro, 100% garantito.
Amen!


 e *NON SCRIVERE MAI* codiche che dipende da qualche caso particolare 
  Domanda da profano: hai (avete) qualche link "buono" da consultare per
imparare qualcosa in merito? Un po' ho cercato ma senza troppo successo,
e vorrei capirci qualcosina di piu' per rendermi conto se quel che
faccio e' sicuro o no.
  Grazie e un saluto,
-- 
Gianfranco Bertozzi
Linux User #183585

 Io ho trovato abbastanza illuminante il seguente libro:
  Grazie per la segnalazione. Roba che un non esperto puo' capire o si
tratta di aramaico antico scritto una lettera si e una no? ;-)
  In italiano c'e' niente?
  Grazie,


 Non si tratta di aramaico ma devi già saper programmare.
  Quello dovrei esserci, seppure a livello amatoriale. L'inglese lo
so (sufficientemente diciamo) ma preferisco leggere nella mia lingua
perche' mi viene piu' facile... sulle traduzioni concordo in pieno. Vedo
di ordinarlo allora, grazie della dritta.
  Saluti,


 (ROTFL) "un caso di studio".
SBAM!


Anche perchè quanti *programmatori* hai visto in una università? :)