Hallo,

Ik heb een registratieformulier aangemaakt, en gebruikers kunnen hun gebruikersnaam en wachtwoord gewoon opgeven. En deze worden dan in de mysql database opgeslagen.

Ik gebruik niet meer dan volgende regel hiervoor.
mysql_query("INSERT INTO users (username, password) VALUES ('$username','$password')");

Maar de wachtwoorden worden gewoon als tekst opgeslagen in mijn mysql tabel(varchar). Hoe kan ik dit beter beveiligen zodat het wachtwoord gehashed word. En hoe unhash in het terug zodat ze nog wel steeds kunnen aanmelden?

Thanks!
Dat zorgt er voor dat het 2 tot de 12e macht keer een computatie doet. Voor het hashen van wachtwoorden wil je een relatief traag algoritme gebruiken. Bij Bcrypt kan je dynamisch de traagheid aanpassen door de cost parameter aan te passen
Het moet voor Bcrypt een waarde tussen 4 en 31 zijn. 2^12=4096. Die array is optioneel, de standaard cost is 10.

Nu je op een veilige manier wachtwoorden hast stel ik voor dat je switched van mysql_ functies naar de mysqli_ functies zodat je gebruik kunt maken van prepared statements. Het is netter en als je jezelf aanleert om altijd prepared statements te gebruiken is de kans dat je sql injecties mogelijk maakt kleiner.
<?php
include("password.php");
session_start();
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);

mysql_connect("localhost", "root","***") or die(mysql_error()); //Connect to server
mysql_select_db("first_db") or die("Cannot connect to database"); //Connect to database
?>

De functie mysql_real_escape_string() heeft een database connectie nodig. Niet handig om die te gebruiken voordat je connect. PHP gaat nu zelf proberen zonder password te connecten. Meestal met een foutmelding tot gevolg.

escapen van je password bij het inloggen moet je niet doen trouwens.
Je gebruikt de waarde van $_POST['password'] niet in je query.

Stel het password is ' (alleen een single quote).
Na het escapen is het \'

Daarna haal je het gehaste password op. Dat zou de hash van ' moeten zijn.

Als je daarna de hash van \' bepaalt, is dat niet gelijk.
(tenzij je bij het opslaan van het password natuurlijk dezelfde fout maakt)
Ivo P op 09/03/2015 09:17:51

<?php
include("password.php");
session_start();
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);

mysql_connect("localhost", "root","***") or die(mysql_error()); //Connect to server
mysql_select_db("first_db") or die("Cannot connect to database"); //Connect to database
?>

De functie mysql_real_escape_string() heeft een database connectie nodig. Niet handig om die te gebruiken voordat je connect. PHP gaat nu zelf proberen zonder password te connecten. Meestal met een foutmelding tot gevolg.

escapen van je password bij het inloggen moet je niet doen trouwens.

Goede punten. Maar de mysqli extensie gebruiken in combinatie met prepared statements is nog netter. Dan escape je dingen impliciet door waardes als waardes door te geven, niet als delen van de query.

Ivo P op 09/03/2015 09:17:51

Je gebruikt de waarde van $_POST['password'] niet in je query.

Dat willen we ook helemaal niet, het wachtwoord komt niet verder dan PHP.

Ivo P op 09/03/2015 09:17:51

Stel het password is ' (alleen een single quote).
Na het escapen is het \'

Daarna haal je het gehaste password op. Dat zou de hash van ' moeten zijn.

Als je daarna de hash van \' bepaalt, is dat niet gelijk.
(tenzij je bij het opslaan van het password natuurlijk dezelfde fout maakt)


Inderdaad niet gewenst.

Dat willen we ook helemaal niet, het wachtwoord komt niet verder dan PHP.


dat zeg ik ook niet. Ik constateer alleen dat de reden voor het escapen het gebruik ik een query zou zijn. Aangezien dat niet plaats vindt (prima), is het escapen ook overboedig / ongewenst (zie rest)
Even een bijkomende vraag, ik heb een extra veld aangemaakt in mijn users tabel. Namelijk admin, wanneer er in dat veld de waarde "azert" is mogen ze aanloggen, maar ik wil ook de juiste footbooschap vermelden wanneer de gebruikersnaam, wachtwoord of dat ze idd access denied krijgen omdat ze geen admin rechten hebben.

Ik denk dat er iets mis is met mijn if else structuur, mogelijk nog iets anders. (mysql zal ik nog aanpassen naar mysqli of pdo) Als ik met de juiste credentials inlog die admin rechten hebben, heb ik geen probleem.
Maar als ik inlog met een gebruikersnaam die niet bestaat, krijg ik gewoon en wit scherm. Hetzelfde als ik inlog met een acccount die wel bestaat maar geen admin is?

Alvast bedankt!

<?php
session_start();
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
$bool = true;

