webentwicklung-frage-antwort-db.com.de

Blockieren Sie die Anforderung für mehrere erfolglose Anmeldungen für einen Zeitraum

Ich habe eine Website und möchte die Anforderung von BOTs blockieren und versuchen, mich brutal auf meiner Website anzumelden.

Jetzt verwende ich Session zum Speichern des Anmeldeversuchs und zeige das Captcha nach 3 erfolglosen Anmeldeversuchen, aber es liegt ein Problem vor. Die Sitzung wird entfernt, wenn der Benutzer den Browser schließt.

Welche Art von Lösung sollte ich in Betracht ziehen, um BOTs- und Brute-Force-Anmeldungen zu verhindern? Welche Eigenschaft des Benutzersystems oder Browsers sollte ich speichern, um sein/ihr nächstes Login zu verwalten?

Bearbeiten 1)

Ich verwende keinen ASP.NET-Mitgliedschaftsanbieter. Ich verwende meine eigenen Authentifizierungs- und Autorisierungsklassen

15
Arian

Sie können die Sitzung nicht verwenden, da der Client ein Cookie für Sie speichern muss und ein Angreifer Ihnen nicht weiterhelfen wird. Sie benötigen einen globalen Status.

Sie müssen sich nicht die Mühe machen, IP-Adressen zu verfolgen, da ein Bösewicht nur einen Anonymyzing-Proxy verwendet.

Verwenden Sie nicht die Kontosperrung, es sei denn, Sie müssen dies tun (PCI-Anforderung), da dies nur den Angreifer dazu bringt, Ihre Benutzer zu sperren.

Sie möchten auch vermeiden, dass Sie sich selbst etwas antun, indem Sie Ihren Server zu viel arbeiten lassen.

Das funktioniert:

Speichern Sie bei fehlgeschlagener Authentifizierung den Benutzernamen zusammen mit der Anzahl im globalen Status. Synchronisierter count++, wenn mehr Authentifizierungen mit diesem Benutzernamen fehlschlagen. Ich benutze dafür Redis.

Wenn count >= threshold, fordern Sie den gelösten CAPTCHA-Wert an, bevor Sie fortfahren. CAPTCHA auf dem Anmeldebildschirm anzeigen.

Löschen Sie nach erfolgreich der Authentifizierung den gespeicherten Benutzernamen im globalen Status. Geben Sie dem Benutzer "Trusted User Agent" den HMAC-Code " cookie ", damit er in Zukunft für diesen Benutzernamen auf dieser UA kein CAPTCHA ausführen muss.

Sie können dasselbe für Kennwörter tun , aber wahrscheinlich mit einem höheren Schwellenwert.

Wenn Sie CAPTCHA nicht mögen , fordern Sie Proof of Work an, indem Sie beispielsweise den Kunden die Primfaktoren einer sehr großen Zahl berechnen und übermitteln lassen.

Stellen Sie sicher, dass Sie bcrypt verwenden, um Ihre Passwörter zu hacken, und dass der Kostenfaktor so hoch ist, dass es> = 250 ms dauert, ein Passwort zu hacken. Dies verlangsamt Ihren Server, verlangsamt aber auch einen Angreifer. Vermeiden Sie Hashing, es sei denn, sie bestehen das CAPTCHA (falls erforderlich).

Benutzer dazu ermutigen, lange, komplizierte und unvergessliche Texte zu verwenden? Passwörter, so dass sie schwerer zu erzwingen sind.

31
Neil McGuigan

