Welkom, Gast. Je bent niet ingelogd.

Cursus:Hoe maak ik een veilig inlogsysteem

Door Saven op 24 Dec 2006, 00:06

Cursus: Hoe maak ik een veilig loginsysteem
(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:

1
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.

1
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:

1
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:

1
<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:

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
<?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

Hunterseaker
Geplaatst op: 22 Apr 2007, 12:07

Ook al is dit een redelijk oud topic, toch heb ik ff een vraagje aan saven: Waarom zou je ooit het password in een cookie zetten? Als de cookies, saven_id en saven_password gestolen worden ben je ook binnen....
Beter lijkt mij dus om het ip van de vorige login te checken met het ip adres van de huidige login poging. Dit in combinatie met een login hash gebruiken.

Jou script is veilig, zolang er maar geen cookies gestolen worden.....

Headshot
Geplaatst op: 18 Apr 2007, 09:54

Nice

NickD
Kurosaki Kun!!
Geplaatst op: 01 Apr 2007, 20:56

achjah zoals eerder werd gezegd. hij is wel heen =)
(in de eerste reactie fsow.. )

btw sorry voor \'t kickje

iisys
Hmhm, indeed. whtvr.
moderator
Geplaatst op: 27 Dec 2006, 17:24

DJVG schreef:

[...]
Waarom?
SSL is alleen voor een veilige overdracht...

Precies, veilige overdracht voor gevoelige informatie zoals wachtwoorden ed.

DJVG
&#61514;
Geplaatst op: 27 Dec 2006, 15:38

Syncie schreef:

1. Gebruik SSL als dat kan.

Waarom?
SSL is alleen voor een veilige overdracht...

Saven
admin
Geplaatst op: 26 Dec 2006, 11:39

Wouser schreef:

ik zou eigenlijk zo wie zo altijd sessies gebruiken... en ik had eigenlijk ook wel beter verwacht

Ik vind deze die een vriend van me heeft gemaakt trouwens veel mooier en is 100% veilig

http://www.plaatscode.be/3547/


Mja :\') het ging mij er eigenljik om dat sommige mensen alleen checken op cookie id, en dat ze daarom meteen gaan bleren dat cookies onveilig zijn

Wouser
Cadeau'tjes :r
Geplaatst op: 24 Dec 2006, 20:02

ik zou eigenlijk zo wie zo altijd sessies gebruiken... en ik had eigenlijk ook wel beter verwacht

Ik vind deze die een vriend van me heeft gemaakt trouwens veel mooier en is 100% veilig

http://www.plaatscode.be/3547/

[Laatst bewerkt door Wouser op zondag 24 december 2006, om 20:12]
Syncie
Geplaatst op: 24 Dec 2006, 18:49

Nisk gezegd

[Laatst bewerkt door Syncie op maandag 25 december 2006, om 00:44]
Syncie
Geplaatst op: 24 Dec 2006, 17:33

Ik had wel wat stukken beters van jou verwacht..

Zoiets:

1. Gebruik SSL als dat kan.

2. Zorg voor een maximaal aantal loginpogingen.

3. Maak een hash met de username, password(Gehashed), timestamp(Die update je bij elk bezoek van de user). Sla die op in een sessie/cookie.
Hash: hash(username, password, timestamp) Hierin in het password al gehashed.

4. Zo controleer je of iemand is ingelogd: Selecteer alles van de hash tabel waar het IP van de bezoeker gevonden is. Vergelijk de hash en als die klopt is diegene ingelogd.

Zo voorkom je ook het stelen van cookies/sessies.

[Laatst bewerkt door Syncie op maandag 25 december 2006, om 00:44]
Rinaldo
Geplaatst op: 24 Dec 2006, 17:26

Nice Saven

iisys
Hmhm, indeed. whtvr.
moderator
Geplaatst op: 24 Dec 2006, 15:44

Andries Louw W. schreef:

Dit script is pas lek als een mandje!!

Gebruik nooit en te nimmer in je script:
$ingelogd = true;

om te kijken of iemand ingelogd is!

Als de hosts register_globals aan hebben staan (Staat standaard aan, en meer dan 90% van de hosts hebben dat nog steeds aan!), dan is een simpele ?ingelogd=true achter de url genoeg om ingelogd te geraken!

Ik raad bij deze iedereen af dit systeem te gebruiken!

