Protección de fuerza bruta en PHP

Si tiene un sistema donde los usuarios pueden suscribirse y elegir sus propias contrase√Īas, probablemente sea un objetivo de ataques de fuerza bruta como un ataque de diccionario . Puede limitar este problema mostrando al usuario qu√© tan segura es su contrase√Īa. Sin embargo, obligar a los usuarios a ingresar una contrase√Īa realmente segura los molestar√°, ya que les gusta algo que pueden recordar.

Otra forma de muro que puede colocar es bloquear una direcci√≥n IP durante unos minutos ante una serie de errores de inicio de sesi√≥n. Esta no es una protecci√≥n a prueba de agua, pero el hacker ahora requiere una botnet para realizar el ataque de fuerza bruta. Este es un obst√°culo que deber√≠a mantener a raya a los piratas inform√°ticos casuales y a los guionistas. Entonces, seg√ļn los datos que est√° protegiendo, esta deber√≠a ser una defensa decente.

Configurar esta defensa no es difícil. Mostraré un ejemplo de cómo hacer esto con el caché de usuario de APC .

<?php
$apc_key
= "{$_SERVER['SERVER_NAME']}~login:{$_SERVER['REMOTE_ADDR']}";
$tries
= (int)apc_fetch($apc_key);
if ($tries >= 10) {
header
("HTTP/1.1 429 Too Many Requests");
echo
"You've exceeded the number of login attempts. We've blocked IP address {$_SERVER['REMOTE_ADDR']} for a few minutes.";
exit();
}

$success
= login($_POST['username'], $_POST['password']);
if (!$success) {
apcu_inc
($apc_key, $tries+1, 600); # store tries for 10 minutes
} else {
apc_delete
($apc_key);
}

Aumentando el tiempo de bloqueo

El bloqueo de una IP puede afectar a toda una oficina, lo que puede resultar molesto. Comenzar con un tiempo de espera bajo y aumentarlo cada vez que se bloquea una IP ayudar√° en su contra.

<?php
$apc_key
= "{$_SERVER['SERVER_NAME']}~login:{$_SERVER['REMOTE_ADDR']}";
$apc_blocked_key
= "{$_SERVER['SERVER_NAME']}~login-blocked:{$_SERVER['REMOTE_ADDR']}";

$tries
= (int)apc_fetch($apc_key);
if ($tries >= 10) {
header
("HTTP/1.1 429 Too Many Requests");
echo
"You've exceeded the number of login attempts. We've blocked IP address {$_SERVER['REMOTE_ADDR']} for a few minutes.";
exit();
}

$success
= login($_POST['username'], $_POST['password']);
if (!$success) {
$blocked
= (int)apc_fetch($apc_blocked_key);

apc_store
($apc_key, $tries+1, pow(2, $blocked+1)*60); # store tries for 2^(x+1) minutes: 2, 4, 8, 16, ...
apc_store
($apc_blocked_key, $blocked+1, 86400); # store number of times blocked for 24 hours
} else {
apc_delete
($apc_key);
apc_delete
($apc_blocked_key);
}