Implementierung von Ratenbegrenzung und IP-Blockierung in Willow CMS
Dieser Blogbeitrag beschreibt ausführlich die Implementierung von Ratenbegrenzung und IP-Blockierung in einem Willow CMS und konzentriert sich dabei auf die wichtigsten Codekomponenten und deren Gründe. Diese Informationen richten sich an Entwickler, die ähnliche Sicherheitsmaßnahmen in ihren Projekten implementieren möchten. Seit Willow für diese Site live geschaltet wurde, war es interessant, die Protokolle anzusehen und all die Versuche aus Singapur zu sehen, Exploits zu finden!
Ratenbegrenzung
Ratenbegrenzung ist eine Technik zum Schutz von Anwendungsressourcen durch Beschränkung der Anzahl von Anfragen, die ein Client innerhalb eines bestimmten Zeitraums stellen kann. Diese Implementierung verwendet aus Effizienzgründen das Middleware-Muster und den Caching-Mechanismus von CakePHP.
RateLimitMiddleware
Der Kern der Ratenbegrenzungslogik befindet sich in src/Middleware/RateLimitMiddleware.php . Lesen Sie den vollständigen Code auf GitHub. Hier ist eine Aufschlüsselung der wichtigsten Teile:
class RateLimitMiddleware implements MiddlewareInterface
{
// Use default configuration or that provided to the constructor
public function __construct(array $config = [])
{
$this->limit = $config['limit'] ?? 3;
$this->period = $config['period'] ?? 60;
// Specific some default routes that should be rate limited
$this->rateLimitedRoutes = $config['routes'] ?? [
'/users/login',
'/users/register',
'/articles/add-comment/',
];
}
// Process a server request and return a response.
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// Use CakePHP method to get the client IP (more on this later)
$ip = $request->clientIp();
$route = $request->getUri()->getPath();
if ($this->isRouteLimited($route)) {
$key = "rate_limit_{$ip}_normal";
$rateData = $this->updateRateLimit($key, $this->period);
if ($rateData['count'] > $this->limit) {
// ...
throw new TooManyRequestsException(
// ...
);
}
}
return $handler->handle($request);
}
// ... more methods below, see the full file on GitHub
}
Wichtige Aspekte dieser Middleware:
- Zielrouten: Die
isRouteLimited()
Die Methode prüft, ob die aktuelle Route einer Geschwindigkeitsbegrenzung unterliegt, und ermöglicht so eine detaillierte Kontrolle. - Caching für Effizienz:
updateRateLimit()
Die Methode liest und erhöht die Anzahl der Anfragen aus dem Cache. Dadurch werden bei jeder Anfrage Datenbankabfragen vermieden und die Leistung verbessert. Wenn der Zeitraum abgelaufen ist, wird der Zähler zurückgesetzt. - Ausnahmebehandlung: Wenn das Limit überschritten wird,
TooManyRequestsException
wird ausgelöst, die Ausführung wird angehalten und ein 404-Fehler an den Client gesendet, einschließlich derRetry-After
Kopfzeile. - Protokollierung: Verstöße werden zur Analyse und Überwachung protokolliert.
- Konfiguration: Die Anzahl der zulässigen Anfragen und die Zeiträume werden aus Einstellungswerten abgerufen, sodass Sie diese im Admin-Bereich konfigurieren können.
- Wildcard-Unterstützung: Die Reihe der geschwindigkeitsbegrenzten Routen unterstützt Wildcards, sodass Sie
pages/*
oderarticles/*
. Siehe die Methode isRouteLimited() .
IP-Blockierung
Die IP-Blockierung fügt eine weitere Sicherheitsebene hinzu, indem sie Anfragen von bekannten böswilligen IP-Adressen verhindert. Die Implementierung kombiniert Caching mit Datenbanksuche und verwaltet so die Liste blockierter IPs effizient.
IpBlockerMiddleware
Diese Middleware src/Middleware/IpBlockerMiddleware.php kümmert sich um das Blockieren und Verfolgen verdächtiger Aktivitäten. Den vollständigen Code finden Sie auf GitHub. Hier ist eine Aufschlüsselung der wichtigsten Teile:
class IpBlockerMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// ...
$clientIp = $request->clientIp();
if ($this->ipSecurity->isIpBlocked($clientIp)) {
// Return 403 Forbidden
}
if ($this->ipSecurity->isSuspiciousRequest($route, $query)) {
// Log suspicious activity
$this->ipSecurity->trackSuspiciousActivity($clientIp, $route, $query);
// Return 403 Forbidden
}
return $handler->handle($request);
}
}
Und so funktioniert es:
- IP-Blockierung: Wenn die anfragende IP in der Sperrliste steht (überprüft über
isIpBlocked()
), wird sofort eine 403-Forbidden-Antwort zurückgegeben. - Erkennung verdächtiger Anfragen: Die
isSuspiciousRequest()
Die Methode prüft anhand einer Liste verdächtiger URL-Muster. Wenn eine Übereinstimmung gefunden wird, wird die Aktivität protokolliert und verfolgt.
IpSecurityService
Die Datei src/Service/IpSecurityService.php verwaltet die Kernlogik für die IP-Blockierung und die Erkennung verdächtiger Aktivitäten. Sie verwendet Caching zur Leistungssteigerung und bietet einen zentralen Ort für IP-bezogene Funktionen. Lesen Sie den vollständigen Code auf GitHub. Hier ist eine Aufschlüsselung der wichtigsten Teile:
class IpSecurityService
{
private array $suspiciousPatterns = [/* list of regular expressions */ ];
public function isIpBlocked(string $ip): bool
{
// Caching logic ...
// Database lookup if not in cache
$blockedIp = $blockedIpsTable->find()
// ... expiry checks ...
->first();
// ... caching logic
return $blockedStatus;
}
public function blockIp(string $ip, string $reason, ?DateTime $expiresAt = null): bool
{
// ... database save to blocked_ips table and logging the event
}
public function isSuspiciousRequest(string $route, string $query): bool
{
// Regex matching against suspicious patterns
// ... logging ...
}
public function trackSuspiciousActivity(string $ip, string $route, string $query): void
{
// Increase suspicious activity counter using cache
// ... progressive blocking logic (if IP has offended in last 24 hours block for 48 hours) ...
}
}
Wichtige Verbesserungen und Funktionen dieses Dienstes:
- Caching: Beide
isIpBlocked()
UndtrackSuspiciousActivity()
Verwenden Sie Caching, um die Datenbanklast zu reduzieren. - Progressive Blockierung: Die
trackSuspiciousActivity()
Methode implementiert progressive Sperrung. Wiederholungstäter werden länger gesperrt. - Umfassende Musterliste: Eine detaillierte Liste verdächtiger Muster in
$suspiciousPatterns
hilft, eine Vielzahl bösartiger Anfragen zu erkennen. Ich denke, in Zukunft werde ich diese aus der Datenbank laden/zwischenspeichern, um das Bearbeiten/Hinzufügen neuer Regeln zu vereinfachen.
Load Balancer-Unterstützung
Der Code unterstützt Willow CMS, das hinter einem Load Balancer läuft, indem er Proxy-Headern vertraut. Dies wird durch die Einstellung aktiviert'Security.trustProxy'
Zutrue
auf der Seite Willow CMS Admin->Einstellungen. Dadurch wird sichergestellt, dass die Client-IP und andere Anforderungsinformationen korrekt aus den weitergeleiteten Headern abgerufen werden und wir den integrierten CakePHP-Framework-Code verwenden, um die Client-IP zuverlässig abzurufen.
if (SettingsManager::read('Security.trustProxy', false)) {
$request = $request->withAttribute('trustProxy', true);
}
PHPUnit Tests
Dies ist ziemlich wichtiger Code, daher muss er mit einigen Unit-Tests versehen werden. Sie können sie in RateLimitMiddlewareTest und IpBlockerMiddlewareTest nachlesen. Ich verwende Datenprovider in PHPUnit, um die Tests sauber und leicht aktualisierbar zu halten.
IpBlockerMiddlewareTest
Dieser Testfall konzentriert sich auf dieIpBlockerMiddleware
, deckt Fälle von blockierten IPs, zwischengespeicherten Status, abgelaufenen Blockierungen, verdächtigen Anfragen und Pfaddurchquerungen ab.
- Vorrichtungsaufbau: Die
$fixtures = ['app.BlockedIps']
Deklaration verwendet eine Vorrichtung für dieBlockedIps
Tabelle, die einen konsistenten Datensatz zum Testen von Datenbankinteraktionen bereitstellt. - Verspottung:
RequestHandlerInterface
wird simuliert, um das Verhalten der Middleware zu isolieren und die Anforderungsverarbeitung zu simulieren. - Testfälle:
- testProcessWithBlockedIp : Bestätigt, dass blockierte IPs eine 403-Antwort erhalten.
- testProcessWithNonBlockedIp : Überprüft, ob nicht blockierte IPs durchgelassen werden.
- testProcessWithCachedBlockedStatus : Überprüft, ob zwischengespeicherte Blockstatus eingehalten werden.
- testProcessWithExpiredBlockedIp : Überprüft, dass abgelaufene Blöcke keinen 403-Fehler verursachen.
- testProcessWithMissingRemoteAddr : Bestätigt das Verhalten, wenn
REMOTE_ADDR
fehlt. - testProcessWithSuspiciousRequest , testProcessWithEncodedSuspiciousRequest : Überprüft die Erkennung verdächtiger URL-Muster, einschließlich codierter Muster.
- testMultipleSuspiciousRequestsLeadToBlock : Simuliert mehrere verdächtige Anfragen und überprüft, ob die IP schließlich blockiert und in der Datenbank gespeichert wird.
- Datenprovider: pathTraversalProvider und sqlInjectionProvider bieten eine saubere Möglichkeit, verschiedene Angriffsvektoren ohne Code-Duplikation zu testen. Diese Provider speisen Daten in parametrisierte Testmethoden ein und erhöhen so die Testabdeckung.
RateLimitMiddlewareTest
Diese Testsuite zieltRateLimitMiddleware
, mit Schwerpunkt auf Ratenbegrenzungslogik, Platzhalterrouten und unterschiedlicher Routenbehandlung.
- Setup: Die
setUp
Methode löscht den 'rate_limit'-Cache vor jedem Test und stellt so eine saubere Grundlage für eine genaue Ratenzählung sicher. Sie definiert auch Ratenbegrenzungsparameter (limit
Undperiod
) für die Tests. - Testfälle:
- testRateLimitGeneralRoute : Testet eine Route, die nicht geschwindigkeitsbegrenzt ist.
- testRateLimitSensitiveRoute : Testet eine Route, die geschwindigkeitsbegrenzt ist , und stellt eine
TooManyRequestsException
nach Überschreiten des Grenzwertes. - testDifferentRoutesDoNotAffectRateLimit : Überprüft, ob unterschiedliche Routen unabhängige Ratenbegrenzungen haben, um unbeabsichtigte Störungen zu verhindern.
- testRateLimitWildcardRoute : Demonstriert die Ratenbegrenzung mit Wildcard-Routen am Beispiel des PagesController.
Diese Testfälle demonstrieren bewährte Vorgehensweisen zum Testen von Middleware. Sie bieten zielgerichtete Szenarien, nutzen Mocking, wo es angebracht ist, und verwenden Datenanbieter zum effizienten Testen mehrerer Varianten.