[PHP] Gebruik GET variabele in SQL query

Pagina: 1
Acties:
  • 209 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • mr_obb
  • Registratie: Juni 2001
  • Laatst online: 01-09 14:15

mr_obb

Lakse Perfectionist

Topicstarter
Ik heb de volgende vraag. Ik ben bezig met een simpele website. Ik wil een variabele uit de $_GET-array gebruiken in mijn SQL-query. In extreem simpele code zou dat zijn:

code:
1
2
3
$variabele = $_GET['variabele'];
$query = "SELECT * FROM tabel WHERE kolom1 ='".$variabele."' ORDER BY prioriteit";
mysql_query($query,$db_conn);


In deze code zit geen enkele beveiliging ingebouwd. Op de server staat wel Magic Quotes aan. Op welke manier kan ik verwachten dat een gebruiker misbruik kan maken van deze slechte code? Het is mijzelf nog niet gelukt om iets gevaarlijks uit te halen.

Als ik weet hoe de gebruikers er misbruik van kunnen maken, kan ik daar een beveiliging tegen bouwen.

Ik heb de FAQ gelezen en gezocht naar vergelijkbare topics. Zonder bevredigend resultaat.

[ Voor 12% gewijzigd door mr_obb op 13-01-2005 19:09 ]


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

Zonder bevredigend resultaat? Herhaal je zoekactie nog eens met de woorden sql en injection en ik gok dat de resultaten je om de oren vliegen ;)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • Johnny
  • Registratie: December 2001
  • Nu online

Johnny

ondergewaardeerde internetguru

En dat kan je in PHP allemaal heel makkelijk voorkomen door bij strings mysql_real_escape_string() (vaak nog met stripslashes() er bij) te gebruiken, en voor integers intval()

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


Acties:
  • 0 Henk 'm!

  • mr_obb
  • Registratie: Juni 2001
  • Laatst online: 01-09 14:15

mr_obb

Lakse Perfectionist

Topicstarter
Creepy schreef op donderdag 13 januari 2005 @ 18:47:
Zonder bevredigend resultaat? Herhaal je zoekactie nog eens met de woorden sql en injection en ik gok dat de resultaten je om de oren vliegen ;)
Ja en die gaan allemaal over queries in de user tabel. Mijn vraag is of ze kwaad kunnen doen als ik in een standaard tabel zo'n query gebruik. Ze kunnen alles in de tabel opvragen, maar dat vind ik niet het grootste probleem. Kunnen ze ook andere geintjes uithalen?

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 00:12
Waarom zou je het risico nemen... als je een integer verwacht dan cast je hem als integer, als je een string verwacht dan ben je al safe als je de quotes er uit stript. Op zijn simpelst:
PHP:
1
2
$variabele = (int)$_GET['variabele'];
$variabele = str_replace('"', '', str_replace("'", '', $_GET['variabele']));

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

Verwijderd

Kijken of $_GET['variabele'] in een array met toegestane waarden zit helpt ook toch? Zo doe ik het iig:
PHP:
1
2
3
4
if (in_array($variabele, $toegestane_waarden)) {
doe iets}
else{
doe niets}

[ Voor 5% gewijzigd door Verwijderd op 13-01-2005 21:43 ]


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

mr_obb schreef op donderdag 13 januari 2005 @ 18:57:
[...]


Ja en die gaan allemaal over queries in de user tabel. Mijn vraag is of ze kwaad kunnen doen als ik in een standaard tabel zo'n query gebruik. Ze kunnen alles in de tabel opvragen, maar dat vind ik niet het grootste probleem. Kunnen ze ook andere geintjes uithalen?
Ja dat kan. En dat had je echt wel geweten als je naast GoT ook nog eens met behulp van google had gezocht.

Met de juiste queries kunnen ze informatie ophalen over de databases. Daarnaast kan het ook mogelijk zijn om records, tabellen, of zelfs de gehele database te verwijderen.

Nogmaals: zoek nu eens echt op SQL injection en ook buiten GoT. Er is echt veel info over te vinden.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • Lentje
  • Registratie: Juni 2001
  • Laatst online: 05-09 15:08
Creepy schreef op donderdag 13 januari 2005 @ 22:38:
[...]

Ja dat kan. En dat had je echt wel geweten als je naast GoT ook nog eens met behulp van google had gezocht.

Met de juiste queries kunnen ze informatie ophalen over de databases. Daarnaast kan het ook mogelijk zijn om records, tabellen, of zelfs de gehele database te verwijderen.

Nogmaals: zoek nu eens echt op SQL injection en ook buiten GoT. Er is echt veel info over te vinden.
Maar zover ik weet ondersteunt mysql_query() geen meerdere queries in 1 keer? Dus het zou in dit geval wel veilig zijn toch?

Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Lentje schreef op vrijdag 14 januari 2005 @ 00:52:
[...]


