Registrierung der benutzerdefinierten REST-Route
Die Funktion zur Registrierung der REST-API-Route wird verwendet, um einen neuen Endpunkt in WordPress hinzuzufügen. Dieser Endpunkt ermöglicht es, externe Anfragen an WordPress zu senden und eine Antwort zu erhalten.
Schritte der Registrierung:
Hook zur Initialisierung der REST-API: Mit add_action('rest_api_init', function () { … }); wird eine anonyme Funktion registriert, die während der Initialisierung der REST-API aufgerufen wird.
Definition der Route: Innerhalb dieser anonymen Funktion wird register_rest_route aufgerufen, um die Route zu definieren.
Namespace: 'hnp_api_firewall/v1' legt den Namespace fest, der als Versionierung der API dient.
Route: '/api' ist der spezifische Endpunkt innerhalb des Namespace.
Optionen: Ein Array von Optionen, darunter:
Methode: 'methods' => 'POST' spezifiziert, dass die Route nur POST-Anfragen akzeptiert.
Callback: 'callback' => 'hnp_api_firewall_callback' gibt die Funktion an, die aufgerufen wird, wenn die Route erreicht wird.
Berechtigung: 'permission_callback' => 'hnp_api_firewall_combined_permissions' bestimmt die Funktion, die die Berechtigungen für den Zugriff auf die Route überprüft.
Kombinierte Berechtigungs- und Blockierungslogik
Die Funktion hnp_api_firewall_combined_permissions dient dazu, die Berechtigungen und Blockierungslogik zu kombinieren. Sie wird aufgerufen, bevor die Haupt-Callback-Funktion ausgeführt wird, um sicherzustellen, dass nur berechtigte Anfragen zugelassen werden.
Schritte der Berechtigungsprüfung:
IP-Überprüfung: Die IP-Adresse des Anfragenden wird überprüft, um festzustellen, ob sie blockiert ist.
Wenn die IP-Adresse blockiert ist und die Blockierungsdauer noch nicht abgelaufen ist, wird der Zugriff verweigert.
Wenn die Blockierungsdauer abgelaufen ist, wird die IP-Adresse entsperrt und die Blockierungsinformationen werden zurückgesetzt.
Überprüfung der API-Benutzer und -Geheimnisse: Die Kopfzeilen der Anfrage werden auf gültige API-Benutzer und -Geheimnisse überprüft.
Wenn die Anmeldedaten korrekt sind, wird der Zähler für gültige Versuche erhöht.
Wenn die Anmeldedaten falsch sind, wird der Zähler für ungültige Versuche erhöht.
Wenn die Anzahl ungültiger Versuche einen bestimmten Schwellenwert überschreitet (z.B. 50), wird die IP-Adresse blockiert.
Versuchsverfolgung: Die Anzahl der erfolgreichen und fehlgeschlagenen Anmeldeversuche wird verfolgt, um die Blockierungslogik zu unterstützen.
Rückgabewert
Erfolgreiche Berechtigung: Wenn die Berechtigung erfolgreich ist, gibt die Funktion true zurück, wodurch die Haupt-Callback-Funktion hnp_api_firewall_callback aufgerufen wird.
Fehlgeschlagene Berechtigung: Wenn die Berechtigung fehlschlägt, wird ein Fehler zurückgegeben und die Haupt-Callback-Funktion wird nicht ausgeführt.
Haupt-Callback-Funktion
Die Haupt-Callback-Funktion hnp_api_firewall_callback wird aufgerufen, wenn die Berechtigung erfolgreich ist und die Route erreicht wird. Sie gibt eine JSON-Antwort mit dem Dateninhalt zurück, der in diesem Fall ein einfaches Beispiel mit {"testdata": "test"} ist.
// Register the custom REST route add_action('rest_api_init', function () { register_rest_route('hnp_api_firewall/v1', '/api', array( 'methods' => 'POST', 'callback' => 'hnp_api_firewall_callback', 'permission_callback' => 'hnp_api_firewall_combined_permissions', )); }); // Combined function to handle permissions and blocking logic function hnp_api_firewall_combined_permissions(WP_REST_Request $request) { $ip_address = sanitize_text_field($_SERVER['REMOTE_ADDR']); $blocked_ips = get_option('hnp_blocked_ips', array()); // Check if IP is blocked if (isset($blocked_ips[$ip_address])) { $block_info = $blocked_ips[$ip_address]; $block_time = $block_info['block_time']; $block_duration = $block_info['block_duration']; $current_time = current_time('timestamp'); // If current time is less than block time + block duration, deny access if ($current_time < ($block_time + $block_duration)) { return new WP_Error('blocked_ip', 'Your IP is temporarily blocked due to too many attempts.', array('status' => 403)); } else { // Unblock IP and reset attempts after block duration unset($blocked_ips[$ip_address]); update_option('hnp_blocked_ips', $blocked_ips); } } // Check API user and secret $api_user = $request->get_header('APIUser'); $api_secret = $request->get_header('APISecret'); $valid_api_user = '4GI53seaRLu!FK9XEiAk323U6M!f2bT7Sda28ZqsaegQCn0!Y121Y1L'; $valid_api_secret = '091572EddV!YcTKGR3Q13a!CM6TN!UWbPqFRdwa1XpP!1g8o32aaJD4'; // Tracking attempts $attempts = get_option('hnp_attempts', array()); if (!isset($attempts[$ip_address])) { $attempts[$ip_address] = array( 'valid_count' => 0, 'invalid_count' => 0, 'invalid_license_count' => 0, 'first_attempt_time' => current_time('timestamp') ); } $permission_granted = null !== $api_user && $api_user === $valid_api_user && null !== $api_secret && $api_secret === $valid_api_secret; if ($permission_granted) { $attempts[$ip_address]['valid_count']++; } else { $attempts[$ip_address]['invalid_count']++; // Block IP if invalid attempts exceed threshold (e.g., 50) if ($attempts[$ip_address]['invalid_count'] >= 50) { $blocked_ips[$ip_address] = array('block_time' => current_time('timestamp'), 'block_duration' => 12 * HOUR_IN_SECONDS); update_option('hnp_blocked_ips', $blocked_ips); return new WP_Error('blocked_ip', 'Your IP is temporarily blocked due to too many invalid attempts for API Secret/Username.', array('status' => 403)); } update_option('hnp_attempts', $attempts); return new WP_Error('invalid_credentials', 'Invalid API Secret key or password.', array('status' => 403)); } // Reset invalid attempts on successful authentication if (isset($attempts[$ip_address])) { unset($attempts[$ip_address]['invalid_count']); update_option('hnp_attempts', $attempts); } return true; } function hnp_api_firewall_callback() { return new WP_REST_Response(array( 'testdata' => 'test' ), 200); }
cUrl Anfrage zum Testen:
curl -X POST https://yourdomain.com/wp-json/hnp_api_firewall/v1/api \ -H "APIUser: 4GI53seaRLu!FK9XEiAk323U6M!f2bT7Sda28ZqsaegQCn0!Y121Y1L" \ -H "APISecret: 091572EddV!YcTKGR3Q13a!CM6TN!UWbPqFRdwa1XpP!1g8o32aaJD4"
PHP Anfrage zum Testen:
<?php function call_hnp_api_firewall() { $url = 'https://yourdomain.com/wp-json/hnp_api_firewall/v1/api'; $args = array( 'headers' => array( 'APIUser' => '4GI53seaRLu!FK9XEiAk323U6M!f2bT7Sda28ZqsaegQCn0!Y121Y1L', 'APISecret' => '091572EddV!YcTKGR3Q13a!CM6TN!UWbPqFRdwa1XpP!1g8o32aaJD4' ), 'body' => array( // Any additional data you want to send in the body ) ); $response = wp_remote_post($url, $args); if (is_wp_error($response)) { $error_message = $response->get_error_message(); echo "Something went wrong: $error_message"; } else { $response_body = wp_remote_retrieve_body($response); echo 'Response:<br>'; echo '<pre>'; print_r(json_decode($response_body, true)); echo '</pre>'; } } // Call the function call_hnp_api_firewall(); ?>
C# Anfrage zum Testen:
using System; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; class Program { private static async Task CallHnpApiFirewallAsync() { var url = "https://yourdomain.com/wp-json/hnp_api_firewall/v1/api"; using (var client = new HttpClient()) { // Set the APIUser and APISecret headers client.DefaultRequestHeaders.Add("APIUser", "4GI53seaRLu!FK9XEiAk323U6M!f2bT7Sda28ZqsaegQCn0!Y121Y1L"); client.DefaultRequestHeaders.Add("APISecret", "091572EddV!YcTKGR3Q13a!CM6TN!UWbPqFRdwa1XpP!1g8o32aaJD4"); // Optionally set the content of the request (if needed) var content = new StringContent("", System.Text.Encoding.UTF8, "application/json"); try { var response = await client.PostAsync(url, content); if (response.IsSuccessStatusCode) { var responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine("Response:"); Console.WriteLine(responseBody); } else { Console.WriteLine($"Error: {response.StatusCode}"); } } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); } } } static void Main(string[] args) { Task.Run(() => CallHnpApiFirewallAsync()).GetAwaiter().GetResult(); } }
Sicherheit:
Anzahl der möglichen Kombinationen bei BrutForceAttacken
Einzelne Schlüssel:
Für einen einzelnen Schlüssel mit 50 Zeichen und 94 möglichen Zeichen pro Position ergibt sich:
945094 hoch50
Zwei Schlüssel kombiniert
Da beide Schlüssel unabhängig voneinander betrachtet werden, multiplizieren wir die Anzahl der möglichen Kombinationen beider Schlüssel:
(94 hoch50)×(94 hoch50)(94 hoch50)×(94 hoch50)
Dies entspricht:
9410094 hoch100
Zeit für einen Brute-Force-Angriff
Angenommen, ein Computer kann 1 Milliarde (1.000.000.000) Kombinationen pro Sekunde testen:
Anzahl der Kombinationen:
Die Anzahl der Kombinationen für einen Schlüssel: 945094 hoch50 (eine extrem große Zahl)
Die Anzahl der Kombinationen für beide Schlüssel: 9410094 hoch100 (noch viel größer)
Zeit für Brute-Force:
Selbst wenn ein Computer 1 Milliarde Kombinationen pro Sekunde testen könnte, würde das Testen aller Kombinationen von zwei Schlüsseln extrem lange dauern.
Zum Vergleich:
Eine Milliarde Sekunden sind etwa 31,7 Jahre.
Die Anzahl der Kombinationen für 9410094 hoch100 ist so groß, dass selbst mit extrem schneller Hardware Billionen von Jahren benötigt würden, um alle Kombinationen zu testen.
Durch die Rate Limitierung der Firewall wird die Zeit auf Milliarden von Jahren erhöht, zudem sind DDOS oder ähnliche Hacking-Angriffe nicht möglich. Die Schnittstelle wird somit zusätzlich geschützt.
↩ Zurück zur Blogübersicht