Лучшая практика: логин пользователя защита от перебора? - PullRequest
0 голосов
/ 27 июня 2018

Какова лучшая практика для защиты входа пользователя в систему от грубой силы в PHP?

Мне нравится идея использовать recaptcha для предотвращения автоматического входа в систему. Это приведет к большим затратам для атакующего. Также злоумышленник не может делать учетные записи пользователей DoS, умышленно используя неправильный пароль.

Достаточно ли защиты? Рекомендуется ли в любом случае добавить блок «х минут» после «у попыток»? Существуют ли варианты защиты входа в систему?

Я знаю о 2FA *. Но это должна быть дополнительная функция, и я хочу защитить пользователей, которые тоже не используют 2FA

* двухфакторная аутентификация

1 Ответ

0 голосов
/ 19 октября 2018

Прогрессивные задержки обычно являются наилучшим компромиссом в отношении безопасности и удобства использования.

В Дирижабль мы внедрили прогрессивную задержку здесь ( соответствующая конфигурация ), когда неудачные попытки из определенной IP-подсети или в отношении конкретной учетной записи пользователя увеличатся количество времени, которое они должны ждать перед последовательными попытками.

Если вы ищете повторно используемый код для получения подсети с IP-адреса:

<?php
declare(strict_types=1);
class StackOverflowCopyPaste
{
    /** @var int $v4MaskBits */
    private $v4MaskBits;

    /** @var int $v6MaskBits */
    private $v6MaskBits;

    /**
     * @param int $v4MaskBits
     * @param int $v6MaskBits
     */
    public function __construct(int $v4MaskBits = 24, int $v6MaskBits = 48)
    {
        $this->v4MaskBits = $v4MaskBits;
        $this->v6MaskBits = $v6MaskBits;
    }

    /**
     * Return the given subnet for an IP and the configured mask bits
     *
     * Determine if the IP is an IPv4 or IPv6 address, then pass to the correct
     * method for handling that specific type.
     *
     * @param string $ip
     * @return string
     */
    public function getSubnet(string $ip): string
    {
        if (\preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip)) {
            return $this->getIPv4Subnet(
                $ip,
                (int) ($this->v4MaskBits ?? 32)
            );
        }
        return $this->getIPv6Subnet(
            $ip,
            (int) ($this->v6MaskBits ?? 128)
        );
    }


    /**
     * Return the given subnet for an IPv4 address and mask bits
     *
     * @param string $ip
     * @param int $maskBits
     * @return string
     */
    public function getIPv4Subnet(string $ip, int $maskBits = 32): string
    {
        $binary = \inet_pton($ip);
        for ($i = 32; $i > $maskBits; $i -= 8) {
            $j = \intdiv($i, 8) - 1;
            $k = (int) \min(8, $i - $maskBits);
            $mask = (0xff - ((1 << $k) - 1));
            $int = \unpack('C', $binary[$j]);
            $binary[$j] = \pack('C', $int[1] & $mask);
        }
        return \inet_ntop($binary).'/'.$maskBits;
    }

    /**
     * Return the given subnet for an IPv6 address and mask bits
     *
     * @param string $ip
     * @param int $maskBits
     * @return string
     */
    public function getIPv6Subnet(string $ip, int $maskBits = 48): string
    {
        $binary = \inet_pton($ip);
        for ($i = 128; $i > $maskBits; $i -= 8) {
            $j = \intdiv($i, 8) - 1;
            $k = (int) \min(8, $i - $maskBits);
            $mask = (0xff - ((1 << $k) - 1));
            $int = \unpack('C', $binary[$j]);
            $binary[$j] = \pack('C', $int[1] & $mask);
        }
        return \inet_ntop($binary).'/'.$maskBits;
    }
}

Демо доступно на 3v4l .

Почему подсети вместо IP-адресов?

Допустим, вы управляете всей подсетью /24 и отправили 10 неудачных попыток из 192.168.0.1. Ваша задержка увеличится до максимума (30 секунд).

Если вы заблокировали только IP-адреса, вы можете отправить еще один запрос с 192.168.0.2 и без задержек. Блокировка 192.168.0.0/24 не будет иметь такой же слабости.

Эта проблема значительно усугубляется, если учесть, что при выделении IPv6 обычно выделяются целые подсети /48 или /64 вместо одного IP-адреса, поэтому теоретически можно использовать от 2 ^ 64 до 2 ^ 80 адресов при атаке методом перебора. прежде чем вам пришлось страдать от ограничения скорости.

Таким образом, чтобы обойти эти проблемы, рассматривая целую подсеть (которая настраивается; по умолчанию: /24 для IPv4, /48 для IPv6), поскольку тот же источник более устойчив к этим атакам. Поскольку задержки являются просто неудобством, пользователи с законными учетными данными никогда не будут по-настоящему заблокированы в своей учетной записи.

...