web-dev-qa-db-fra.com

Quelle est la meilleure méthode pour empêcher une attaque par force brute?

J'ai ma page de connexion et bien sûr, je veux empêcher les attaques par force brute et causer moins de retard aux utilisateurs lorsqu'ils se connectent.

Actuellement, vous saisissez votre nom d'utilisateur et votre mot de passe pour vous connecter.

J'envisage d'implémenter un reCAPTCHA . Cependant, cela apparaît lors de la connexion après 3 tentatives infructueuses.

Ma question est:

  1. Sur quoi basez-vous cette tentative? Des adresses IP? Il peut toujours être caché ... nom d'utilisateur? Et s'ils essaient un utilisateur qui n'existe pas?

  2. Quelle serait la meilleure méthode pour compter les tentatives de connexion infructueuses?

29
lecardo

Les sessions ne sont pas fiables car elles reposent sur des cookies, les CAPTCHA sont régulièrement cassés [y compris ReCAPTCHA]. La seule méthode fiable est d'une simplicité trompeuse: poser une question. N'utilisez pas une question mathématique parce que les ordinateurs sont étonnamment aptes à les résoudre pour une raison quelconque. Les bons vieux standby sont des choses comme:

  • Quel est le quatrième mot du sixième paragraphe sur cette page ?
  • Quel est le nom de l'auteur de ce site? [indice]

C'est stupide, facile à mettre en œuvre et très difficile à résoudre pour une machine.

En ce qui concerne le forçage, essayez d'ajouter deux champs à votre table utilisateur, 'first_failed_login' [INTEGER horodatage unix ou DATETIME] et 'failed_login_count'. [INTEGER]

<?php
$bad_login_limit = 3;
$lockout_time = 600;

$first_failed_login, failed_login_count; // retrieve from DB

if(
    ($failed_login_count >= $bad_login_limit)
    &&
    (time() - $first_failed_login < $lockout_time)
) {
  echo "You are currently locked out.";
  exit; // or return, or whatever.
} else if( /* login is invalid */ ) {
  if( time() - $first_failed_login > $lockout_time ) {
    // first unsuccessful login since $lockout_time on the last one expired
    $first_failed_login = time(); // commit to DB
    $failed_login_count = 1; // commit to db
  } else {
    $failed_login_count++; // commit to db.
  }
  exit; // or return, or whatever.
} else {
  // user is not currently locked out, and the login is valid.
  // do stuff
}

Ainsi, votre système de connexion ne reconnaîtra que 3 tentatives de connexion par utilisateur toutes les 10 minutes.

47
Sammitch

Ne vous fiez pas aux sessions ou aux cookies, ceux-ci font confiance au client et vous ne devez JAMAIS faire confiance au client. J'ai créé une classe qui s'occupe de la protection contre les attaques par force brute en PHP.

https://github.com/ejfrancis/BruteForceBlocker

il enregistre toutes les connexions ayant échoué à l'échelle du site dans une table db, et si le nombre de connexions ayant échoué au cours des 10 dernières minutes (ou quel que soit le délai que vous choisissez) dépasse une limite définie, il applique un délai et/ou une exigence de captcha avant de vous reconnecter.

exemple:

 //build throttle settings array. (# recent failed logins => response).

 $throttle_settings = [

         50 => 2,            //delay in seconds
         150 => 4,           //delay in seconds
         300 => 'captcha'    //captcha 
];


 $BFBresponse = BruteForceBlocker::getLoginStatus($throttle_settings); 

//$throttle_settings is an optional parameter. if it's not included,the default settings array in BruteForceBlocker.php will be used

 switch ($BFBresponse['status']){

    case 'safe':
         //safe to login
         break;
     case 'error':
         //error occured. get message
         $error_message = $BFBresponse['message'];
         break;
     case 'delay':
         //time delay required before next login
         $remaining_delay_in_seconds = $BFBresponse['message'];
         break;
     case 'captcha':
         //captcha required
         break;

 }
3
ejfrancis

Essayez de vérifier que vous avez affaire à un vrai navigateur. Peut-être que quelques-uns Java avec des noms de fonction aléatoires ou quelque chose pourraient bloquer beaucoup de scripts simples, à moins qu'ils contrôlent à distance un vrai navigateur (ce qui n'est pas si rare), ou évaluer le js/css correctement dans le script de raclage.

Je recommanderais de lire plus loin sur ce sujet et de tester votre solution par rapport à python mechanize ou à d'autres outils de scraper bien connus.

Mais on est sûr, il n'y a pas de vraie solution contre les attaques automatiques.

2
enthus1ast