Unzureichende Kontrolle der Interaktionsfrequenz

Beschreibung

Unzureichende Kontrolle der Interaktionsfrequenz ist eine Schwachstelle, bei der Software nicht ordnungsgemäß begrenzt, wie oft ein Akteur - ob Mensch oder automatisiert - Aktionen ausführen oder Anfragen senden kann. Ohne Frequenzkontrollen können Benutzer oder automatisierte Systeme schneller oder öfter mit der Anwendung interagieren als beabsichtigt, was potenziell Ressourcen erschöpft, Schutzmechanismen umgeht oder die Programmlogik manipuliert. Dies umfasst Szenarien wie unbegrenzte Authentifizierungsversuche, uneingeschränkte API-Aufrufe, Abstimmungen ohne Abkühlzeiten oder Gutscheineinlösungen ohne Rate-Limits.

Risiko

Diese Schwachstelle ermöglicht mehrere Angriffsvektoren. Denial-of-Service-Angriffe werden möglich, wenn Angreifer das System mit Anfragen schneller überfluten als es verarbeiten kann, was CPU, Speicher, Netzwerkbandbreite oder Datenbankverbindungen erschöpft. Brute-Force-Angriffe gegen Authentifizierung werden ohne Versuchslimits machbar - Angreifer können Tausende von Passwörtern pro Sekunde ausprobieren. Geschäftslogik-Missbrauch tritt auf, wenn Benutzer unbegrenzt oft abstimmen, Gutscheine einlösen oder andere eingeschränkte Aktionen ausführen können. Automatisierte Bots können Inhalte scrapen, Spam-Konten erstellen oder Systeme mit übermenschlicher Geschwindigkeit manipulieren. Das Fehlen von Rate-Limiting ist besonders gefährlich bei öffentlich zugänglichen APIs und Authentifizierungsendpunkten.

Lösung

Implementieren Sie Rate-Limiting auf mehreren Ebenen: pro Benutzer, pro IP, pro Sitzung und global. Verwenden Sie Techniken wie Token-Buckets, gleitende Fenster oder feste Fensterzähler zur Verfolgung von Anfrageraten. Fügen Sie exponentielle Verzögerung bei wiederholten Fehlern hinzu, insbesondere bei der Authentifizierung. Implementieren Sie CAPTCHA nach Schwellenwertverletezungen, um Menschen von Bots zu unterscheiden. Verwenden Sie Kontosperrrichtlinien mit eskalierenden Sperrdauern. Setzen Sie angemessene Limits für alle API-Endpunkte basierend auf erwarteten legitimen Nutzungsmustern. Protokollieren Sie Rate-Limit-Verletzungen für die Sicherheitsüberwachung. Erwägen Sie die Verwendung spezialisierter Rate-Limiting-Dienste oder Middleware für komplexe Anwendungen.

Häufige Auswirkungen

AuswirkungDetails
VerfügbarkeitBereich: Verfügbarkeit

Denial of Service (Ressourcenverbrauch) - Unbegrenzte Anfragen können Serverressourcen erschöpfen und das System für legitime Benutzer unzugänglich machen.
ZugriffskontrolleBereich: Zugriffskontrolle

Umgehung des Schutzmechanismus - Unbegrenzte Authentifizierungsversuche ermöglichen Brute-Force-Angriffe gegen Passwörter und andere Anmeldedaten.
IntegritätBereich: Integrität

Unerlaubte Aktionen - Uneingeschränkte Aktionsfrequenz ermöglicht die Manipulation von Abstimmungen, Bewertungen, Transaktionen oder anderer Geschäftslogik.

Beispielcode

Anfälliger Code

// Anfällig: Keine Begrenzung der Authentifizierungsversuche
#define MAX_PASSWORD_LENGTH 64

int isValidUser = 0;
char password[MAX_PASSWORD_LENGTH];

// Anfällig: Endlosschleife ohne Versuchszähler
while (isValidUser == 0) {
    printf("Passwort eingeben: ");
    fgets(password, MAX_PASSWORD_LENGTH, stdin);
    isValidUser = validatePassword(password);

    // Keine Begrenzung - Angreifer kann unbegrenzt Passwörter ausprobieren
}
# Anfällig: Kein Rate-Limiting am Login-Endpunkt
from flask import Flask, request

app = Flask(__name__)

@app.route('/login', methods=['POST'])
def login():
    # Anfällig: Kein Rate-Limiting
    username = request.form['username']
    password = request.form['password']

    if check_credentials(username, password):
        return create_session(username)
    else:
        return 'Ungültige Anmeldedaten', 401