mysql_connect("localhost", "ok", "ok") or die (mysql_error());
mysql_select_db("first_db") or die ("Cannot connect to database");
$query = mysql_query("Select * from users WHERE username='$username'");
$exists = mysql_num_rows($query);
$table_users = "";
$table_password = "";
if($exists > 0)
{
while($row = mysql_fetch_assoc($query))
{
$table_users = $row['username'];
$table_password = $row['password'];
$admin = $row['admin'];
}
if (($admin =="azert"))
{

if(($username == $table_users) && ($password == $table_password) && ($admin == "azert"))
{

if($password == $table_password)
{
$_SESSION['user'] = $username;
$_SESSION['admin'] = $admin;
header("location: home.php");
}
else

{
Print '<script>alert("Incorrect username!");</script>';
Print '<script>window.location.assign("login.php");</script>';
}
}
else
{
Print '<script>alert("Incorrect Password!");</script>';
Print '<script>window.location.assign("login.php");</script>';
}
}
else
{
Print '<script>alert("Acces denied!");</script>';
Print '<script>window.location.assign("login.php");</script>';
}}
?>
Even in jip en janneke taal:

Inloggen is om te bepalen WIE een anonieme gebruiker zou kunnen zijn. Alle gebruikers zijn in den beginne anoniem maar we willen niet dat iedereen overal zomaar bij kan. Daarom willen we gebruikers identificeren aan de hand van een gebruikersnaam/email en wachtwoord.
Daarna is een anonieme gebruiker in eens een bekende gebruiker geworden en kunnen we uit de database lezen welke rechten (of rollen) de gebruiker heeft.

Bovenstaande brengt ons op het logische punt dat je altijd eerst gaat inloggen om de identiteit te achterhalen van de gebruikers en pas daarna ga je bepalen welke rechten ze hebben.


dus:
<?php
if($username == $table_users && $password == $table_password)
{
$_SESSION['user'] = $username;
$_SESSION['admin'] = $admin;

if($admin == "azert")
{
header("location: admin.php");
} else {
header("location: home.php");
}
}
?>

[size=xsmall]Toevoeging op 09/03/2015 14:00:11:[/size]

Ik zou je foutmeldingen beperken tot 'Combinatie van gebruikersnaam en wachtwoord onjuist.'. Dit om hackers niet de informatie te geven dat ze bijvoorbeeld de gebruikersnaam al geraden hebben.

[size=xsmall]Toevoeging op 09/03/2015 14:05:04:[/size]

Een access denied pagina zou ik hooguit tonen aan gebruikers die
a) reeds ingelogd zijn
b) onvoldoende rechten hebben om de pagina te bekijken

Deze pagina mag ook een normale webpagina zijn die netjes de mededeling 'Onvoldoende rechten' laat zien.

Voor gebruikers die niet zijn ingelogd zou ik doorsturen naar de loginpagina.
Ronnie Peeters op 09/03/2015 13:15:12

Ik denk dat er iets mis is met mijn if else structuur, mogelijk nog iets anders. (mysql zal ik nog aanpassen naar mysqli of pdo) Als ik met de juiste credentials inlog die admin rechten hebben, heb ik geen probleem.

En daarnaast is je if/else-structuur inderdaad niet goed. Verbeter je het inspringen, dan zie je dat if ($admin == "azert") bij false (dus de gebruiker is geen admin) altijd eindigt in inloggen:

<?php
if ($exists > 0) {
    while($row = mysql_fetch_assoc($query)) {
        $table_users = $row['username']; 
        $table_password = $row['password']; 
        $admin = $row['admin'];
    }
    if ($admin == "azert") {
        if(($username == $table_users) && ($password == $table_password) && ($admin == "azert")) {
            if ($password == $table_password) {
                $_SESSION['user'] = $username; 
                $_SESSION['admin'] = $admin; 
                header("location: home.php"); 
            } else {
                print '<script>alert("Incorrect username!");</script>'; 
                print '<script>window.location.assign("login.php");</script>'; 
            }
        } else {
            print '<script>alert("Incorrect Password!");</script>'; 
            print '<script>window.location.assign("login.php");</script>'; 
        }
    } else {
        print '<script>alert("Acces denied!");</script>'; 
        print '<script>window.location.assign("login.php");</script>'; 
    }
}
?>
Voor wat dient die exit() in het volgende?

<?php // kleurtjes

// vervang regels 19 t/m 27 door dit
if(($username == $table_users) && password_verify($password, $table_password))
{
$_SESSION['user'] = $username; // heb je geen id dat je kan gebruiken? is wat netter
header("location: home.php");
exit();
}
?>

Alvast bedankt!
bij de header() functie geef je aan dat de client doorgestuurd wordt maar hiermee wordt het script nog niet beƫindigd. Je script loopt na het wijzigen van de headers (dat een onderdeel is van je response) gewoon door omdat er ook gewoon content meegegeven kan worden wat enkel bij een redirect geen zin heeft.

Reageren