SQL Injection

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Rob Meijeren

Rob Meijeren

21/12/2011 16:37:15
Quote Anchor link
hallo allemaal,

ik heb een probleem. ik heb een formulier waar ik via de get methode gegevens ophaal. alleen is deze gevoelig voor sql injectie. zoals hieronder te zien is gebruik ik mysql_real_escape_string strip_tags en htmlentities maar toch is het mogelijk om mijn database op te vragen. kan iemand mij helpen?

Groeten,

Rob

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php

$Serie
= mysql_real_escape_string(strip_tags(htmlentities($_GET["Serie"])));
        $sql = mysql_real_escape_string(strip_tags(htmlentities("Select DISTINCT Seizoen From ". $Serie ." ORDER BY Seizoen")));

?>
 
PHP hulp

PHP hulp

22/12/2024 16:51:53
 
Wouter J

Wouter J

21/12/2011 16:49:07
Quote Anchor link
- Mysql_real_escape_string is genoeg, al die andere functies zijn niet nodig. Gebruik htmlentities bij het ophalen uit de database (dus na een query) en bij het maken van een query.
- Onnodig variabelen kopiëren kost tijd, gebruik gewoon de $_GET var + mysql_real_escape_string in je query.
- Mysql_real_escape_string is alleen nodig voor stings, niet voor getallen enz. Ook is het overbodig en misschien zelfs fout om het rond een query te zetten. Dit geld ook voor alle andere functies.

Wat bedoel je met 'maar toch is het mogelijk om mijn database op te vragen.'? Want dat kan zo namelijk niet meer...
 
Bartje Jansen

Bartje Jansen

25/12/2011 14:17:21
Quote Anchor link
Wanneer je mysql_real_escape_string() gebruikt, ben je VERPLICHT (!!!!) om óók quotes rondom de waardes te gebruiken. Doe je dat niet, dan is jouw code nog steeds gevoelig voor SQL-injection. Dynamische tabel- en kolomnamen kun je dus niet gebruiken, daar kun je namelijk geen quotes gebruiken.

Zoek de verschillen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
$_POST
['input'] = '1 or 1=1';

// zo lek als een mandje:
$query = "SELECT * FROM tabel WHERE id = ".mysql_real_escape_string($_POST['input']);
echo $query;

// veilig
$query = "SELECT * FROM tabel WHERE id = '".mysql_real_escape_string($_POST['input'])."'";
echo $query;
?>


Ps. Wouter J slaat hier en daar de plank mis, er is meer nodig om veilig te werken.
 
Wouter J

Wouter J

25/12/2011 16:14:58
Quote Anchor link
@Bartje, hier nogmaals hetzelfde bericht als ik bij je andere bericht heb geschreven: linkje

Verder is je query niet goed, selecteer gewoon wat je wilt en niet * gebruiken.

Ook moet je bij getallen helemaal geen mysql_real_escape_string gebruiken. Bij getallen moet je gaan typecasten om je query veilig te maken.

En voordat we elkaar hier allemaal gaan uitmaken voor 'slecht' en 'hier en daar de plank mis slaan' wens ik je nog een vrolijk en gezegend kerstfeest toe.
 
- SanThe -

- SanThe -

25/12/2011 17:35:25
Quote Anchor link
Ik denk eigenlijk dat jullie beiden (Bartje en Wouter) gelijk hebben.

Wat Bartje aanstipt is gewoon een feit. In zijn voorbeeld is mysql_real_escape_string($_POST['input']) zonder quotes er omheen gewoon lek.

En wat Wouter zegt (int) $_POST['input'] is in orde.

Wel een interessante discussie.
Gewijzigd op 25/12/2011 17:36:48 door - SanThe -
 
Bartje Jansen

Bartje Jansen

29/12/2011 18:25:06
Quote Anchor link
Wouter J op 25/12/2011 16:14:58:
Verder is je query niet goed, selecteer gewoon wat je wilt en niet * gebruiken.

De query is uitstekend, zit geen enkele fout in. Dat het gebruik van een * niet is aan te raden voor een productie systeem, dat is logisch. Maar voor een lullig voorbeeldje voldoet het uitstekend.

Quote:
Ook moet je bij getallen helemaal geen mysql_real_escape_string gebruiken.

Voor PHP ziet de hele wereld eruit als een string, dat is dus geen argument.

