Hoe de identiteit van de persoon vast te stellen
Ik worstel al een tijdje met een probleem qua authenticatie
Ik doe het nu als volgt:
Code (php)
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
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
$actie = $_GET['actie'];
if(isSet($actie) && $actie == 'verifieren'){
if($_SERVER['REQUEST_METHOD'] != 'POST'){
$error = true;
$error_no_form = true;
}
else{
# Omzetten naar variabelen
$email = $_POST['email'];
$wachtwoord = $_POST['wachtwoord'];
if(empty($email) || empty($wachtwoord)){
$error = true;
$error_gebruiker_wachtwoord = true;
}
else{
# Database selecteren
$email = addslashes($email);
$wachtwoord = crypt($wachtwoord, '$6$rounds=5909$abcdefghijklmnop$');
# Gegevens uit database ophalen.
$query = "SELECT * FROM gebruikers WHERE email='" . $email . "' " . "AND wachtwoord='" . $wachtwoord . "'";
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$aantalRijen_resultaat = mysql_num_rows($resultaat);
$rij = mysql_fetch_assoc($resultaat);
if($aantalRijen_resultaat == 0){
$error = true;
$error_verkeerde_gegevens = true;
}else{
$_SESSION['gebruiker_id'] = $rij['gebruiker_id'];
$_SESSION['email'] = $rij['email'];
$_SESSION['wachtwoord'] = $rij['wachtwoord'];
$_SESSION['login'] = true;
}
}
}
}
if(isSet($actie) && $actie == 'verifieren'){
if($_SERVER['REQUEST_METHOD'] != 'POST'){
$error = true;
$error_no_form = true;
}
else{
# Omzetten naar variabelen
$email = $_POST['email'];
$wachtwoord = $_POST['wachtwoord'];
if(empty($email) || empty($wachtwoord)){
$error = true;
$error_gebruiker_wachtwoord = true;
}
else{
# Database selecteren
$email = addslashes($email);
$wachtwoord = crypt($wachtwoord, '$6$rounds=5909$abcdefghijklmnop$');
# Gegevens uit database ophalen.
$query = "SELECT * FROM gebruikers WHERE email='" . $email . "' " . "AND wachtwoord='" . $wachtwoord . "'";
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$aantalRijen_resultaat = mysql_num_rows($resultaat);
$rij = mysql_fetch_assoc($resultaat);
if($aantalRijen_resultaat == 0){
$error = true;
$error_verkeerde_gegevens = true;
}else{
$_SESSION['gebruiker_id'] = $rij['gebruiker_id'];
$_SESSION['email'] = $rij['email'];
$_SESSION['wachtwoord'] = $rij['wachtwoord'];
$_SESSION['login'] = true;
}
}
}
}
Ik controleer de e-mail en het wachtwoord. Als deze leeg zijn dan foutmelding, zo niet dan crypt ik het wachtwoord, want zo staat deze op opgeslagen. De reden dat ik pas later crypt is omdat anders het wachtwoord veld nooit leeg is en je dus nooit die foutmelding kan krijgen dat je geen pass hebt ingevuld.
Daarna controleer ik aan de hand van de informatie de gebruiker in de database, als daar als resultaat 0 uit komt dan bestaat de gebruiker niet, of de gegevens zijn verkeerd. Anders bestaat de gebruiker wel.
Als de gebruiker wel bestaat gaat het voor mijn gevoel mis, ik sla gebruikers id, email en wachtwoord in een sessie op en doe dan ook nog login sessie true eraan toevoegen.
Nu is het gevaarlijk om een wachtwoord in een sessie te knallen, want mocht de sessie gestolen worden zou je in theorie aan de hand van de hash het wachtwoord kunnen genereren.
Wat ik met die sessie doe is het volgende:
Code (php)
1
2
3
2
3
$query = "SELECT * FROM gebruikers WHERE email='" . $_SESSION['email'] . "' " . "AND wachtwoord='" . $_SESSION['wachtwoord'] . "' AND gebruiker_id = '" . $_SESSION['gebruiker_id'] . "'";
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$rij = mysql_fetch_assoc($resultaat);
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$rij = mysql_fetch_assoc($resultaat);
Vervolgens bestaat $rij['gebruiker_id'] dus want je bent het hele inlog proces doorlopen
Nu doe ik op elke "beveiligde" pagina het volgende
Maar ik twijfel dus aan de veiligheid. $_SESSION['login'] kan je handmatig op true zetten, dus deze controle slaat nergens op, dan kijk ik of de gebruiker bestaat, maar deze informatie zou je ook uit de sessie kunnen halen dus ik ben bang dat mijn beveiliging helemaal nergens op slaat.
Heeft iemand tips hoe het beter kan?
Je paswoord sla je sowieso niet op!
Je hebt dat paswoord enkel nodig wanneer de gebruiker inlogt; dus wanneer $_POST['wachtwoord'] actief is.
Aan de hand van $_POST['email'] en $_POST['wachtwoord'] selecteer je een gebruiker uit de lijst.
Indien die gevonden wordt, kan je $_SESSION['gebruiker_id'] zetten.
Sessions worden bijgehouden op de sever. Eens $_SESSION['gebruiker_id'] een waarde heeft, kan je er van uit gaan dat de gebruiker ingelogd is.
Aan de hand van $_SESSION['gebruiker_id'] kan je telkens (bij elke muisklik van de gebruiker) de juiste user selecteren. Dat wachtwoord heb je niet meer nodig.
Dit is een basis. Daarna zijn er nog extra beveiligingsmaatregelen mogelijk. controleren op IP, login tijd opslaan, ... maar eerst de basis
Gewijzigd op 17/01/2012 13:44:43 door Kris Peeters
Oke Kris, maar stel $_SESSION['gebruiker_id'] = 1. En ik maak ook een $_SESSION['gebruiker_id'] = 1 aan, dan ben ik toch die gebruiker dan? Zonder ook maar ingelogd of iets te zijn?
Volgens mij verwar jij sessions met cookies.
Ik weet niet precies hoe je het doet, maar er bestaat toch iets zoals session hijacking? Daarmee zou je dat toch kunnen doen dan?
Dan steel je de cookie waarin de sessionid in staat, ga er eerst maar eens wat over lezen :)
Ik denk dat ik het zo aanpak dan, ik laat een willekeurig getal genereren na het inloggen, deze hash ik en deze sla ik op in de database.
Vervolgens aan de hand van $_SESSION['gebruiker_id'] en $_SESSION['hash'] laat ik de gebruiker autoriseren, lijkt mij wel voldoende dan toch?
Heel eerlijk van session hijacking heb ik nog niet zoveel kaas gelezen, maar dat lijkt idd via cookies te gaan, die gebruik ik sowieso niet.
Jij misschien niet, maar de browser moet toch echt wel een sessionid aan de server leveren om te zeggen "hé, dit ben ik!". En meestal wordt dit id in een cookie opgeslagen.
Ja oke, maar deze session_id gebruik ik verder niet, dus dan kunnen ze die wel stelen, maar kunnen ze er niks mee toch?
Jij komt op een site waar sessies worden gebruikt. Als je nog geen sessie hebt gaat ie er eentje aanmaken. Dat sessie krijgt een "random" id, die krijgt de browser te horen. Elke keer dat de browser vervolgens naar een pagina van die site gaat waar sessies gebruikt worden, moet hij aangeven wie hij is (sessionid).
Kijk maar eens bij de cookies van je browser van verschillende sites (bijvoorbeeld van phphulp).
Code (php)
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
48
49
50
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
48
49
50
if(isSet($actie) && $actie == 'verifieren'){
if($_SERVER['REQUEST_METHOD'] != 'POST'){
$error = true;
$error_no_form = true;
}
else{
# Omzetten naar variabelen
$email = addslashes($_POST['email']);
$wachtwoord = $_POST['wachtwoord'];
if(empty($email) || empty($wachtwoord)){
$error = true;
$error_gebruiker_wachtwoord = true;
}
else{
# Database selecteren
$wachtwoord = crypt($wachtwoord, '$6$rounds=5909$wootsaltforthesecretpassword$');
# Gegevens uit database ophalen.
$query = "SELECT * FROM gebruikers WHERE email='" . $email . "' " . "AND wachtwoord='" . $wachtwoord . "'";
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$aantalRijen_resultaat = mysql_num_rows($resultaat);
$rij = mysql_fetch_assoc($resultaat);
if($aantalRijen_resultaat == 0){
$error = true;
$error_verkeerde_gegevens = true;
}else{
$hash = crypt(microtime(), '$6$rounds=5909$supersafehashsalt$');
$query_update_sorteervolgorde = sprintf("UPDATE gebruikers SET secret_hash='%s' WHERE gebruiker_id='%s'",
mysql_real_escape_string($hash),
mysql_real_escape_string($rij['gebruiker_id'])
);
mysql_query($query_update_sorteervolgorde, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query_update_sorteervolgorde . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$_SESSION['gebruiker_id'] = $rij['gebruiker_id'];
$_SESSION['hash'] = $hash;
}
}
}
}
if($_SERVER['REQUEST_METHOD'] != 'POST'){
$error = true;
$error_no_form = true;
}
else{
# Omzetten naar variabelen
$email = addslashes($_POST['email']);
$wachtwoord = $_POST['wachtwoord'];
if(empty($email) || empty($wachtwoord)){
$error = true;
$error_gebruiker_wachtwoord = true;
}
else{
# Database selecteren
$wachtwoord = crypt($wachtwoord, '$6$rounds=5909$wootsaltforthesecretpassword$');
# Gegevens uit database ophalen.
$query = "SELECT * FROM gebruikers WHERE email='" . $email . "' " . "AND wachtwoord='" . $wachtwoord . "'";
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$aantalRijen_resultaat = mysql_num_rows($resultaat);
$rij = mysql_fetch_assoc($resultaat);
if($aantalRijen_resultaat == 0){
$error = true;
$error_verkeerde_gegevens = true;
}else{
$hash = crypt(microtime(), '$6$rounds=5909$supersafehashsalt$');
$query_update_sorteervolgorde = sprintf("UPDATE gebruikers SET secret_hash='%s' WHERE gebruiker_id='%s'",
mysql_real_escape_string($hash),
mysql_real_escape_string($rij['gebruiker_id'])
);
mysql_query($query_update_sorteervolgorde, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query_update_sorteervolgorde . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$_SESSION['gebruiker_id'] = $rij['gebruiker_id'];
$_SESSION['hash'] = $hash;
}
}
}
}
Vervolgens doe ik dan dit:
Code (php)
1
2
3
4
5
2
3
4
5
if(isSet($_SESSION['gebruiker_id']) && isSet($_SESSION['hash'])){
$query = "SELECT * FROM gebruikers WHERE gebruiker_id = '" . $_SESSION['gebruiker_id'] . "' AND secret_hash='" . $_SESSION['hash'] . "'";
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$rij = mysql_fetch_assoc($resultaat);
}
$query = "SELECT * FROM gebruikers WHERE gebruiker_id = '" . $_SESSION['gebruiker_id'] . "' AND secret_hash='" . $_SESSION['hash'] . "'";
$resultaat = mysql_query($query, $verbindDatabase) or die("A MySQL error has occurred.<br />Query: " . $query . "<br /> Error: (" . mysql_errno() . ") " . mysql_error());
$rij = mysql_fetch_assoc($resultaat);
}
En uiteindelijk op elke pagina dit:
Gewijzigd op 17/01/2012 14:43:03 door Pong Zor
Dit: $email = addslashes($email); is geen beveiliging.
Gebruik mysql_real_escape_string().
Is dat het enige?
Ik zag addslashes() staan, verder niet echt gekeken.
Ja klopt, het is beetje samenvoegen van oude code, toen ik nog helemaal noob was in PHP met nieuwe code. Voor de rest vang ik al mijn queries af met escapes.
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$email = addslashes($_POST['email']);
$wachtwoord = $_POST['wachtwoord'];
if(empty($email) || empty($wachtwoord)){
?>
$email = addslashes($_POST['email']);
$wachtwoord = $_POST['wachtwoord'];
if(empty($email) || empty($wachtwoord)){
?>
Dit is verkeerd om checken. Eerst gebruik je de $_POST variabelen om daarna de $email en $wachtwoord te gaan controleren of ze wel een waarde hebben. Als die check echt nodig is omdat er geen waarde is, dan ligt je script al met de pootjes omhoog omdat de $_POST variabelen niet bestonden.
Check dus of de $_POST['email'] en $_POST['wachtwoord'] wel bestaan (met isset()) en controleer daarna wat de inhoud is van die $_POST waardes (of zo je wilt van $email en $wachtwoord.
Overigens ben ik persoonlijk dan ook geen fan van gewoon mysql_real_escape_string klakkeloos te gebruiken. Wat mij betreft is het beter om echt de inhoud te controleren, zodat als er een poging is om bijvoorbeeld script of sql code te injecteren dan kan je dat ook opmerkingen en er iets mee doen (loggen, aangifte doen, ip adressen blokkeren, users blokkeren etc etc).