is deze database query veilig genoeg?
Ik heb nog niet zo heel veel met beveiliging van database queries gedaan vandaar dat ik hier even mee bezig ben.
Ik heb de volgende classe:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
Class ZoekClass extends DatabaseClass{
private function checkString($waarde)
{
$veilig = mysql_real_escape_string((get_magic_quotes_gpc())? stripslashes($waarde): $waarde);
return $veilig;
}
public function zoekFunctie($nummer)
{
$con = $this->maakVerbinding();
$query = "SELECT naam, achternaam FROM tbl_gegevens WHERE id='".$this->checkString($nummer)."'";
//voer query uit etc....
$this->sluitVerbinding($con);
}
}
?>
Class ZoekClass extends DatabaseClass{
private function checkString($waarde)
{
$veilig = mysql_real_escape_string((get_magic_quotes_gpc())? stripslashes($waarde): $waarde);
return $veilig;
}
public function zoekFunctie($nummer)
{
$con = $this->maakVerbinding();
$query = "SELECT naam, achternaam FROM tbl_gegevens WHERE id='".$this->checkString($nummer)."'";
//voer query uit etc....
$this->sluitVerbinding($con);
}
}
?>
Nu wilde ik graag weten is de functie checkString($waarde) genoeg om ervoor te zorgen dat ik geen sqlinjectie tegen me krijg (plan is om elke variabel die ik in me query gebruik door deze functie te laten lopen)? En zo niet, wat zou ik daar dan nog meer aan kunnen doen?
Dat maakt het heel traag (10 query's = 10 keer verbinding maken en sluiten i.p.v. 1 keer)
Oja, het ziet er veilig uit
Gewijzigd op 13/11/2012 15:40:06 door TJVB tvb
TJVB tvb op 13/11/2012 15:39:37:
Waarom maak en sluit je elke keer een verbinding?
Dat maakt het heel traag (10 query's = 10 keer verbinding maken en sluiten i.p.v. 1 keer)
Oja, het ziet er veilig uit
Dat maakt het heel traag (10 query's = 10 keer verbinding maken en sluiten i.p.v. 1 keer)
Oja, het ziet er veilig uit
Ik sluit uiteraard de verbinding pas als al mijn queries zijn uitgevoerd :)
Ama saril op 13/11/2012 15:43:11:
Ik sluit uiteraard de verbinding pas als al mijn queries zijn uitgevoerd :)
Oke, want in de code die je laat zien doe je dat meteen
Gewijzigd op 13/11/2012 15:50:20 door - SanThe -
- SanThe - op 13/11/2012 15:49:24:In bovenstaand zie ik nergens dat er een query wordt uitgevoerd.
Ook al heb je het doorgestreept ter verduidelijking; ik wilde de focus graag leggen op de sqlinjectie functie. Het uitvoeren van een query, foutafhandeling en het ophalen van variabelen heb ik geen vragen over dus heb ik dat eruitgegooid anders wordt het code voorbeeld zo lang :)
Nu, misschien is dit toch met juiste moment om eens te kijken naar PDO, en hoe die omgaat met de beveiliging van user data
zie http://www.phphulp.nl/php/tutorial/overig/pdo-verbinden-met-verschillende-databases/534/prepared-statements/1368/
Gewijzigd op 13/11/2012 16:00:49 door Kris Peeters
@kris, je haalt de woorden uit me mond!
Kris Peeters op 13/11/2012 15:57:52:
Ik heb ook al verschillende keren een wrapper class gemaakt om databases aan te pakken.
Nu, misschien is dit toch met juiste moment om eens te kijken naar PDO, en hoe die omgaat met de beveiliging van user data
zie http://www.phphulp.nl/php/tutorial/overig/pdo-verbinden-met-verschillende-databases/534/prepared-statements/1368/
Nu, misschien is dit toch met juiste moment om eens te kijken naar PDO, en hoe die omgaat met de beveiliging van user data
zie http://www.phphulp.nl/php/tutorial/overig/pdo-verbinden-met-verschillende-databases/534/prepared-statements/1368/
Ah bedankt had nog niet echt aan PDO gedacht. Misschien toch is tijd om de tutorial te bekijken, bedankt.
edit---
Terzijde:
Is mijn functie checkString($waarde) wel voldoende om sql injectie tegen te gaan :P?
Ook al ga ik de class dan waarschijnlijk toch ombouwen naar PDO of mysqli ben ik toch beniewd.
Gewijzigd op 13/11/2012 16:18:50 door ama saril
mysql_real_escape_string is in principe voldoende om beschermd te zijn tegen injection. Dus ja, het lijkt me wel veilig.
Ik zou eerder voor PDO als mysqli gaan eerlijk gezegd.
Stefan van den Broek op 13/11/2012 16:48:45:
Ik zou eerder voor PDO als mysqli gaan eerlijk gezegd.
Ben op dit moment beide methoden aan het bekijken dan kan ik later beslissen welke ik ga gebruiken. Wil hoe dan ook weten hoe beide werken.
Omdat je in zowel PDO als mysqli parameters in combinatie met een prepared statement moet gebruiken, is het uiteindelijke doel van een prepared statement geheel voorbij gestreefd. Dat doel is nl. om een x aantal dezelfde queries achter elkaar sneller te laten verlopen.
Bij mij is dat 9999 van de 10.000 gewoon 1 query, dus voorlopig blijf mijn keuze nog bij mysqli omdat ik daar tenminste nog de escape mogelijk heb.
MySQLi geeft je een mysqli.query functie om normale queries uit te voeren en geeft je een mysqli.real_escape_string functie om te escapen.
PDO geeft je een pdo.query functie die dezelfde functionaliteit heeft als MySQLi::query() en mysql_query(). Maar het geeft je ook een pdo.exec functie die hetzelfde doet, alleen met een toevoeging dat het het aantal 'affected rows' returned, waardoor je dat in 1 kan doen. Daarnaast geeft PDO je pdo.quote om variabelen te escapen.
Hierin zie je precies de rede waarom ik eerder PDO zou gebruiken dan MySQLi, PDO biedt je op bijna elk vlak extra dingen, waar MySQLi gewoon een vreemde functional to object translation is.
Overigens hoeft prepared statement helemaal niet de rede te zijn dat je PDO of MySQLi moet gebruiken. Prepared statements zijn niks anders dan wat queries die je ook zelf met de mysql_* extensie kunt uitvoeren: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html
Gewijzigd op 09/12/2012 22:00:52 door Wouter J
Wouter J op 09/12/2012 21:52:28:
Ger, zowel PDO als MySQLi hoefen niet via prepared statements gebruikt te worden. Het wordt alleen heel vaak gebruikt in tutorials omdat dat het grote verschil is met de mysql_* extensie.
MySQLi geeft je een mysqli.query functie om normale queries uit te voeren en geeft je een mysqli.real_escape_string functie om te escapen.
PDO geeft je een pdo.query functie die dezelfde functionaliteit heeft als MySQLi::query() en mysql_query(). Maar het geeft je ook een pdo.exec functie die hetzelfde doet, alleen met een toevoeging dat het het aantal 'affected rows' returned, waardoor je dat in 1 kan doen. Daarnaast geeft PDO je pdo.quote om variabelen te escapen.
Hierin zie je precies de rede waarom ik eerder PDO zou gebruiken dan MySQLi, PDO biedt je op bijna elk vlak extra dingen, waar MySQLi gewoon een vreemde functional to object translation is.
Overigens hoeft prepared statement helemaal niet de rede te zijn dat je PDO of MySQLi moet gebruiken. Prepared statements zijn niks anders dan wat queries die je ook zelf met de mysql_* extensie kunt uitvoeren: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html
MySQLi geeft je een mysqli.query functie om normale queries uit te voeren en geeft je een mysqli.real_escape_string functie om te escapen.
PDO geeft je een pdo.query functie die dezelfde functionaliteit heeft als MySQLi::query() en mysql_query(). Maar het geeft je ook een pdo.exec functie die hetzelfde doet, alleen met een toevoeging dat het het aantal 'affected rows' returned, waardoor je dat in 1 kan doen. Daarnaast geeft PDO je pdo.quote om variabelen te escapen.
Hierin zie je precies de rede waarom ik eerder PDO zou gebruiken dan MySQLi, PDO biedt je op bijna elk vlak extra dingen, waar MySQLi gewoon een vreemde functional to object translation is.
Overigens hoeft prepared statement helemaal niet de rede te zijn dat je PDO of MySQLi moet gebruiken. Prepared statements zijn niks anders dan wat queries die je ook zelf met de mysql_* extensie kunt uitvoeren: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html
wat is de functie dan van pdo.quote? pdo was tochzo opgezet dat je geen variabele hoeft te escapen?
De echte reden van het opzetten van PDO kan je lezen op de php pagina:
Quote:
The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP. Each database driver that implements the PDO interface can expose database-specific features as regular extension functions. Note that you cannot perform any database functions using the PDO extension by itself; you must use a database-specific PDO driver to access a database server.
PDO provides a data-access abstraction layer, which means that, regardless of which database you're using, you use the same functions to issue queries and fetch data. PDO does not provide a database abstraction; it doesn't rewrite SQL or emulate missing features. You should use a full-blown abstraction layer if you need that facility.
PDO provides a data-access abstraction layer, which means that, regardless of which database you're using, you use the same functions to issue queries and fetch data. PDO does not provide a database abstraction; it doesn't rewrite SQL or emulate missing features. You should use a full-blown abstraction layer if you need that facility.
Het is een abstractie laag die het gebruik van verschillende databases mogelijk maakt onder dezelfde set van functies. Dus als je PDO gebruikt voor MySQL vandaag en morgen over wilt stappen naar Oracle of MSS, dan zou dat vrij simpel moeten zijn, omdat PDO het grootste deel van de verschillen al overbrugt.
Ah ok, dus ik moet nog steeds mysql_real_escape_string() gaan gebruiken?
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
// dit is veilig
$sql = "
INSERT INTO tabel (naam)
VALUES (:naam)
";
$stmt = $db->prepare($sql);
$stmt->bindParam(':naam', $_POST['naam'], PDO::PARAM_STR);
?>
// dit is veilig
$sql = "
INSERT INTO tabel (naam)
VALUES (:naam)
";
$stmt = $db->prepare($sql);
$stmt->bindParam(':naam', $_POST['naam'], PDO::PARAM_STR);
?>
Een andere zaak is: je kan nog steeds gevaarlijke sql strings maken, bv.
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
// dit is niet veilig
$sql = "
INSERT INTO tabel (naam)
VALUES ('" . $_POST['naam'] . "')
";
?>
// dit is niet veilig
$sql = "
INSERT INTO tabel (naam)
VALUES ('" . $_POST['naam'] . "')
";
?>
PDO zal op geen enkele manier injection voorkomen, bij dit laatste stuk code
Dat is duidelijk, werd al bang. Had alles met bindParam() gedaan. Had het nie leuk gevonden om nog al me variabele te moeten escapen hiervoor, bedankt in ieder geval.
Je hebt mijn reactie niet goed gelezen of niet goed begrepen. Ik heb gezegd dat je geen parameters kunt gebruiken zonder prepared statements.
Ama saril op 10/12/2012 10:45:47:
Ah ok, dus ik moet nog steeds mysql_real_escape_string() gaan gebruiken?
Dat moet je in elk geval niet doen. Dan gebruik je twee methodes door elkaar die in principe compleet los van elkaar staan. Als je prepared statements gebruikt dan kan je de input veilig verwerken met de parameters, gebruik je geen prepared statements dan kan je bijvoorbeeld de al eerder door Wouter genoemde PDO::quote() functie gebruiken.
Toevoeging op 10/12/2012 12:05:34:
Edit: waarbij ik nu zie dat je wellicht mijn eerdere reactie hebt gelezen alszijnde dat die quote functie niets met PDO te maken had. Dat was niet de strekking van het verhaal. PDO ensig is niet bedoeld om alle injecties altijd tegen te gaan, maar biedt wel bescherming via functies als quote().