SQL injection gaat niet alleen om het droppen van tables, het gaat ook om het vergaren van data die niet rechtmatig is. met een '\' OR 1 OR \'' kun je al veel doen. Bovendien, het is gewoon fout om zomaar user data in een query te stoppen, de 'maar het werkt toch'-beredenering is natuurlijk een van de meest foutequote:Op donderdag 1 september 2005 20:01 schreef Swetsenegger het volgende:
[..]
Ik heb het geprobeerd te injecten, en dat lukt echt niet zolang je je data in je query maar tussen ' zet.
En gewoon is_numeric volstaat natuurlijk ook
want laten we het nu eens proberen te injecten
we maken '""DROP TABLE tabel" van de id= in de url.
wat krijgen we dan?
$query="SELECT * FROM table WHERE id=''"DROP TABLE table";
geeft een prachtige sql fout. Maar goed, is_numeric of addslashes
en ow... natuurlijk nooit backticks gebruiken in je query
En dan ook niet mijn redenering. Ik heb voldoende gelezen over injection om te weten dat mijn methode veilig is.quote:Op donderdag 1 september 2005 20:46 schreef JeRa het volgende:
[..]
SQL injection gaat niet alleen om het droppen van tables, het gaat ook om het vergaren van data die niet rechtmatig is. met een '\' OR 1 OR \'' kun je al veel doen. Bovendien, het is gewoon fout om zomaar user data in een query te stoppen, de 'maar het werkt toch'-beredenering is natuurlijk een van de meest foute![]()
Je hoort mij niet zeggen dat dat niet zo is. Als een user wat vreemds in de url propt krijgt hij gewoon netjes een melding dat hij dat niet moet doen.quote:een query behoort altijd te werken, ook als de user iets vreemds opgeeft (intval levert in het geval van ongeldige user input gewoon 0 op).
Joh....quote:Als er tekst van de user moet worden geinserted in een query, behoor je altijd mysql_real_escape_string te gebruiken. Gebruik je tekst van de user in een query met LIKE, zorg er dan ook voor dat de procenten (%) en de underscores (_) ge-escaped worden want die hebben een speciale betekenis in queries.
En dat doe ik ook. Ik denk dat niemand met 100% zekerheid kan stellen dat zijn script veilig is, maar zolang ik numerieke gets check of ze ook daadwerkelijk numeriek zijn (lijkt me een stuk veiliger dan intval, welke een string gewoon interpreteert als integer en derhalve wel eens meer informatie uit je tabel kan trekken dan voor de user bedoeld was) en ASCII gets gewoon escape is er niets aan de hand. PLUS het feit dat ik mijn data altijd tussen quotes zet in een query, maakt injection redelijk lastig.quote:Dit soort basics zorgen ervoor dat je vanaf het begin een script maakt dat veilig is; zolang je er maar over nadenkt
backticks zijn een workaround voor beroerde database modellen, waarbij je reserved names als veldnamen gebruikt. Dat moet je gewoon niet doen, en derhalve zijn backticks volledig overbodig. Wanneer je je aanleert geen backticks te gebruiken, zal je dus ook geen reserved words als veldnamen nemen, waardoor je beter hebt nagedacht over je databasde modelquote:Natúúrlijk nooit backticks gebruiken, want de verdomd goede reden om dat niet te doen is...?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <?php function stream($kamer,$user) { ob_implicit_flush(); $result=runquery("SELECT * FROM $kamer ORDER BY ID DESC LIMIT 0,1"); $row=mysql_fetch_array($result); $last_ID=$row[ID]; $res=runquery("SELECT * FROM chat_times WHERE chatroom='$kamer' AND username='$user'"); $ro=mysql_fetch_array($res); $their_time=$ro[said_time]; $now=time(); $diff=$now-$their_time; $iotime=600; #idle out time while($diff < $iotime && !connection_aborted()){ $result=runquery("SELECT * FROM $kamer ORDER BY ID DESC LIMIT 0,1"); $row=mysql_fetch_array($result); $new_ID=$row[ID]; while($new_ID>$last_ID){ $i=$last_ID+1; $result2=runquery("SELECT * FROM $kamer WHERE ID='$i'"); $row2=mysql_fetch_array($result2); $sentence=parse_sentence($row2[sentence],$row2[systemmess]); $result3=runquery("SELECT * FROM chat_leden WHERE username='$row2[username]'"); $row3=mysql_fetch_array($result3); $line=lineformat($row2[ID], $row[datum], $row3[access_level], $row2[chatname], $row2[kleur], $sentence, $row2[adminmess], $row2[username]); print ($line); $line=""; $last_ID++; } if($diff%25<=1){ $idleline='<!---->'; print ($idleline); } sleep(1); $rest=runquery("SELECT * FROM chat_times WHERE chatroom='$kamer' AND username='$user'"); $ro=mysql_fetch_array($rest); $their_time=$ro[said_time]; $now=time(); $diff=$now-$their_time; } $line='<b style="color:#ffffff">Je hebt te lang niets gezegd. Klik <a href="display.php?kamer='.$kam.'">HIER</a> om de kamer te herladen</b><script>scroll();</script>'; print ($line); } ?> |
Als je checks op je variabele doet, zie ik dat toch echt niet terug als je in een query direct een $_GET element gooit. Mijn opvatting is dat je mensen niet moet aanleren om $_POST of $_GET te vertrouwen, maar dus eerst de user input te validerenquote:Op donderdag 1 september 2005 21:10 schreef Swetsenegger het volgende:
[..]
En dan ook niet mijn redenering. Ik heb voldoende gelezen over injection om te weten dat mijn methode veilig is.
Het database model heeft hier dus helemaal niéts mee te maken, hoogstens de naamgeving. En er zijn voorbeelden van database servers die namen als 'e-mail' toestaan maar dit in een query zien als een berekening (vanwege het minteken) en daarop stoppen. In dat geval zijn backticks benodigd (hoewel de meeste DB servers het nu goed doen).quote:[..]
backticks zijn een workaround voor beroerde database modellen, waarbij je reserved names als veldnamen gebruikt. Dat moet je gewoon niet doen, en derhalve zijn backticks volledig overbodig. Wanneer je je aanleert geen backticks te gebruiken, zal je dus ook geen reserved words als veldnamen nemen, waardoor je beter hebt nagedacht over je databasde model
quote:Op donderdag 1 september 2005 21:17 schreef JeRa het volgende:
[..]
Als je checks op je variabele doet, zie ik dat toch echt niet terug als je in een query direct een $_GET element gooit. Mijn opvatting is dat je mensen niet moet aanleren om $_POST of $_GET te vertrouwen, maar dus eerst de user input te valideren
quote:Op donderdag 1 september 2005 21:10 schreef Swetsenegger het volgende:
In dit geval gaf ik een antwoord op een vraag. Ik hoef toch geen veiligheid tutorial te schrijven bij dit soort vragen?
Dat is net zoiets als een probleem in Windows oplossen door te zeggen dat je Windows opnieuw moet installeren. Mijn opvatting is dat als het op een andere, betere manier kan, je als scripter die er wat meer verstand van heeft de morele verplichting hebt die zo goed mogelijk te meldenquote:
Bullshit. Porbeer de query welke ik hierboven gaf maar te injecten. Maak maar een voorbeeld scriptje, pleur 'm online en wij gaan met z'n allen proberen 'm te injecten. Safe genoeg voor huis tuin en keuken gebruik.quote:Op donderdag 1 september 2005 21:36 schreef JeRa het volgende:
[..]
Dat is net zoiets als een probleem in Windows oplossen door te zeggen dat je Windows opnieuw moet installeren.
Ja met die intval is dat risico zeer zeker aanwezig inderdaad. Tenslotte verkomt dat op geen enkele manier dat er data uit de database getrokken kan worden welke niet voor de persoon bedoelt isquote:Mijn opvatting is dat als het op een andere, betere manier kan, je als scripter die er wat meer verstand van heeft de morele verplichting hebt die zo goed mogelijk te meldenanders heb je over twee weken een nieuw topic, 'mijn site is gehacked!11!1'
Je mist het punt. SQL injection hoeft niet altijd schadelijk te zijn, maar als jij nou een voorbeeld geeft waarbij injection mogelijk is en een gebruiker gaat dezelfde methode ook voor andere (mogeiljk gevaarlijkere) queries gebruiken, dan zijn de poppen aan het dansen. Beter gebruik je één uniforme methode om dit soort dingen af te handelen, dan de ene keer het wel te doen en de andere keer niet onder het mom van 'het werkt toch';quote:Op donderdag 1 september 2005 21:49 schreef Swetsenegger het volgende:
[..]
Bullshit. Porbeer de query welke ik hierboven gaf maar te injecten. Maak maar een voorbeeld scriptje, pleur 'm online en wij gaan met z'n allen proberen 'm te injecten. Safe genoeg voor huis tuin en keuken gebruik.
In dit geval was de intval() bedoeld om er zeker van te zijn dat het een numeriek type is wat in de query gezet wordt, op het moment dat je geen intval gebruikt en je staat toe dat er tekst in een gevaarlijke query komt gaat het wellicht nog erger fout. Ik ben het helemaal met je eens dat de user input gevalideerd moet worden, maar validatie is véél makkelijker als je weet met wat voor type variabele je te maken hebt - bovendien is bij een slechte validatie de kans op injection dan verkleind aangezien je zeker weet dat de user input in het type staat dat in de query mág staan.quote:Ja met die intval is dat risico zeer zeker aanwezig inderdaad. Tenslotte verkomt dat op geen enkele manier dat er data uit de database getrokken kan worden welke niet voor de persoon bedoelt is
1 2 3 | <?php $query = 'SELECT * FROM `database` WHERE `id` = ' . $id; ?> |
Dan krijg je inderdaad onzin.quote:Op donderdag 1 september 2005 20:01 schreef Swetsenegger het volgende:
Ik heb het geprobeerd te injecten, en dat lukt echt niet zolang je je data in je query maar tussen ' zet.
En gewoon is_numeric volstaat natuurlijk ook
want laten we het nu eens proberen te injecten
we maken '""DROP TABLE tabel" van de id= in de url.
wat krijgen we dan?
1 2 3 4 5 6 7 | <?php # stel $_GET[...] = "0 UNION SELECT * FROM `auth`" $id = $_GET[...]; $query = 'SELECT * FROM `database` WHERE `id` = ' . $id; # $query is nu: "SELECT * FROM `database` WHERE `id` = 0 UNION SELECT * FROM `auth`" ?> |
practise what you preachquote:Op donderdag 1 september 2005 22:01 schreef JeRa het volgende:
In dit geval was de intval() bedoeld om er zeker van te zijn dat het een numeriek type is wat in de query gezet wordt, op het moment dat je geen intval gebruikt en je staat toe dat er tekst in een gevaarlijke query komt gaat het wellicht nog erger fout. Ik ben het helemaal met je eens dat de user input gevalideerd moet worden, maar validatie is véél makkelijker als je weet met wat voor type variabele je te maken hebt - bovendien is bij een slechte validatie de kans op injection dan verkleind aangezien je zeker weet dat de user input in het type staat dat in de query mág staan.
Kortom, je antwoord was net zo onveilig en onvolledig dan dat van mij. Sterker nog, jij bracht het nog als 'veilig'. En in MIJN opinie is geen veiligheid nog altijd beter dan schijn veiligheid.quote:Mijn opvatting is dat als het op een andere, betere manier kan, je als scripter die er wat meer verstand van heeft de morele verplichting hebt die zo goed mogelijk te melden
Waar bracht ik het als veilig?quote:Op donderdag 1 september 2005 22:10 schreef Swetsenegger het volgende:
Kortom, je antwoord was net zo onveilig en onvolledig dan dat van mij. Sterker nog, jij bracht het nog als 'veilig'. En in MIJN opinie is geen veiligheid nog altijd beter dan schijn veiligheid.
Nee daar ga je de fout al inquote:Op donderdag 1 september 2005 22:08 schreef Vloris het volgende:
Ter info, de gewraakte query:
[ code verwijderd ]
1 2 3 | <?php $query="SELECT * FROM table WHERE id='".$_GET['id']."'"; ?> |
Nee hoor, dan krijgen we ditquote:Dan krijg je inderdaad onzin.
Maar, als we in de id= waarde nou een ' verstoppen kun je daarachter leuke sql opnemen.
Een voorbeeldje, stel dat er nog een tabel `auth` is met plaintext usernames en passwords (of md5 hashes, daar kan een hacker ook wel wat mee). De volgende injectie moet dan toch best wat leuks kunnen laten zien (mits mysql versie 4 of hoger gebruikt)
1 2 3 | <?php $query="SELECT * FROM table WHERE id='"0 UNION SELECT * FROM `auth`"'"; ?> |
En dan ga je er al vanuit dat de hacker allerlei kennis heeft over je database model.quote:Wauw! Geldige query die mysql zonder problemen uitvoert. Fijn, we krijgen nu als resultaat naast het bedoelde antwoord ook 1 of meerdere regels uit de auth tabel.
Eventueel in plaats van een * kolomnamen hernoemen zodat ze meegenomen worden naar de juiste uitvoer van de pagina, maar daar is wel wat op te vinden.
Je bericht is een kwartier naderhand gewijzigd, dat zag ik ook niet. Maar 'id' is vast een numeriek type, en die ga je vergelijken met een string?quote:Op donderdag 1 september 2005 22:18 schreef Swetsenegger het volgende:
[..]
Het antwoord van JeRa was dus niets vollediger dan dat van mij, terwijl hij dat wel suggereerde.
Waar komen die dubbele quotes opeens vandaan? Die zijn er niet, en dan krijg je het probleem dat Vloris hierboven opmerkt en waarvoor ik mij schaam dat ik dat niet eerder zagquote:Op donderdag 1 september 2005 22:18 schreef Swetsenegger het volgende:
Nee hoor, dan krijgen we dit
[ code verwijderd ]
Het enige wat ik er aan toegevoegd heb is de ;quote:Op donderdag 1 september 2005 22:23 schreef JeRa het volgende:
[..]
Je bericht is een kwartier naderhand gewijzigd, dat zag ik ook niet.
quote:Maar 'id' is vast een numeriek type, en die ga je vergelijken met een string?![]()
is_numeric ook.quote:bovendien voorkomt intval de invoeging van tekst in een query,
wanneer je je data tussen ' ' zet is injection niet zo eenvoudig als het lijkt.quote:want jouw methode voorkomt ook niet dat iemand andere info uit de database haalt. Ik zei alleen dat dat met SQL injection wellicht mogelijk was, maar in de oorspronkelijke query moet daar natuurlijk validatie aan vooraf gaan
Die staan er al vanaf de eerste post van mij hieroverquote:Op donderdag 1 september 2005 22:43 schreef JeRa het volgende:
[..]
Waar komen die dubbele quotes opeens vandaan?
Hij staat niet tussen php tags, dus het is lastig te zienquote:Op donderdag 1 september 2005 19:52 schreef Swetsenegger het volgende:
$query=" SELECT * FROM database WHERE id='".$_GET['id']";
Be my guest, zet een voorbeeld scriptje in elkaar en probeer het.quote:Op donderdag 1 september 2005 22:34 schreef Vloris het volgende:
Goed, even snel.
Swetsenegger: dan pak ik die query met quotes en zorg ik ervoor dat $_GET['id'] begint met 0' UNION ... etc.
Misschien moet er nog een \ voor de ', dat zou kunnen, maar die is er prima in te futselen. En het probleem dat er ineens nog een ' achteraan komt is eenvoudig op te lossen door mijn injectie te laten eindigen op een nutteloze WHERE 'foo' = 'foo
(misschien ook weer \' dat weet ik zo niet precies)
is_numeric controleert of het in het goede type staat. intval() zet het automatisch om naar het goede type. alleen zie ik is_numeric niet echt staan bij die query, en het zorgt er niet voor dat de waarde ook automatisch is wat je wilde. Met intval is het zelfs mogelijk om '3 schapen' in te voeren en daar het goede getal uit te krijgen.quote:
Een \' om de quotes te omzeilen is meer dan genoeg.quote:[..]
wanneer je je data tussen ' ' zet is injection niet zo eenvoudig als het lijkt.
Kijk, dat bedoelde ik in m'n vorige post ook, misschien is dit dan ten overvloede, maar je kunt best ' tekentjes injecten. Dat probeerde ik eigenlijk aan te tonen. Zonder voorzorgsmaatregelen (als b.v. magic_quotes ergens enigszins aan staat) is het dan prima te injecten.quote:Op donderdag 1 september 2005 22:56 schreef Swetsenegger het volgende:
wanneer je je data tussen ' ' zet is injection niet zo eenvoudig als het lijkt.
Dit schreef jij:quote:Op donderdag 1 september 2005 22:58 schreef Swetsenegger het volgende:
[..]
Die staan er al vanaf de eerste post van mij hierover
[..]
Hij staat niet tussen php tags, dus het is lastig te zien
Jij neemt kennelijk aan dat magic_quotes_gpc op On staat. Dit is echter niet altijd het geval. Als die niet aan staat is het ongelofelijk makkelijk om met quotes te spelen en géén error te laten optreden. En die verregaande kennis over het model, je hoeft alleen wat namen te kennen; en security through obscurity werkt natuurlijk niet hequote:Op donderdag 1 september 2005 22:59 schreef Swetsenegger het volgende:
[..]
Het enige wat je krijgt is sql errors. En dan hebben we het nog niet eens over het feit dat je blijkbaar verregaande kennis hebt van het database model.
Als ik iets niet wil in mijn query is het ongecontroleerd 'automatische' scriptjesquote:Op donderdag 1 september 2005 23:00 schreef JeRa het volgende:
[..]
is_numeric controleert of het in het goede type staat. intval() zet het automatisch om naar het goede type.
Nee, en bij jouw query zie ik ook geen controle op user input staan.quote:alleen zie ik is_numeric niet echt staan bij die query,
Nee, het zorgt dat het TYPE automatisch is wat ik wilde. Of de waarde klopt heb ik geen enkel idee van.quote:en het zorgt er niet voor dat de waarde ook automatisch is wat je wilde.
Dat geeft '0'. -edit- nopes, 3. Nu maar hopen dat je 3 wilde hebbenquote:Met intval is het zelfs mogelijk om '3 schapen' in te voeren en daar het goede getal uit te krijgen.
quote:En 'id' is meestal een kolom van het type UNSIGNED INT, en een integer moet je vergelijken met een integer en niét met een string (wat je in die query nu dus in feite doet).
Nogmaals, be my guest. Maak een voorbeeld scriptje en ga lekker de hele avond zitten injecten. Ik zie je voorbeeld injection graag tegemoed.quote:Een \' om de quotes te omzeilen is meer dan genoeg.
quote:Op donderdag 1 september 2005 23:02 schreef JeRa het volgende:
[..]
Dit schreef jij:
$query="SELECT * FROM table WHERE id='"0 UNION SELECT * FROM `auth`"'";
Die code die jij beschrijft zorgt echt niet voor de aanhalingstekens, hoogstens voor de enkele quotes ('). Het resultaat dat geproduceerd wordt is dus zonder de aanhalingstekens, maar met de enkele quotes. Als de user iets doet in de trant van:
' OR 1 OR '
Dan heb je dat dus al omzeild.
1 2 3 | <?php $query="SELECT * FROM table WHERE iets='".$variabele."'"; ?> |
1 2 3 | <?php $query="SELECT * FROM table WHERE iets='"SELECT * FROM `database` WHERE `id` = 0 UNION SELECT * FROM `auth`"'"; ?> |
Forum Opties | |
---|---|
Forumhop: | |
Hop naar: |