Met vriendelijke groet,
PHP developer
Andries Louw Wolthuizen


Mee eens, en het is sowieso zinloos om $ingelogd = true te zetten, want zo is het alleen op die pagina beschikbaar.
Ik gebruik een class method om dit in te stellen:
$u->set_var(\'is_signedIn\', 1);
Die zet $_SESSION[\'u\'][\'is_signedIn\'] en $u->is_signedIn op 1 (true).
Zo kan je er niet zomaar bijkomen dmv register_globals.

en ik zou sowieso aan je host vragen of ze register_globals uitzetten. Heeft geen nut als t aanstaat.

Gast
Geplaatst op: 24 Dec 2006, 14:35

Dit script is pas lek als een mandje!!

Gebruik nooit en te nimmer in je script:
$ingelogd = true;

om te kijken of iemand ingelogd is!

Als de hosts register_globals aan hebben staan (Staat standaard aan, en meer dan 90% van de hosts hebben dat nog steeds aan!), dan is een simpele ?ingelogd=true achter de url genoeg om ingelogd te geraken!

Ik raad bij deze iedereen af dit systeem te gebruiken!

Met vriendelijke groet,
PHP developer
Andries Louw Wolthuizen

HyperTesia
Webdeveloper
Geplaatst op: 24 Dec 2006, 14:32

nice tut saven

Tildo
Geplaatst op: 24 Dec 2006, 13:42

Bernt schreef:

Lol:\')
Nice saven!

Spoiler 😨 (selecteer om te bekijken)
ghogho, de man die denk dat hij zich zelf unbant bij snake\'s sigchat

leuk artikeltje

Bernt
B3rnTz0r
Geplaatst op: 24 Dec 2006, 13:03

Lol:\')
Nice saven!

Triple
Geplaatst op: 24 Dec 2006, 12:41

Vet ik doe mee

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
<?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
{
   ?>
<form method=\"POST\" action=\"inloggen.php\">
<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"border-collapse: collapse\" bordercolor=\"#111111\" width=\"100%\" id=\"AutoNumber1\">
    <tr>
      <td width=\"24%\">Gebruikersnaam:</td>
      <td width=\"76%\"><input type=\"text\" name=\"username\" size=\"20\"></td>
    </tr>
    <tr>
      <td width=\"24%\">Wachtwoord:</td>
      <td width=\"76%\"><input type=\"password\" name=\"password\" size=\"20\"></td>
    </tr>
  </table>
  <p>Nog geen account? Registreer je!<br>
  Wachtwoord vergeten?<br>
  <br>
  <input type=\"submit\" value=\"Inloggen\" name=\"submit\"></p>
</form>
   <?php
}
?>

Suma
heeft gelijk
Geplaatst op: 24 Dec 2006, 12:06

Dit is een erg handige blog Mooi Saven !

Alleen de titel klopt niet echt zoals iisys al zei xD

iisys schreef:

Nou niet wat je noemt een heel login systeem :\')

Saven
admin
Geplaatst op: 24 Dec 2006, 12:01

iisys schreef:

Nou niet wat je noemt een heel login systeem :\')

Nee :\') maar ik wist niks anders hoe ik het kon benoemen

iisys
Hmhm, indeed. whtvr.
moderator
Geplaatst op: 24 Dec 2006, 11:22

Nou niet wat je noemt een heel login systeem :\')

[Laatst bewerkt door Saven op zondag 24 december 2006, om 12:01]
Sharp
:')
moderator
Geplaatst op: 24 Dec 2006, 11:20

Nice, zoiets had ik nodig

[Laatst bewerkt door Twizy op zondag 24 december 2006, om 11:52]
AfcAjax
Geplaatst op: 24 Dec 2006, 10:27

FastFox schreef:

Je bent wel erg ver heen als je dit om 00:00 gaat typen. Niet alleen de tijd maar ook gewoon de \'cursus\' opzich. :\')

Zeker

FastFox
Geplaatst op: 24 Dec 2006, 09:51

Je bent wel erg ver heen als je dit om 00:00 gaat typen. Niet alleen de tijd maar ook gewoon de \'cursus\' opzich. :\')

AfcAjax
Geplaatst op: 24 Dec 2006, 08:51

Cool Saven. Kun je me miss even helpen met me ubb?

📫

Nieuw privébericht

🔥

Registreren


Login