Hey allemaal,

Ik ben pas een half jaartje bezig met PHP en heb nu enige ervaring opgedaan. Maar ik had een vraag betreffende een inlogsysteem wat ik aan het opzetten ben. Ik wil graag een functie erin toevoegen dat als je na 3 inlogpogingen niet de juiste combinatie van username en password hebt weten in te voeren dat dan je account voor 30 minuten geblokkeerd wordt.

Alleen ik heb echt geen idee hoe ik zo'n functie op moet bouwen. Heeft iemand hier ervaring mee of weet iemand een tutorial want via google kan ik niks vinden qua tuts of scripts waar het in voorkomt.

NB, ik draai nog op een oudere versie van php, namelijk 4.4.4.

Alvast bedankt!
Groet, Justin Streuper

<?php
if($_SERVER['METHOD_REQUEST'] == 'POST')
{
	// Kijken of er niet iets is vergeten anders een error
	if(!isset($_POST['username']))
	{
		echo 'U bent vergeten uw gebruikersnaam in te vullen<br>';
		echo $login_form;
	}
	else
	{
		if(!isset($_POST['password']))
		{
			echo 'U bent vergeten uw wachtwoord in te vullen<br>';
			echo $login_form;
		}
		else
		{
	
			// Alles uit de database halen
			$sql = mysql_query("SELECT
									gebruikersnaam, wachtwoord 
								FROM
									gebruikers
								WHERE
									gebruikersnaam = '".mysql_real_escape_string($_POST['username'])."'
								AND
									wachtwoord = '".mysql_real_escape_string(md5($_POST['password']))."'"));
									
			// Kijken of de query is gelukt
			if(mysql_query($sql))
			{
				$sql1 = mysql_query("SELECT * FROM suspended WHERE ip = '".$_SERVER['REMOTE_ADDR']."'")
				if(mysql_num_rows(sql1) == 0)
				{
					$sql3 = mysql_query("INSERT INTO suspended (pogingen, ip) VALUES ('1', '" .$_SERVER['REMOTE_ADDR']. "')");
				}
				elseif(mysql_num_rows(sql1) >= 1)
				{
					$sql3 = mysql_query("UPDATE suspended SET pogingen = pogingen +1 WHERE ip = '".$_SERVER['REMOTE_ADDR']."'")
				}
				else
				{
					echo 'Er is helaas een fout opgetreden';
				}
			}
			else
			{
				if(mysql_num_rows($sql) == '')
				{
					echo 'Uw wachtwoord / gebruikersnaam combinatie is niet correct<br>';
					echo $login_form;
				}
				else
				{
					$_SESSION['login'] = $_POST['username'];
					
					// Doorsturen naar de volgende pagina
					header('Location: next.php');
				}
			}
		}
	}			
}
else
{
	// Kijken of je in de tabel suspended voorkomt
	$sql2 = mysql_query("SELECT * FROM suspended WHERE ip = '".$_SERVER['REMOTE_ADDR']."'");
	if(mysql_num_rows($sql2) > 0)
	{
		echo 'Uw heeft nog '.(3 - mysql_num_rows($sql2)).' pogingen over<br>';
		
		// Kijken of je nog wel meer als 0 pogingen over hebt zoja form echoen anders niks
		if(3 - mysql_num_rows($sql2) ! 0)
		{
			echo $login_form;
		}
	}
	else
	{
		// Het formulier
		echo $login_form;
	}
}

// Het login formulier
$login_form = '<form action="" method="post">
	Gebruikersnaam: <input name="username" type="text"><br>
	Wachtwoord: <input name="password" type="password"><br>
	<input type="submit" value="Log in">
</form>';
?>



Misschien is dit iets weet niet of hij foutloos is hoor ;)
Lijkt een beetje op mijn snippet.
Die van mij werkt alleen met functies maar de systemen zijn in werking hetzelfde.

De opzet is niet moeilijk:

1. Als de login fout is -> kijk of IP al in database bestaat
1-> ja: Update query uitvoeren om de count met 1 te verhogen en de datetime aan te passen.
1->nee: Insert query uitvoeren om de ip, count en datetime in de database op te nemen.