Maar zover ik weet ondersteunt mysql_query() geen meerdere queries in 1 keer? Dus het zou in dit geval wel veilig zijn toch?
op dit moment is dat zo, maar er is geen enkele garantie dat dat ooit veranderd ;)
Buiten dat feit, kan je wel op deze manier data terug krijgen uit dezelfde query die niet voor jou bestemd zijn (bijvoorbeeld een rechtencheck die je op deze manier kan omzeilen) of dat je met het verwijderen van een item op de site meteen maar alles verwijderd.
Nee, escape nu alles wat je naar de database toestopt, daarmee voorkom je al een groot deel van alle problemen ;)

Acties:
  • 0 Henk 'm!

  • Lentje
  • Registratie: Juni 2001
  • Laatst online: 05-09 15:08
Erkens schreef op vrijdag 14 januari 2005 @ 00:56:
[...]

op dit moment is dat zo, maar er is geen enkele garantie dat dat ooit veranderd ;)
Buiten dat feit, kan je wel op deze manier data terug krijgen uit dezelfde query die niet voor jou bestemd zijn (bijvoorbeeld een rechtencheck die je op deze manier kan omzeilen) of dat je met het verwijderen van een item op de site meteen maar alles verwijderd.
Nee, escape nu alles wat je naar de database toestopt, daarmee voorkom je al een groot deel van alle problemen ;)
Ja ik ben het ook volledig met je eens dat je eerst user input moet checken. Maar in dit geval kon er niet veel kwaad dacht ik.

Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Erkens schreef op vrijdag 14 januari 2005 @ 00:56:
[...]

op dit moment is dat zo, maar er is geen enkele garantie dat dat ooit veranderd ;)
Ik weet niet of ik die knipoog als 'grapje' moet opvatten. Want wat je schrijft is natuurlijk onzin. Het php team heeft opzettelijk de multiple query ondersteuning eruit gehaald vanwege injection gevaar.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

T-MOB schreef op donderdag 13 januari 2005 @ 19:12:
Waarom zou je het risico nemen... als je een integer verwacht dan cast je hem als integer, als je een string verwacht dan ben je al safe als je de quotes er uit stript. Op zijn simpelst:
PHP:
1
2
$variabele = (int)$_GET['variabele'];
$variabele = str_replace('"', '', str_replace("'", '', $_GET['variabele']));
Vreemde methode heb jij. :o Het volgende is toch meer de standaard, en ook wat meer naar de wens van de meeste programmeurs:
PHP:
1
2
3
4
5
6
7
8
9
$var1 = isset($_GET['var1']) && is_integer($_GET['var1']) ? $_GET['var1'] : false;
$var2 = isset($_GET['var2']) && !empty($_GET['var2']) ? addslashes($_GET['var2']) : false;

if (($var1 !== false) && ($var2 !== false)) {
    $query = "SELECT * FROM tabel WHERE kolom1 = ".$var1." AND kolom2 = '".$var2."' ORDER BY prioriteit";
    mysql_query($query,$db_conn);
} else {
    die("Stoute usertjes komen er niet in!");
}


De bovenste twee regels checken uitgebreid of de variabelen wel gezet zijn, en of ze integer, respectievelijk een string zijn, en zo niet, wordt er de waarde false in gezet, waarop expliciet gecontroleerd wordt met de !== operator. Merk op dat de != operator niet voldoet: $var1 zou immers eventueel 0 kunnen zijn, of $var2 kan bestaan uit één of een aantal nullen.

[ Voor 10% gewijzigd door NMe op 14-01-2005 03:40 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Grijze Vos schreef op vrijdag 14 januari 2005 @ 03:05:
[...]

Ik weet niet of ik die knipoog als 'grapje' moet opvatten. Want wat je schrijft is natuurlijk onzin. Het php team heeft opzettelijk de multiple query ondersteuning eruit gehaald vanwege injection gevaar.
Hoe kan je een knipoog nu zien als een grapje 8)7
Maar hoezo is dat onzin? Wellicht dat ze ooit eens inzien dat het erg handig kan zijn om in een keer meerdere query's te sturen, en dan bedoel ik vooral performance. Want ik vind het bijzonder irritant dat het in PHP niet mogelijk is.

Acties:
  • 0 Henk 'm!

  • pjonk
  • Registratie: November 2000
  • Laatst online: 10-09 15:33
Magic quotes GPC :X. Op PHP.net raden ze het ook af, zie http://www.php.net/manual/en/security.magicquotes.php
Schrijf je scripts altijd zo dat ze onafhankelijk van server instellingen (zoals magic quotes GPC) werken, want als je je script naar een andere server verhuist die magic quotes GPC UIT heeft staan heb je een serieus probleem.