Quote:
Bij getallen moet je gaan typecasten om je query veilig te maken.
En dat zou SQL injection tegen moeten gaan? SQL injection ga je tegen door de database aan het werk te zetten, die moet bekijken of de userinput een correct datatype heeft. mysql_real_escape_string() is dus al een lapmiddel, je hebt eigenlijk prepared statements nodig. Dan kun je ook in het logboek van jouw database zien welke queries veilig zijn en waar nog risico's zitten.

Met MySQL is het alleen een hoop geknutsel om met prepared statements te werken, je hebt er extra code voor nodig. Zowel met PDO als MySQLi is het behelpen, dit houdt vele programmeurs tegen, en dat is jammer.

Kijk ook eens hoe PHP dat voor PostgreSQL heeft opgelost, met pg_query_params() heb je maar één functie nodig om de query op te sturen en de userinput op een veilige manier mee te geven. Ook het fetchen blijft lekker eenvoudig, heb je geen extra code voor nodig. (zelfs nog minder code dan voor fetchen van een MySQL-resultaat)

Kortom, laat de database het werk voor jou doen, hoef jij niet meer aan te prutsen met typecasting e.d. Kun je leuke dingen gaan doen :-)
 
Marco PHPJunky

Marco PHPJunky

29/12/2011 18:45:40
Quote Anchor link
@bartje
Wouter heeft zeer zeker gelijk wat betreft de * die kan je beter nooit gebruiken...
ook heeft hij gelijk wat betreft controleren van int met mysql_real_escape_string

Daarbij ben ik van mening dat mysql_real_escape_sting() enkel en alleen voor string waarde gebruikt dient te worden en niet voor Int waardes omdat dit gewoon geen zin heeft omdat je een int op een andere manier checkt...

Daarnaast is phpmyadmin niet de betrouwbaarste en stabielste database (tool) die er bestaad er gebeuren soms hele rare dingen bij hun...

Maar je kan de input van een user/gebruiker beter een keer teveel checken dan te weining en de input moeten nou eenmaal in goede banen geleid worden..
vertrouw NOOIT op de correctheid van de input de gebruiker
Vertrouw NOOIT op volledige correctheid van de input van programmeurs/bouwers..
Vertrouw Niemand dus check en check alles..
 
Wouter J

Wouter J

29/12/2011 22:57:18
Quote Anchor link
Bartje Jansen:
Kortom, laat de database het werk voor jou doen, hoef jij niet meer aan te prutsen met typecasting e.d. Kun je leuke dingen gaan doen :-)

Om met iets positiefs te beginnen. Hier ben ik het volledig mee eens. Prepared statements zijn het best te gebruiken, zelf script ik ook altijd met PDO want MySQLi heeft wat rare fratsen met prepared statements.

Bartje Jansen:
Voor PHP ziet de hele wereld eruit als een string, dat is dus geen argument.

Hier sla je helaas wel de plank mis.
Als gebruiker denk je dat alles eruit ziet als een string, maar het is niet zo. Omdat de webdevelopers wel eens de mist in gaan keurt PHP '212' ook goed en zet het zelf om naar 212. Het is niet zo dat PHP alles leest in strings.
Precies zoals dat 0 gezien wordt als false en elke andere waarde als true. Dat is ook zoiets dat in PHP is toegevoegd voor het gemak van de gebruiker en dat is niet zoiets dat hoort in PHP.
PHP is eigenlijk een totaal verkeerde taal. Het is wel leuk allemaal, maar zo soepel. Alles voor het gemak van de developer, maar eigenlijk zijn veel PHP scripts logisch gezien fout omdat PHP zo gemakkelijk omgaat met de regels. Nee, probeer maar eens in echte stricte talen dit soort code uit, je krijg dan schermen vol met errors...

@Marco en vertrouw ook niet jezelf. Zeg niet ik ben de enige die die variabele beheert dus daar hoeft geen real_escape_string over, want dan zit je fout. Je moet alles controleren.
Ik heb bij update/delete queries zelfs altijd een extra functie die kijkt of ik niet ergens een where vergeten ben, want ik wil mezelf checken en zeker weten dat ik niks fout doe.
 
Marco PHPJunky

Marco PHPJunky

30/12/2011 01:42:39
Quote Anchor link
@Wouter

Dat zeg ik ook en wilde ik ook totaal niet zeggen..
Ik wilde ermee zeggen dat je juist alles moet controleren..

Quote:
Je moet alles controleren.


Dat is juist wat ik zeg...
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.