(C) Copyright 2006-2007, Saven.nl
Deze cursus mag nergens anders zonder mijn toestemming worden gepubliceerd
Je hebt het misschien wel eens meegemaakt, je gebruikte een gratis source die waarvan het ledensysteem lek was, en iedereen zomaar in je Admin CP kon.
Nou bij zo\'n soort probleem ga ik je nu helpen. We gaan een veilig inlog systeem maken met behulp van cookies en een mysql database.
[strip]
\"Cookies?\" Ja cookies ja. \"Cookies zijn toch juist onveilig en hackbaar enzo..\".
Nou, als je weet wat je doet niet dus.
Ik zal eens met een simpel voorbeeld beginnen dat zeer onveilig is.
We hebben 1 cookie genaamt \"saven_id\". in dat id staat het id nummer van je account.
Stel dat we zo\'n soort code gebruiken:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php if( isset($_COOKIE[\'saven_id\']) ) { $ingelogd = true; $query = mysql_query(\"SELECT * FROM leden WHERE id=\'$_COOKIE[saven_id]\'\"); $list = mysql_fetch_object($query); } else { $ingelogd = false; } ?>
Nou weet ik niet of dit in het echt zou werken, want zo bagger script ik nooit :\'), maar dat even terzijde.
Je hebt dus de bovenstaande code. Je ziet dat er al enorm veel dingen mis zijn.
De scripting is ronduit bagger en onveilig.
Laten we beginnen met het uitleggen van het bovenstaande script:
- We kijken of er een cookie bestaat die \"saven_id\" heet, zo nee is de persoon niet ingelogd, zo ja gaan we checken..
We gaan er van uit dat de persoon is ingelogd.
Zoals je ziet is de persoon hoe dan ook ingelogd als er een cookie \"saven_id\" bestaat. Dit is enorm onhandig en onveilig, omdat iemand dan zo ingelogd kan zijn op je site.
Nou is dit niet direct het gevaarlijkste, maar juist de query die gegevens op haalt.
Een cookie staat op de computer van die client, en kan dus ook bewerkt worden.
Stel dat het \"saven_id\" van de webmaster 1 is.
Dan kunnen we zonder problemen inloggen op de account van de webmaster simpelweg door onze cookie id op 1 te zetten.
Dit was dan nog wel het meest domme en simpelste voorbeeld, maar helaas komen dit soort dingen wel voor bij beginnende scripters.
We gaan het even iets moeilijker maken voor de scriptkiddie. We gaan nu checken of er meerdere cookies bestaan, en anders nagaan of iemand is ingelogd.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php if( isset($_COOKIE[\'saven_id\']) && isset($_COOKIE[\'saven_password\']) && !empty($_COOKIE[\'saven_id\']) && !empty($_COOKIE[\'saven_password\']) ) { $query = mysql_query(\"SELECT * FROM leden WHERE id=\'$_COOKIE[saven_id]\'\"); if( mysql_num_rows($query) == 1 ) { $ingelogd = true; $fetch = mysql_fetch_object($query); } else { $ingelogd = false; } } else { $ingelogd = false; } ?>
Nou is dit al ietsje veiliger dan het vorige voorbeeld, maar nog steeds verre van echt veilig.
We controleren nu of de 2 cookies bestaan, en gaan een query uitvoeren.
Als de uitgevoerde query een resultaat heeft dan is de persoon ingelogd, zoniet, dan niet.
Maar het probleem is er nog steeds dat iemand webmaster kan worden door zijn cookie id te veranderen.
Nu kun je denk ik zelf wel het goede script bedenken:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php if( isset($_COOKIE[\'saven_id\']) && isset($_COOKIE[\'saven_password\']) && !empty($_COOKIE[\'saven_id\']) && !empty($_COOKIE[\'saven_password\']) ) { $query = mysql_query(\"SELECT * FROM leden WHERE id=\'\".addslashes($_COOKIE[\'saven_id\']).\"\' AND password=\'\".addslashes($_COOKIE[\'saven_password\']).\"\'\")or die(mysql_error()); if( mysql_num_rows($query) == 1 ) { $ingelogd = true; $fetch = mysql_fetch_assoc($query); } else { $ingelogd = false; } } else { $ingelogd = false; } ?>
Ten eerste zorgen we dat er geen sql injection kan worden uitgevoerd in de input, en controleren we of een user bestaat met het id én wachtwoord.
Nu kun je dus niet meer je id op 1 zetten, maar heb je ook het wachtwoord nodig.
Ook hebben we de query even netjes gemaakt, en gebruikeren we fetch_assoc ipv fetch_object.
Nou zijn er nog steeds mensen die zoiets hebben zoals hier vlak boven staat, alleen gaan ze alsnog data vanuit de cookie lezen.
Dus bijvoorbeeld:
<input type=\"text\" name=\"gebruikersnaam\" value=\"<?= $_COOKIE[\'saven_gebruikersnaam\'] ?>\" />
Dan heeft het nog niet echt nut als je alleen op de user_id en password controleerd, want de gebruikersnaam kan nog willekeurige data bevatten.
Bijvoorbeeld, html code, of misschien is sql injection wel mogenlijk.
Je zult dus op alle cookies moeten checken, en je data altijd vanuit de database halen. Als je het uit de database haalt weet je zo goed als zeker dat er niet mee geknoeid kan worden! (tenzij je je aanmeldformulier, of profiel instellingen niet goed checkt dat iemand alsnog html kan gebruiken)
Hier onder even een voorbeeldscriptje van hoe het goed zou zijn:
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
<?php if( isset($_COOKIE[\'id\']) && isset($_COOKIE[\'username\']) && isset($_COOKIE[\'password\']) ) { $query = mysql_query(\"SELECT * FROM leden WHERE id=\'\".addslashes($_COOKIE[\'id\']).\"\' AND username=\'\".addslashes($_COOKIE[\'username\']).\"\' AND password=\'\".addslashes($_COOKIE[\'password\']).\"\'\")or die(mysql_error()); if( mysql_num_rows($query) == 1 ) { $ingelogd = true; $fetch = mysql_fetch_assoc($query); } else { $ingelogd = false; } } else { $ingelogd = false; } if( $ingelogd == true ) { echo \'Welkom \'.$fetch[\'username\'].\' op onze website.<br />je persoonlijke id is \'.$fetch[\'id\'].\' enzo.\'; } else { echo \'Niet ingelogd\'; } ?>
noot: ik heb dit om 00:00 getypt toen ik moe was, er kunnen dus wat foutjes in zitten