2. Vervolgens schrijf je een functie die controleert of de login al 3x foutief is ingevoerd, zo ja, controleer de tijd van de laatste login poging, trek deze af van de huidige tijd, als het onder de 15 minuten (bijv.) dan mag diegene nog niet opnieuw inloggen. Is het over de 15 minuten, dan mag het wel, verwijder dan de IP uit de database of zorg dat de functie werkt met de tafel van 3 (1x3=3, 2x3=6, 3x3=9 etc.) zo behoud je namelijk wel het ip adres in de database en kan je dit evt weergeven in een logfile.

Daarnaast dien je bij het laden van de pagina ook te kijken of de loginpoging niet veroudert is (bijv. van gisteren). moet je de count resetten of de hele rij uit de database gooien aangezien het niet eerlijk zou zijn om als je vandaag 2x fout inlogt en vervolgens op safe denkt te spelen en het morgen opnieuw te proberen, en dan voor een onaangename verassing komen te staan dat je ineens 3x foutief hebt ingelogd. Nu is dat in dit geval niet erg want het scheelt een kwartier, maar als je van plan bent het account te blokkeren o.i.d. is dat wel lullig..

Hieronder mijn snippet code:


<?php
	
	function connect()
		{
			$username	=	"";
			$password	=	"";
			$host		=	"";
			$dbnaam		=	"";
			
			mysql_connect($host, $username, $password) or die ("connection failed");
			mysql_select_db($dbnaam) or die ("Database could not be found");	
		}
	
	function first_attempt()
		{
			// Als ip adres niet voorkomt, invoeren in database
			$sql	=	"INSERT 
							INTO 
								iplog 
								(
								 	id,
									ipnummer,
									tijd,
									poging
								)
							VALUES
								(
									'',
									'".$_SERVER['REMOTE_ADDR']."',
									'".time()."',
									'1'
								)";
			$result	=	mysql_query($sql);
			
			if($result)
				{
					echo 'Foutieve inlogpoging';
				}else{
					echo 'Er ging iets fout, probeer opnieuw.';
				}
		}
		
		function following_attempts()
		{
			$query	=	mysql_query("
								SELECT
									id,
									ipnummer,
									tijd,
									poging
								FROM
									iplog
								WHERE
									ipnummer = '".$_SERVER['REMOTE_ADDR']."'");
			
			while($record = mysql_fetch_object($query))
				{
					$id			=	$record->id;
					$ipnummer	=	$record->ipnummer;
					$tijd		=	$record->tijd;
					$poging		=	$record->poging;
				}//sluiten while
				$pogingoptellen	=	$poging+1;
				
				$sql	=	"UPDATE
										iplog
									SET
										tijd='".time()."',
										poging='".$pogingoptellen ."'
									WHERE
										ipnummer = '".$_SERVER['REMOTE_ADDR']."'
								";
					$result	=	mysql_query($sql);
					
					if($result)
						{
							echo 'Foutieve inlogpoging';
						}else{
							echo 'Er ging iets fout, probeer opnieuw.';
						}
		}
		
		
	if($_SERVER['REQUEST_METHOD'] == 'POST')
		{
			// connect database
			connect();
			
			if($_POST['naam'] != 'naam')
				{
					$query2	=	mysql_query("
								SELECT
									id,
									ipnummer,
									tijd,
									poging
								FROM
									iplog
								WHERE
									ipnummer = '".$_SERVER['REMOTE_ADDR']."'");
					
					while($record = mysql_fetch_object($query2))
						{
							$id			=	$record->id;
							$ipnummer	=	$record->ipnummer;
							$tijd		=	$record->tijd;
							$poging		=	$record->poging;
						}//sluiten while

					if(mysql_num_rows($query2) >= 0)
						{
							if($poging >= 3)
								{
									// Meer dan 3x foutief, ban voor 30 sec.
									$timestamp 	=	time();
									$difference = 	$timestamp - $tijd;
									echo $difference;
									echo '<br>';
									echo '<br>';
									if($difference >= "120")
										{
											echo 'Er zijn 2 minuten voorbij!';
										}else{
											echo 'De 2 minuten zijn nog niet voorbij...';
										}
									
								}else
									{
										if(mysql_num_rows($query2) == 0)
											{
												first_attempt();
											}else{
												following_attempts();
											}
									}
						}
				}
			
		}
	
	
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>

<body>
	<form action="" method="post" name="test">
    Naam <input type="text" name="naam" />
    <input type="submit" name="submit" value="test" />
    </form>

</body>
</html>


Let wel: Dit systeem is zeker niet waterdicht en alleen geschreven door mij om de werking ervan te testen. Het bevat geen mysql_real_escape_strings of andere beveiligingen tegen injection o.i.d.

Het is ook geen werkend login systeem. Het is de bedoeling, dat je in de database een tabel aanmaakt met de volgende waarden:

tabel:
+ id INT
+ ipnummer VARCHAR
+ tijd DATETIME (YYYY-MM-DD HH-II-SS)
+ poging INT

De waarden zijn ook niet erg goed gekozen :P.. Maargoed zoals ik zei, snel geschreven. Voor als je gaat testen, je ziet in het formulier alleen input field "naam" en een submit button. Hij checkt op de naam die je invoert. Het goede antwoord is namelijk naam, kleine letters (check het script).

Het script is niet volledig dus moet hier en daar verbeterd worden.
he bedankt he ik zal er eens naar kijken en proberen in mijn inlog script te verwerken. miss dat ik wel op gebruikersnaam ga bannen in plaats van ip. Op ip is namelijk best makkelijk te omzeilen door gebruik van proxy etc.
iig bedankt he. Gisteravond was ik niet online vanwege sport dus heb er niet op kunnen reageren.
Ip is juist niet te omzeilen. Remote_addr kan je naar mijn weten niet bewerken. Op gebruikersnaam bannen is een beetje lullig aangezien ik dan op jou account 3x foutief kan gaan inloggen en dat jij dan vervolgens een ban krijgt ;)!
he bedankt voor de tip he.

Idd het zou lullig zijn om het op gebruikersnaam te doen. Volgens mij met Remote_addr haal je het externe ip van de router/modem wat die persoon ook heeft en haalt die op.

Deze kan gereset worden door je router/modem een dag of meer uit te zetten en dan weer aan. Het ip kan dan gewijzigd zijn. Maar voor een hacker om zo lang te wachten is het niet waard.

Je zou een proxy om te proberen een ander ip te krijgen maar remote_addr veranderd dan niet, dat weet ik zeker.

Of het ip na een dag van de router/modem uit hebben staan veranderd weet ik niet zeker vanwege het grote tekort aan ip adressen tegenwoordig. De ISP's kunnen alle ip adressen al op static hebben staan.
Je hebt sowieso altijd hetzelfde ip adres qua REMOTE_ADDR want dit is via de internetleverancier gekoppeld aan jouw model. Daarom is dit het veiligste en is dé manier voor een ban-systeem.

succes!
Justin schreef op 06.09.2009 21:24
Je hebt sowieso altijd hetzelfde ip adres qua REMOTE_ADDR want dit is via de internetleverancier gekoppeld aan jouw model. Daarom is dit het veiligste en is dé manier voor een ban-systeem.

succes!

Behalve als je via proxy's binnenkomt. Dan ban je de proxy.
Hoe dat werkt weet ik verder niet, zou ik eens uit moeten zoeken.
Komt dat vaak voor bij bruteforce aanvallen?
ik ben er mee bezig geweest en het script lijkt te werken. Alleen het invoeren van de tijd in de database werkt niet. Weet jij er iets voor?
op forums zeggen ze dat het met de functie now() kan. nou probeer ik dus toe te passen maar het lukt me weer s niet :S
Oh ik sprak te vroeg ik kom net 5 min na mijn post erachter dat je helemaal niks hoeft te typen. Je kan gewoon van de column tijd een timestamp column maken dan tijdens een update word de tijd automatisch geupdate.

Gelieve Niet Bumpen:

Twee of meer keer achter elkaar in een topic posten heet bumpen. Bumpen is pas na 24 uur toegestaan en kan een reden zijn voor de admins en moderators om een topic te sluiten. Gebruik indien nodig de knop om je tekst aan te passen.

SanThe.

Reageren