# Angreifer kann Tausende von Anfragen pro Sekunde senden
// Anfällig: Kein Rate-Limiting auf API
const express = require('express');
const app = express();

// Anfällig: Unbegrenzte Anfragen erlaubt
app.post('/api/vote', (req, res) => {
    const { postId, userId } = req.body;

    // Keine Frequenzprüfung - Benutzer kann unbegrenzt abstimmen
    incrementVote(postId);

    res.json({ success: true });
});

// Angreifer kann Abstimmungsergebnisse mit schnellen Anfragen manipulieren

Korrigierter Code

// Korrigiert: Begrenzte Authentifizierungsversuche
#define MAX_PASSWORD_LENGTH 64
#define MAX_ATTEMPTS 3
#define LOCKOUT_SECONDS 300

int isValidUser = 0;
int attemptCount = 0;
char password[MAX_PASSWORD_LENGTH];

// Korrigiert: Begrenzte Versuche mit Sperrung
while (isValidUser == 0 && attemptCount < MAX_ATTEMPTS) {
    printf("Passwort eingeben (Versuch %d von %d): ",
           attemptCount + 1, MAX_ATTEMPTS);
    fgets(password, MAX_PASSWORD_LENGTH, stdin);
    isValidUser = validatePassword(password);
    attemptCount++;

    if (!isValidUser && attemptCount >= MAX_ATTEMPTS) {
        printf("Zu viele Versuche. Gesperrt für %d Sekunden.\n",
               LOCKOUT_SECONDS);
        sleep(LOCKOUT_SECONDS);
    }
}
# Korrigiert: Rate-Limiting mit Flask-Limiter
from flask import Flask, request
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__)
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["200 pro Tag", "50 pro Stunde"]
)

@app.route('/login', methods=['POST'])
@limiter.limit("5 pro Minute")  # Korrigiert: Strenges Rate-Limit für Login
def login():
    username = request.form['username']
    password = request.form['password']

    if check_credentials(username, password):
        return create_session(username)
    else:
        return 'Ungültige Anmeldedaten', 401

# Zusätzlicher Schutz: Kontosperrung nach Fehlversuchen
def check_credentials_with_lockout(username, password):
    lockout = get_lockout_status(username)
    if lockout and lockout.is_active:
        raise TooManyAttemptsError(lockout.remaining_time)

    success = verify_password(username, password)
    if not success:
        record_failed_attempt(username)
    else:
        clear_failed_attempts(username)

    return success
// Korrigiert: Rate-Limiting-Middleware
const express = require('express');
const rateLimit = require('express-rate-limit');

const app = express();

// Korrigiert: Rate-Limiter-Middleware
const voteLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 Minuten
    max: 10, // 10 Stimmen pro Fenster pro IP
    message: 'Zu viele Stimmen, bitte später erneut versuchen',
    standardHeaders: true,
    legacyHeaders: false,
});

app.post('/api/vote', voteLimiter, (req, res) => {
    const { postId, userId } = req.body;

    // Zusätzliche Prüfung: eine Stimme pro Benutzer pro Beitrag
    if (hasUserVoted(userId, postId)) {
        return res.status(409).json({ error: 'Bereits abgestimmt' });
    }

    incrementVote(postId, userId);
    res.json({ success: true });
});

CVE-Beispiele

  • CVE-2024-50653: E-Commerce-Plattform-Gutschein-Endpunkt ohne serverseitige Anfragefrequenzbeschränkungen, was unbegrenzte Einlöseversuche ermöglichte.
  • CVE-2002-1876: Mailserver anfällig für schnelle Verbindungsanfragen, die Denial of Service durch Ressourcenerschöpfung verursachen.

Verwandte CWEs

  • CWE-691: Ungenügender Kontrollflussmanagement (Eltern)
  • CWE-307: Ungenügende Beschränkung übermäßiger Authentifizierungsversuche (Kind)
  • CWE-837: Unzureichende Durchsetzung einer einzelnen, eindeutigen Aktion (Kind)
  • CWE-770: Ressourcenzuweisung ohne Limits oder Drosselung (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-799: Improper Control of Interaction Frequency." https://cwe.mitre.org/data/definitions/799.html
  2. OWASP. "Blocking Brute Force Attacks." https://owasp.org/www-community/controls/Blocking_Brute_Force_Attacks
  3. OWASP. "Rate Limiting." https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html