Newsgroup: it.comp.www.php
Titolo: interrogazione DB

In una query del genere: 
 
$query = @mysql_query("SELECT * FROM magazzino WHERE marca='$mar' AND sezione='$cat' LIMIT ".$inizio.",".$max) or die (mysql_error()); 
 
mi servirebbe sapere quale valore devo dare alla variabile $cat se voglio ottenere tutti i valori del campo "sezione". 
 
grazieeee 


Nessuno. Devi togliere il selettore "AND sezione='$cat'".
 
Sarebbe anche cosa saggia togliere quell' @ davanti a mysql_query e non usare
mysql_query ma piuttosto PDO.
 
Leonardo
 
-- 
Were I Glenallan's Earl this tide, and were you Roland Cheyne,
My spur would be in my horse's side, the bridle upon his mane.
If they hae twenty thousand blades and we twice ten times ten,
Yet they hae but their tartan plaids, and we're mail-clad men.

 usare mysql_query ma piuttosto PDO.
 
E anche fare l'escape corretto di eventuali valori non validati in input.

 
 
mi serviva lasciare il SELECT così perchè prendo con GET la variabile $cat e se questa non esiste mi deve far selezionare tutti i campi. 
per ora ho risolto con un IF (isset) e due SELECT diversi.
mi spieghi bene la faccenda del @, del PDO e dell'escape?
grazie :D

mi spieghi bene la faccenda del @, del PDO e dell'escape?
 
Eh, sarebbe un'azienda di nulla :-D ... dài un'occhiata al manuale, da' retta.
Vedrai che mi rammenti.
 
Sul perche' non e' bene prendere $cat con GET senza escaping, se io in $cat ti
ci metto "' OR 1=1 --" (senza le doppie virgolette), la query ti diventerebbe
 
	SELECT * FROM magazzino WHERE marca='$mar'
		AND sezione='' OR 1=1 --' LIMIT ...
 
e siccome -- e' un commento, e' come se la query fosse
 
	SELECT * FROM magazzino WHERE marca='$mar'
		AND sezione='' OR 1=1
 
e siccome 1=1 e' true e qualsiasi cosa in OR con true e' true, quello t'esegue
 
	SELECT * FROM magazzino
 
qualsiasi sia $mar.
 
In casi piu' complicati e' possibile eseguire altri comandi, ed anche alterare
il contenuto del database.
 
Nei sistemi di autenticazione che commettono quest'errore, "' OR 1=1 --" e' un
utente valido (o una pass valida) e spesso ha i diritti di amministratore. Non
vuoi che questo succeda a te.
 
PDO e' una alternativa alle funzioni mysql_* (che fra un po' SPARIRANNO, ergo,
imparale se vuoi, ma ti suggerisco di no), che consente di ridurre questo tipo
di rischio con piu' facilita'.


perfetto, grazie delle delucidazioni, cercherò di leggere il manuale ;)

il contenuto del database.
 
Ma gia' che ci sono, visto che almeno un lurker mi ha spiegato per email che
"al massimo cosi' mi leggo cosa c'e' nel magazzino", e a quanto pare gli par
cosa da nulla, allora ne racconto una meglio.
 
Diciamo che ci sia una query SQL vulnerabile della forma
 
	SELECT MIN(1) AS x FROM test WHERE cat = '$cat'
 
...a questa query si puo' solo far ritornare una riga, con un solo campo, e,
in quel campo, c'e' sempre e solo uno. Non si possono modificare tabelle ne'
schema e non si possono eseguire statement multipli. Sicche', no problem.
 
Right?
 
Wrong :-)
 
Diciamo che mi interessi il valore del campo "password" di quella riga della
tabella "users" il cui campo "name" vale "Administrator", cosi', per dare un
nome a caso.
 
Io posso mettere qualsiasi cosa al posto di $cat, per cui posso eseguire una
qualunque query purche' cominci per
 
	SELECT MIN(1) AS x FROM test WHERE cat = '...
 
In particolare c'e' un caso in cui posso eseguire DUE query: usando UNION.
 
Pero' il codice PHP legge solo la prima riga, per cui, anche se eseguo (e se
funzionasse; ma non funziona)
 
	SELECT MIN(1) AS x FROM test WHERE cat = '' OR 1=1
	UNION SELECT password FROM users WHERE name='Administrator'
 
vengono tornate due righe, e la seconda contiene il bonus, ma io posso avere
indietro solo la prima... beh, no: se aggiungo un ORDER opportuno, c'e' caso
che riesca nell'intento.
 
Ma diciamo che non posso fare nemmeno questo perche' il PHP, in realta', non
mi ritorna quel valore; lo usa lui internamente, e siccome e' numerico, ecco
che QUASI qualunque password di Administrator viene considerata "0". Vedendo
il risultato di "0", non so se la password e' "pippo" o "puppa".
 
Quindi sono al sicuro...
 
...o anche no. C'e' un altro "canale occulto" che posso usare. Il tempo. Una
query come questa
 
   ... UNION SELECT CASE WHEN SUBSTRING(password,1,1) = 'A' THEN
   BENCHMARK(400000000, 'AES_ENCRYPT(NOW(),NOW())') ELSE 0 END
   FROM users WHERE name = 'Administrator'
 
ritorna zero comunque - pero', se la password comincia per A, ci impiega tre
secondi per ritornarlo. O un secondo, o dieci. Se inizia per qualunque altra
lettera, ritorna istantaneamente.
 
Quindi io sparo 255 query, che mi impiegano 5254 millisecondi in tutto, e in
cinque punto due secondi posso sapere la prima lettera della password. E' la
lettera corrispondente alla query piu' lenta.
 
Dopo dieci secondi, so la seconda lettera della password.
 
Nel giro di un minuto, e per tutta anomalia c'e' un carico anomalo per un 60
secondi (con MySQL 5.0.12+, c'e' la funzione SLEEP(5) che funziona meglio, e
non da' nemmeno carico anomalo...), la password di Administrator e' mia - se
era archiviata in plain text, certo. O qualsiasi altro dato del database, se
so dove cercare.
 
E se uno usa una piattaforma standard, al 99% io lo so.
 
Ed ecco perche', caro il mi' lurker, l'accesso ad una tabella insignificante
e schifata da tutti *non e'* quel problema da nulla che potrebbe sembrare. O
almeno, non e' detto.
