Beste,
Ik ben bezig met een 2FA systeem.
Misschien kent u dat wel van Google Authenticator. Dat een gebruiker dat wil inloggen, eerst een email krijgt waar een code in staat en vervolgens die code moet invoeren om uiteindelijk in te kunnen loggen.
Nu ben ik bezig met zo'n systeem, maar ik wil geen externe API'S gebruiken. (Bijv. Google Authenticator)
In plaats daarvan wil ik een eigen systeem maken.
Maar hoe zal ik dit het best aanpakken?
Een token genereren natuurlijk, met $token = random_bytes(5).
En een verloopdatum met $expires = date(U) + 300;
Zijn er nog extra kolommen die ik moet toevoegen in de MYSQLI database, om de veiligheid van dit systeem te verbeteren, of nog andere (veiligheids)suggesties?
Ja.
Ik heb geprobeerd om het met hash te doen (password_hash($password, PASSWORD_DEFAULT)), maar toen kon ik ineens niet meer inloggen. Ik ga daar ook denk ik nog een topic over starten.
[size=xsmall]Toevoeging op 11/03/2019 19:47:20:[/size]
Maar nu heb ik weer hetzelfde probleem met het document die de gebruiker zou moeten inloggen, via 2FA.
Het document gaat eerst de ingevoerde code dehashen en daarna controleren. Zoja, dan wordt de gebruiker ingelogd via sessions. Maar, zoals "gebruikelijk", doen de sessions het dan niet...
Dit is de (volledige) code:
<?php
session_start();
require 'connection.inc.php';
if(!isset($_GET['request'])) {
if($_GET['request'] !== 'valid') {
header('../2FAVerify.php?error=invalidrequest');
exit();
}
}
else if(!isset($_POST['2FAVerifyCode'])) {
header('Location: ../2FAVerify.php?error=invalidrequest');
exit();
}
else if(empty($_POST['2FACode'])) {
header('Location: ../2FAVerify.php?request=valid&error=emptyfields');
exit();
}
else {
htmlspecialchars($code = $_POST['2FACode']);
htmlspecialchars($email = $_GET['email']);
$sql = 'SELECT * FROM autorisatie WHERE uid=?;';
$stmt = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmt, $sql)) {
echo 'mysqli check statement voor uid is mislukt';
exit();
}
else {
mysqli_stmt_bind_param($stmt, "s", $email);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if($row = mysqli_fetch_assoc($result)) {
// code dehashen
$codeCheck = password_verify($code, $row['token']);
// controleren wel / niet goed
if($codeCheck == false) {
header('Location: ../2FAVerify.php?error=wrongcode&request=valid&email='.$email);
exit();
}
// wel goed
else if ($codeCheck == true) {
// de records van autorisatie verwijderen
$sqlDelete = 'DELETE FROM autorisatie WHERE uid=?;';
$stmtDelete = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmtDelete, $sqlDelete)) {
echo 'MYSQLI delete statement is mislukt';
exit();
}
else {
mysqli_stmt_bind_param($stmtDelete, "s", $email);
mysqli_stmt_execute($stmtDelete);
$result = mysqli_stmt_get_result($stmtDelete);
if(!$result) {
// gebruiker inloggen
$sqlLogin = 'SELECT * FROM employee WHERE Mail=?;';
$stmtLogin = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmtLogin, $sqlLogin)) {
echo 'MYSQLI login statement is mislukt';
exit();
}
else {
mysqli_stmt_bind_param($stmtLogin, "s", $email);
mysqli_stmt_execute($stmtLogin);
$resultLogin = mysqli_stmt_get_result($stmtLogin);
if($rowLogin = mysqli_fetch_assoc($resultLogin)) {
$_SESSION['User'] = $rowLogin['UName'];
$_SESSION['ID'] = $rowLogin['ID'];
header("location:../wellcome.php?uid=".$row['UName']);
exit();
}
else {
echo error_get_last();
exit();
}
}
}
else {
header('Location: ../login.php?error=unknown');
exit();
}
}
}
else if($codeCheck == false) {
header('Location: ../2FAVerify.php?error=wrongcode&request=valid&email='.$email);
exit();
}
}
else {
header('Location: ../2FAVerify.php?error=nouser&request=valid&email='.$email);
exit();
}
}
}
?>
[size=xsmall]Toevoeging op 11/03/2019 19:47:37:[/size]
Zoals ik al zei: Bewandel het pad eens naar waar de sessies aangemaakt worden. Mogelijk wordt er niet aan een if-statement voldaan of bestaat $rowLogin niet.
Ik heb als vervanging van de redirection naar de welkom pagina, print_r($_SESSION['User']) neergezet.
En ik zie gewoon dat de gebruikersnaam keurig wordt weergegeven.
Dus dan ga ik ervan uit dat geen enkele if statement, niet is gelukt.
En alle andere prepared statements, werken gewoon.
Niet even zomaar ergens vanuit gaan, maar dit is gewoon even je script debuggen:
Zet in elke if-statement een verschillende echo neer, en kijk aan de hand van die echo's welke route er bewandeld wordt en of die ook inderdaad uitkomt in die if-statement van lijn 64.
Ik heb nu dit neergezet:
<?php
else {
htmlspecialchars($code = $_POST['2FACode']);
htmlspecialchars($email = $_GET['email']);
$sql = 'SELECT * FROM autorisatie WHERE uid=?;';
$stmt = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmt, $sql)) {
echo 'mysqli check statement voor uid is mislukt';
exit();
}
else {
mysqli_stmt_bind_param($stmt, "s", $email);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if($row = mysqli_fetch_assoc($result)) {
// code dehashen
$codeCheck = password_verify($code, $row['token']);
// controleren wel / niet goed
if($codeCheck == false) {
header('Location: ../2FAVerify.php?error=wrongcode&request=valid&email='.$email);
exit();
}
// wel goed
else if ($codeCheck == true) {
// de records van autorisatie verwijderen
$sqlDelete = 'DELETE FROM autorisatie WHERE uid=?;';
$stmtDelete = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmtDelete, $sqlDelete)) {
echo 'MYSQLI delete statement is mislukt';
exit();
}
else {
echo "ja1 <br>";
mysqli_stmt_bind_param($stmtDelete, "s", $email);
mysqli_stmt_execute($stmtDelete);
$result = mysqli_stmt_get_result($stmtDelete);
if(!$result) {
echo "ja2 <br>";
// gebruiker inloggen
$sqlLogin = 'SELECT * FROM employee WHERE Mail=?;';
$stmtLogin = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmtLogin, $sqlLogin)) {
echo 'MYSQLI login statement is mislukt';
exit();
}
else {
echo "ja3 <br>";
mysqli_stmt_bind_param($stmtLogin, "s", $email);
mysqli_stmt_execute($stmtLogin);
$resultLogin = mysqli_stmt_get_result($stmtLogin);
if($rowLogin = mysqli_fetch_assoc($resultLogin)) {
$user = $rowLogin['UName'];
$_SESSION['User'] = $user;
echo "ja4 <br>";
exit();
}
else {
echo error_get_last();
exit();
}
}
}
else {
header('Location: ../login.php?error=unknown');
exit();
}
}
}
else if($codeCheck == false) {
header('Location: ../2FAVerify.php?error=wrongcode&request=valid&email='.$email);
exit();
}
}
else {
header('Location: ../2FAVerify.php?error=nouser&request=valid&email='.$email);
exit();
}
}
}
?>
en ik zie:
ja1
ja2
ja3
ja4
Is er nog een programma, waarmee het mogelijk is om elke php line te debuggen en te pauzeren etc?
Net zoals het bij javascript mogelijk is met zulke "break points"