Jump to content
Sign in to follow this  
feanor13

[Anti-bruteforce] Verrouillage de fichiers

Rate this topic

Recommended Posts

Salut à tous,

Je suis entrain de créer un système anti-bruteforce et pour cela j'ai besoin de verrouiller un fichier en accès exclusif. Jusque-là, aucun problème. Mais je veux aussi que si une deuxième requête veut accéder à ce fichier alors que celui-ci est verrouillé, la fonction "flock" n'attende pas que le fichier se déverrouille (comme c'est le cas par défaut) mais renvoie une erreur. J'ai donc mis le 3ème paramètre de "flock" à false, mais cela ne fonctionne pas car quand je teste de lancer 2 requête simultanées (avec un sleep suffisamment grand) la 2ème requête attend que la première ait terminée pour s'exécuter.

Je vous donne mon code simplifié:

<?php
$fichier_tentatives = fopen('antibrute/'.$_POST['pseudo'].'.tmp', 'r+');
$block = false;
// pose un verrou exclusif
if(flock($fichier_tentatives,LOCK_EX, $block))
{
//opération à effectuer ...
sleep(10);
}
else
{
exit("Vous ne pouvez pas lancer deux tentatives de connexion simultanément. Réessayez plus tard.");
}
?>

Merci d'avance et @+ !

Share this post


Link to post
Share on other sites

Tu n'as pas bien lu la doc...

Pour que ça ne bloque pas, il faut passer LOCK_NB en deuxième argument (en plus du LOCK_EX, donc LOCK_EX | LOCK_NB). Le troisième argument doit être une référence à une variable qui indiquera si le lock aurait bloqué en l'absence de LOCK_NB, ce qui est redondant avec la valeur de retour de flock et errno a priori...

Voir http://us3.php.net/manual/en/function.flock.php#90547 pour un exemple.

Jacques.

Share this post


Link to post
Share on other sites

Salut,

Merci pour l'exemple, mais cela ne fonctionne toujours pas. Voilà mon code:

<?php
$fichier_tentatives = fopen('antibrute/'.$_POST['pseudo'].'.tmp', 'r+');
// pose un verrou exclusif
if(flock($fichier_tentatives, LOCK_EX | LOCK_NB))
{
sleep(10);
flock($fichier_tentatives, LOCK_UN); // libère le verrou
fclose($fichier_tentatives);
}
else
{
exit("Vous ne pouvez pas lancer deux tentatives de connexion simultanément. Réessayez plus tard.");
}
?>

Je précise que même si je spécifie le paramètre optionnel à false cela ne fonctionne pas.

Merci d'avance et @+

Edited by feanor13

Share this post


Link to post
Share on other sites

Petit problème dans ton fopen, tu ouvres en "r+", il faut que le fichier existe déjà pour que ça marche. Passe en "w" par exemple pour qu'il soit créé à la demande. Note aussi que comme indiqué dans la doc, flock et NFS ne font pas bon ménage. Ce qui veut dire que chez beaucoup d'hébergeurs, en mutualisé et autres solutions ou le disque dur n'est pas local, ça ne marchera pas.

Ce qui d'ailleurs me fait penser qu'il y a encore plus simple: fais juste un fopen en "x" et teste la valeur de retour. Si le fichier n'existe pas, il sera créé, et tout va bien. Si le fichier existe déjà, tu auras une erreur. Evidemment il faut penser à supprimer le fichier une fois que tu as fini (avec unlink).

$lock_filename='/var/tmp/antibrute_'+$pseudo;
$lock_fh=fopen($lock_filename,'x');
if ($lock_fh)
{
// tout va bien, faire traitement
fclose($lock_fh);
unlink($lock_filename);
}
else
{
// lock déjà pris
}

Inconvénient avec cette méthode: s'il y a un problème en cours de route et que le fichier reste, le pseudo en question sera bloqué jusqu'à suppression manuelle du fichier.

Au passage, le nom de fichier qui utilise directement un $_POST['whatever'] c'est très très très dangereux... Si le gars il met des "/" et des ".." il peut casser toutes sortes de choses. Donc bien vérifier/nettoyer avant d'utiliser.

Jacques.

EDIT: ajout incompatibilité avec NFS.

Edited by jcaron

Share this post


Link to post
Share on other sites

Salut,

le problème doit donc venir de l'hébergeur. Merci pour cette précision.

Par contre ta technique ne me convient pas car elle ne me permet pas de sauvegarder le nombre de tentatives de connexion (car il s'agit d'un script de connexion) car le fichier est supprimé après chaque tentative et je ne peux donc pas avertir l'administrateur par mail. Je voulais verrouiller pour éviter que deux requêtes puissent accéder au même fichier. Je pense donc que au lieu de verrouiller, je vais faire comme ceci: A chaque fois qu'une requête sera lancée, j'ouvrirai le fichier, mettrai une valeur à 1 et lorsque l'entier de ma requête sera traité (sleep y compris), je remettrai cette valeur à 0. De plus lorsqu'une requête tentera d'accéder à un fichier, elle vérifiera d'abord que la valeur soit bien à 0, dans le cas contraire je mets un exit().

Que pensez-vous de ma technique ? Des conseils ou améliorations ?

Merci et @+

Share this post


Link to post
Share on other sites

Je ne comprends pas tout... Le but du jeu c'est juste d'empêcher deux personnes de faire la même chose en même temps? Tu crées le fichier de lock au début du traitement, et tu le supprimes quand tu as fini, ça revient exactement au même que les autres méthodes, et c'est plus simple.

Ou j'ai raté un truc?

Jacques.

Share this post


Link to post
Share on other sites

En fait, dans le fichier de lock, j'enregistre aussi le nombre de tentatives pour que à 30 tentatives un email soit automatiquement envoyé à l'administrateur. Je ne supprime donc jamais le fichier.

Je contrôle qu'il est à jour: si oui, j'incrémente le fichier, sinon je mets à jour le fichier. Ce système permet à l'administrateur de prendre des mesures si le quota est dépassé plusieurs fois de suite (par exemple demander au membre de changer son mot de passe). En rajoutant une variable à l'intérieur de mon fichier pour savoir si il est en cours d'utilisation ou non, cela me permet de garder un système (relativement) simple tout en conservant le maximum de fonctionnalités et sans utiliser trop de ressources.

Les autres avantages sont que si il y a interruption, au pire deux requêtes pourront être lancées simultanément mais la connexion ne sera pas bloqué comme avec ton système.

Pour la variable $_POST['pseudo'], ne t'en fais pas, je l'ai sécurisée. C'est juste que j'ai mis un extrait de code. Ce serait trop long sinon ! :whistling:

Donc la méthode "w" ne va pas car elle efface le contenu du fichier.

Alors que penses-tu de ma méthode ? N'hésites pas à me demander des précisions et à faire des suggestions (je suis débutant et preneurs de tout conseils).

Merci à toi et @+

Edited by feanor13

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...