Wat ik zelf altijd doe is in een include script die altijd als eerst wordt uitgevoerd de quotes strippen:
PHP:
1
2
3
4
5
6
7
// Strip magic_quotes if magic_quotes_gpc is turned on
if (get_magic_quotes_gpc() {
   reset($_GET);
   while (list($key, $value) = each($_GET)) {
      $_GET[$key] = stripslashes($_GET[$key]);
   }
}

Het PHP script dat de query uitvoert schrijf ik zo:
PHP:
1
$sql = "SELECT * FROM News WHERE Title='" . addslashes($_GET['title']) . "'";

Deze code klinkt toch veel logischer? Ik voeg expliciet slashes toe aan een GET variabele zodra ik die in een query gebruik. Als je met een ID werkt en die eerst expliciet cast naar een integer worden mogeiljke quotes er automatisch uitgefilterd en heb je addslashes niet meer nodig.

It’s nice to be important but it’s more important to be nice


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 00:12
-NMe- schreef op vrijdag 14 januari 2005 @ 03:40:
[...]
Vreemde methode heb jij. :o Het volgende is toch meer de standaard, en ook wat meer naar de wens van de meeste programmeurs:
Je hebt helemaal gelijk, de code was ook niet bedoeld als bruikbare methode. Meer om aan te geven dat je in 2s kunt zorgen dat er niet in je queries gerommeld kan worden...

Variabelen naar integers casten gebruik ik overigens wel echt, ala:
PHP:
1
2
3
4
5
6
7
8
$id = (int)$_GET['id'];
  $query = mysql_query('SELECT columns FROM table WHERE id = ' .$id .' LIMIT 1', $db);
  if (mysql_num_rows($query) == 1)
  {
   //display content
  } else {
   // spul bestaat niet poepie!
  }

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

T-MOB schreef op vrijdag 14 januari 2005 @ 15:03:
Variabelen naar integers casten gebruik ik overigens wel echt, ala:
PHP:
1
2
3
4
5
6
7
8
$id = (int)$_GET['id'];
  $query = mysql_query('SELECT columns FROM table WHERE id = ' .$id .' LIMIT 1', $db);
  if (mysql_num_rows($query) == 1)
  {
   //display content
  } else {
   // spul bestaat niet poepie!
  }
Ik zou dat niet doen. Als iemand een float over de lijn stuurt, dan wordt dat wel netjes gecast naar een integer, maar het betekent wel dat iemand zit te kloten met je invoer. Je kan beter checken of het een integer is, en zo ja, dan kun je er wat mee doen. Is het geen integer, dan hang je het script op. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

Lentje schreef op vrijdag 14 januari 2005 @ 00:52:
[...]


Maar zover ik weet ondersteunt mysql_query() geen meerdere queries in 1 keer? Dus het zou in dit geval wel veilig zijn toch?
mysql_query("select * from blaat where iets = dinges or 1 = 1; delete * from blaat;",$db);

Waarbij or 1 = 1 ingevoegd zou kunnen worden: resultaat: je ziet ALLE records.
"; delete * from blaat;" zou ook ingevoegd kunnen worden. twee queries in 1 string! ;)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 00:12
-NMe- schreef op vrijdag 14 januari 2005 @ 15:09:
[...]
Ik zou dat niet doen. Als iemand een float over de lijn stuurt, dan wordt dat wel netjes gecast naar een integer, maar het betekent wel dat iemand zit te kloten met je invoer. Je kan beter checken of het een integer is, en zo ja, dan kun je er wat mee doen. Is het geen integer, dan hang je het script op. :P
Mwoah, als iemand een willekeurig integer naar je script stuurt zit ie ook te kloten met de invoer. Bovendien komen (iig op mijn server) alle GET-variabelen binnen als string.
PHP:
1
2
3
$test = $_GET['id'];
if (is_integer($test) ) { echo $test .' (integer)'; }
if (is_string($test) ) { echo $test .' (string)'; }

Echoed altijd "$test (string)", ook al geef je een integer mee.

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Creepy schreef op vrijdag 14 januari 2005 @ 15:10:
[...]

mysql_query("select * from blaat where iets = dinges or 1 = 1; delete * from blaat;",$db);

Waarbij or 1 = 1 ingevoegd zou kunnen worden: resultaat: je ziet ALLE records.
"; delete * from blaat;" zou ook ingevoegd kunnen worden. twee queries in 1 string! ;)
RTFM :+
The query string should not end with a semicolon.
Helaas kan je met PHP niet meerdere query's gelijktijdig sturen...

Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
T-MOB schreef op vrijdag 14 januari 2005 @ 15:22:
Echoed altijd "$test (string)", ook al geef je een integer mee.
Dat komt, omdat PHP $_GET (en $_POST) waarden standaard naar een string cast :). ctype_digit heeft mijn voorkeur, die pakt namelijk ook echt *alleen* getallen en niet 1e4, zoals is_numeric of andere functies :). (Niet dat het veel uitmaakt, maar ik vind 't vreemde getallen, die niet veel gebruikt worden in een GUI voor standaard applicaties, en dus overbodig).

Dat PHP niet meerdere queries uit kan voeren door ze met een ; te scheiden, wil niet zeggen dat je je doel niet dmv een UNION kunt berijken ;).

Gewoon mysql_real_escape string over je $_GET variabelen heen halen, na je andere validaties.

Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

PrisonerOfPain schreef op vrijdag 14 januari 2005 @ 17:39:
Dat PHP niet meerdere queries uit kan voeren door ze met een ; te scheiden, wil niet zeggen dat je je doel niet dmv een UNION kunt berijken ;).
Hoe wil je dat doen dan met INSERTs en UPDATEs (of eventueel DELETEs) 8)7
Pagina: 1