Ik ben een systeem aan het maken voor een bedrijf waarbij ik zoveel mogelijk wil voorkomen dat hackers het systeem in kunnen komen. Ik weet dat dit onmogelijk is als iemand het echt op je gemunt heeft, maar alle beetjes helpen denk ik dan maar.
Ik ben van plan om op de volgende manieren te werk te gaan:
1. gebruiker logt in waarbij bcrypt hashes van het ingevoerde wachtwoord en de hash die in de db staat worden vergeleken.
2. als de hashes kloppen worden er session variabelen aangemaakt met gegevens van de gebruiker. Zie:
3. om te controleren of een gebruiker is ingelogd voordat de pagina wordt getoond gebruik ik:
[script]
<?php
if(!isset($_SESSION['gebruikers_id''])){
echo "<p>U heeft geen toegang</p>";
exit;
}
?>
[/script]
Naast deze 3 punten wil ik de user agent opslaan in een sessie variabele als de gebruiker inlogt. Op elke volgende pagina controleer ik of de user agent hetzelfde is gebleven anders vernietig ik de sessie.
Denken jullie dat ik zo goed op weg ben, of ben ik hier verkeerd bezig en/of hebben jullie nog tips?
Waarom zou je zoveel willen opslaan in SESSIONS? Onthoud dat SESSION eigenlijk gewoon COOKIES zijn (maar dan server side) maar evengoed uit te lezen door de gebruiker.
Dankzij jouw zou je op een slimme manier dus al een naam, id en emailadres in handen kunnen krijgen.
Haal deze gewoon uit de database wanneer je ze nodig hebt!
Je zou een hash kunnen maken van de useragent en deze controleren. De useragent is vrij uniek, maar geef deze dan niet gewoon weg, maar gebruik hiervoor bijvoorbeeld ook bcrypt.
Sla deze useragent op in een aparte tabel en ruim deze op na een bepaalde tijd inactief.
Daarnaast zou je nog bij elke pagina die je opent een unieke string kunnen opslaan in je database en session en deze met elkaar vergelijken. Als iemand de string in handen krijgt is deze maar beperkt geldig.
Waarom zou je zoveel willen opslaan in SESSIONS? Onthoud dat SESSION eigenlijk gewoon COOKIES zijn (maar dan server side) maar evengoed uit te lezen door de gebruiker.
Dankzij jouw zou je op een slimme manier dus al een naam, id en emailadres in handen kunnen krijgen.
Haal deze gewoon uit de database wanneer je ze nodig hebt!
Een $_SESSION['email_adres'] wordt gewoon op de server opgeslagen hoor. Die ziet de client dus niet. Het enige dat de client ziet, is de hash van de sessie-ID.
Wat wél mogelijk is, is bijvoorbeeld session hijacking: wie de cookie met de sessie-ID in handen krijgt, kan de sessie kapen.
Wat je daarom om te beginnen moet doen, is HTTPS met SSL gebruiken. Dat maakt het aftappen van het HTTP-verkeer bijna onmogelijk, waardoor ook de cookie met de sessie-ID niet zo makkelijk in verkeerde handen kan vallen.
Wat je daarnaast kunt doen, is het raden van een geldige sessie-ID moeilijker maken. Standaard is het namelijk slechts een MD5-hash. Daarvan kun je om te beginnen een langere en dus sterkere SHA-1-hash maken:
<?php
// MD5 (128 bits) vervangen door SHA-1 (160 bits)
ini_set('session.hash_function', '1');
// PHP-sessie starten of hervatten
session_start();
?>
Wil je er voor eens en altijd van af zijn, dan doe je dat in php.ini:
; Select a hash function for use in generating session ids.
; Possible Values
; 0 (MD5 128 bits)
; 1 (SHA-1 160 bits)
; This option may also be set to the name of any hash function supported
; by the hash extension. A list of available hashes is returned by the
; hash_algos() function.
; http://php.net/session.hash-function
session.hash_function = 1
In PHP >= 5.3.0 kun je er nog een schepje bovenop gooien door MD5 of SHA-1 te vervangen door een variant van SHA-2, bijvoorbeeld met een 512-bits hash:
<?php
// MD5 (128 bits) vervangen door SHA-2 (512 bits)
ini_set('session.hash_function', 'sha512');
// PHP-sessie starten of hervatten
session_start();
?>
@Ozzie, Ik bedoelde session haijacking. Je moet er niet vanuit gaan dat als je je gegevens in een sessie opslaat, dat deze dan veilig zijn. Mijn mening is dat je niet alles uit een database moet lezen en dan in een session opslaan. Haal het gewoon uit de database als je het nodig hebt.
<?php
$_SESSION['gebruikersnaam'] = 'Ozzie';
$_SESSION['password'] = '12345';
?>
Bedankt voor de reacties!
Ik heb even snel iets gemaakt:
functions.php:
<?php
//sla user agent encrypted op in db
//plaats deze functie nadat $_SESSION['gebruikers_id'] is aangemaakt
function save_ua() {
$encrypted_ua = password_hash($_SERVER['HTTP_USER_AGENT'], PASSWORD_BCRYPT);
$save_ua = $database->prepare('UPDATE gebruikers SET user_agent=:user_agent WHERE gebruikers_id = :gebruikers_id');
$save_ua->execute(array('user_agent' => $encrypted_ua, 'gebruikers_id' => $_SESSION['gebruikers_id']));
}
//controleer of user agent zelfde is als in db, anders sessie destroyen
function check_ua() {
$encrypted_ua = password_hash($_SERVER['HTTP_USER_AGENT'], PASSWORD_BCRYPT);
$check_ua = $database->prepare('SELECT user_agent FROM gebruikers WHERE gebruikers_id = :gebruikers_id');
$check_ua->execute(array('gebruikers_id' => $_SESSION['gebruikers_id']));
$ua = $check_ua->fetch();
if (!(password_verify($encrypted_ua, $ua['user_agent']))) {
$_SESSION = array();
destroy_session();
header('Location: index.php');
exit;
}
}
//genereer sessie id en plaats deze in sessie variabele + database
//plaats deze functie nadat $_SESSION['gebruikers_id'] is aangemaakt
function set_session_id() {
$session_id = bin2hex(openssl_random_pseudo_bytes(16));
$set_session_id = $database->prepare('UPDATE gebruikers SET session_id=:session_id WHERE gebruikers_id = :gebruikers_id');
$set_session_id->execute(array('session_id' => $session_id, 'gebruikers_id' => $_SESSION['gebruikers_id']));
$_SESSION['session_id']=$session_id;
}
//controleer of sessie id variabele en databse sessie id overeenkomen en maak daarna een nieuwe aan
function check_session_id() {
$session_id=$_SESSION['session_id'];
$check_session_id = $database->prepare('SELECT session_id FROM gebruikers WHERE gebruikers_id = :gebruikers_id');
$check_session_id->execute(array('gebruikers_id' => $_SESSION['gebruikers_id']));
$session_id_db = $check_session_id->fetch();
if ($session_id!=$session_id_db['session_id']) {
$_SESSION = array();
destroy_session();
header('Location: index.php');
exit;
} else {
$session_id = bin2hex(openssl_random_pseudo_bytes(16));
$set_session_id = $database->prepare('UPDATE gebruikers SET session_id=:session_id WHERE gebruikers_id = :gebruikers_id');
$set_session_id->execute(array('session_id' => $session_id, 'gebruikers_id' => $_SESSION['gebruikers_id']));
$_SESSION['session_id']=$session_id;
}
}
?>
De set functies roep ik aan nadat de gebruiker succesvol inlogt. De check functies zet ik boven iedere pagina waar een gebruiker daarna naar toe kan.
Daarnaast heb ik als de gebruiker uitlogt:
Tja... ik weet niet hoor, maar als je iemand password in een sessie gaat zetten, ben je niet helemaal slim bezig lijkt mij. Een naam e.d. kun je gewoon in sessie zetten. Waarom zou je die iedere keer opnieuw gaan ophalen?
Toevoeging 2:
Daarnaast begrijp ik Micheal- dat sessie variabelen niet als veilig moeten worden beschouwd, dus zal ik enkel de gebruikers_id uit de database in een sessie variabele opslaan. De rest vraag ik iedere keer met een query op.
@Ozzie, Een wachtwoord opslaan in een sessie is niet slim, dat weet jij en ik. Een naam zou nog kunnen, een gebruikersnaam/emailadres vind ik weer van niet. Als deze zijn te achterhalen hoef je alleen nog het wachtwoord te raden (die lang niet allemaal even moeilijk zijn).
Ik durf ook te wedden dat wel eens het gebruikers id wordt gebruikt als inlog controle (Davey?).
Ik vind dat je met sessies het zelfde om moet gaan als cookies (betreft veiligheid).
Sorry dat ik je wachtwoord hier poste :P
Ja, niet meer doen hoor! Nu moet ik overal al m'n wachtwoorden aanpassen. Ik heb besloten om nu meer tekens te gebruiken. Eerst waren het er 6, nu doe ik er voortaan 10. Het zijn allemaal 4'en, maar uiteraard ben ik niet zo dom om te vertellen in welke volgorde ze staan!