Am einfachsten wäre es, Ihre Lösung mit einem CDN-Anbieter wie Cloudflare ( https://www.cloudflare.com/features-security ) zu konfrontieren, der Bots für Sie erkennt. Viele CDNs bieten dies an und Cloudflare hat einen kostenlosen Tarif.

Wenn Sie dies alternativ selbst versuchen, können Sie die Anzahl der Versuche pro Benutzername in Ihrer Datenbank zählen und anhand dieser Anzahl ein Captcha anzeigen.

4
ABrowne

Identifizieren Sie eine ungültige Anmeldung basierend auf IpAddress (anonymer Proxy). Dies ist jede ungültige Anmelde-IP sowie die Anzahl und Zeit der Anmeldungen, die im Anwendungsstatus gespeichert werden.

Erstellen Sie die Klasse InvalidLogin

public class InvalidLogin
{
    public string IP { get; set; }
    public DateTime Attempttime { get; set; }
    public int AttemptCount { get; set; }
}

Login-Ereignis

protected void Login_Click(object sender, EventArgs e)
        {
            bool Testsuccessfullogin = false;
            if (Testsuccessfullogin)
            {
                //Your code after successfull login
            }
            else
            {
               //Invalid Login --- Capture Each login event based on IP
                string strIp;
                strIp = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; //when user is behind proxy server
                if (strIp == null)
                {
                    strIp = Request.ServerVariables["REMOTE_ADDR"];//Without proxy
                }

                List<InvalidLogin> user = null;
                if (HttpContext.Current.Application["Users"] == null) //Adding List to Application State
                {
                    user = new List<InvalidLogin>();
                }
                else
                {
                    user = (List<InvalidLogin>)HttpContext.Current.Application["Users"];
                }
                var remove = user.RemoveAll(x => x.Attempttime < DateTime.Now.AddMinutes(-15));//Remove IP Before 15 minutes(Give 15 Min Time Next Login)
                var checkLogged = user.Find(x => x.IP == strIp);
                if (checkLogged == null)
                {
                    user.Add(new InvalidLogin
                    {
                        IP = strIp,
                        Attempttime = DateTime.Now,
                        AttemptCount = 1

                    });
                     Application.Lock();
                     HttpContext.Current.Application["Users"] = user;
                      Application.UnLock();
                }
                else
                {
                    if (checkLogged.AttemptCount < 4)
                    {
                        checkLogged.Attempttime = DateTime.Now;
                        checkLogged.AttemptCount++;
                        Application.Lock();
                        HttpContext.Current.Application["Users"] = user;
                        Application.UnLock();
                    }
                }



                if (checkLogged != null)
                {
                    if (checkLogged.AttemptCount > 3)
                    {
                        captcha.Visible = true;  //Showing captcha 
                    }
                }




            }
        }
3
Benjamin

Wenn Sie Ihre eigenen Authentifizierungs- und Autorisierungsklassen verwenden, müssen Sie für jeden Benutzer die Anzahl der fehlgeschlagenen Anmeldeversuche sowie Datum und Uhrzeit zählen.

Wenn die Anzahl der Versuche das Limit erreicht hat, dass Sie den nächsten Anmeldevorgang mit einer Fehlermeldung wie "Ihr Konto wurde für 15 Minuten gesperrt, versuchen Sie es später erneut."

Zum Beispiel. Die Anmeldetabelle heißt [Anmeldungen].

You need to add new colums:
1. [LastLoginAttemptAt] DATETIME NULL
2. [LoginFailedAttemptsCount] INT NOT NULL DEFAULT 0

Ihr Klassen-Login enthält also die folgenden neuen Felder:

public class Login {
    public DateTime? LastLoginAttemptAt {get;set;}
    public int LoginFailedAttemptsCount {get;set;}
}

Außerdem müssen Sie eine Konfigurationsvariable speichern - den Wert für die maximale Anzahl fehlgeschlagener Anmeldeversuche und die Sperrdauer.

const int MaxNumberOfFailedAttemptsToLogin = 10;
const int BlockMinutesAfterLimitFailedAttemptsToLogin = 15; // 15 min

Bei einer signIn-Methode führen Sie Folgendes aus (einfaches Codebeispiel, keine Produktversion):

public void SignIn(string username, string password)
{    
    var login = _userService.TryGetLogin(username);
    if (login == null){
        // Login by username not found.
        // Return error message "Invalid username or password"
        return;
    }

    if (login.LoginFailedAttemptsCount > MaxNumberOfFailedAttemptsToLogin
    && login.LastLoginAttemptAt.HasValue
    && DateTime.Now < login.LastLoginAttemptAt.Value.AddMinutes(BlockMinutesAfterLimitFailedAttemptsToLogin))
    {
        // Login is blocked, need to break the process.
        // Return error message "Your account was blocked 
        // for a 15 minutes, please try again later."
        return;
    } else {
        login.LoginFailedAttemptsCount = 0;
        login.LastLoginAttemptAt = DateTime.Now;
    }

    var success = login.ValidatePassword(password);
    if (!success)
    {
        // Invalid password, need to update the number of attempts.
        login.LastLoginAttemptAt = DateTime.Now; //or UTC
        login.LoginFailedAttemptsCount++;
        // Update(login);
        // Return error message "Invalid username or password"
        return;
    } else {
        login.LoginFailedAttemptsCount = 0;
        login.LastLoginAttemptAt = DateTime.Now;
        // Update(login);
        // Success!
    }
}
1
Yuriy A.

das Einzige, was ich hinzufügen möchte, was andere nicht haben, ist, dass Sie Bots nicht darauf aufmerksam machen möchten, dass sie erkannt wurden. Wenn Sie sie mit einer Meldung blockieren, notieren sie sich lediglich, was sie getan haben, um erkannt und angepasst zu werden. Wenn Sie sie zum Beispiel über die IP-Adresse "bemerken", lassen Sie das eingegebene Kennwort nie erfolgreich zu. Sie werden in die Irre geführt, wenn sie denken, Sie hätten einige komplizierte Passwörter usw. und gehen woanders hin, ohne jemals sicher zu sein, dass Sie sie bemerkt haben.

Ich würde auch vorschlagen, die "Versuche" in einer Datenbank mit IP zu speichern. Sie können dann problemlos zurückkehren und die Versuche überprüfen, die für Ihre Website unternommen wurden. Sie könnten die Webprotokolle abfragen, aber das ist schmerzhafter. Ich logge mich auch erfolgreich ein, damit ich feststellen kann, wann Bots wieder eintreffen, um weitere Nachforschungen anzustellen.

0
Bruce Dunwiddie

Wenn ich dies tun würde, würde ich eine Spalte in einer Datenbank verwenden, um die Anmeldeversuchsnummer und einen Datums-/Zeitstempel für den ersten Versuch zu speichern. Dann haben Sie etwas Logik um den Login

 if(loginAttempt>5 && DateTime.Now<loginDate.AddMinute(5))
{
    //Locked out
}
0
Dzm2012

Sie können das Konto nach einigen fehlgeschlagenen Versuchen sperren und den Benutzer Sicherheitsfragen beantworten lassen, um es wieder zu aktivieren. Erlauben Sie auch nicht die Wiederverwendung der letzten Passwörter und Sie sollten sicher sein.

Nun, wenn Sie dies per Codierung tun möchten, speichern Sie die Zeit für den dritten Anmeldeversuch [MaxAttemptTime] (DateTime.Now) und die Zeit für die Freigabe des Kontos [ReleaseTime] (z. B. nach 20 Minuten DateTime.Now.AddMinutes(20)).

Jedes Mal, wenn derselbe Benutzer versucht, sich anzumelden, sollte dies auf der Grundlage des [ReleaseTime] abgelehnt werden. Setzen Sie diese Zähler bei der erfolgreichen Anmeldung eines echten Benutzers zurück.

0