RAIVN Botban

Schlagwort: functions.php

  • Diese WordPress Sicherheits-Schutzregeln brauchst du unbedingt

    Diese WordPress Sicherheits-Schutzregeln brauchst du unbedingt

    Diese 5 wichtige Sicherheits-Schutzregeln, die in der functions.php deiner WordPress-Seite nicht fehlen sollten, um grundlegende Schwachstellen zu mindern, sind:


    1. Deaktiviere die Bearbeitung von Dateien im WordPress-Admin-Bereich

    Die Bearbeitung von Themes und Plugins direkt im WordPress-Dashboard ist ein hohes Sicherheitsrisiko. Wenn ein Angreifer Zugriff auf das Admin-Konto erhält, kann er schädlichen Code in jede Datei (einschließlich functions.php) einschleusen.

    PHP

    // Deaktiviert den Theme- und Plugin-Editor (empfohlen)
    define( 'DISALLOW_FILE_EDIT', true );
    

    Anmerkung: Diese Zeile wird oft direkt in der wp-config.php eingefügt, da sie eine globale Konfigurationsdirektive ist. Sie dient aber dem gleichen Sicherheitszweck.


    2. Entferne die WordPress-Versionsnummer

    Die Anzeige der genauen WordPress-Versionsnummer kann Angreifern nützliche Informationen liefern, wenn sie gezielt nach bekannten Schwachstellen in dieser Version suchen. Es ist besser, diese Informationen zu verbergen.

    PHP

    // Entfernt die WordPress-Versionsnummer aus Header, RSS und anderen Metadaten
    function remove_wp_version_strings( $src ) {
        global $wp_version;
        parse_str( parse_url( $src, PHP_URL_QUERY ), $query );
        if ( !empty( $query['ver'] ) && $query['ver'] === $wp_version ) {
            $src = remove_query_arg( 'ver', $src );
        }
        return $src;
    }
    add_filter( 'script_loader_src', 'remove_wp_version_strings' );
    add_filter( 'style_loader_src', 'remove_wp_version_strings' );
    
    // Entfernt die Version aus dem <head>
    remove_action( 'wp_head', 'wp_generator' );
    

    3. Deaktiviere die XML-RPC-Schnittstelle (wenn nicht benötigt)

    XML-RPC (xmlrpc.php) ist ein älteres Protokoll, das oft für Brute-Force-Angriffe und DDoS-Attacken missbraucht wird (insbesondere der pingback-Dienst). Wenn du keine mobilen Apps, Jetpack oder andere Dienste nutzt, die XML-RPC benötigen, solltest du es deaktivieren.

    PHP

    // Deaktiviert die XML-RPC-Schnittstelle
    add_filter( 'xmlrpc_enabled', '__return_false' );
    
    // Entfernt den RSD-Link (falls vorhanden)
    remove_action( 'wp_head', 'rsd_link' );
    

    4. Begrenze Login-Versuche

    Um Brute-Force-Angriffe auf die Login-Seite (wp-login.php) zu verhindern, solltest du die Anzahl der möglichen Login-Versuche beschränken. Dies wird zwar oft über ein dediziertes Sicherheits-Plugin (z. B. Limit Login Attempts) gelöst, kann aber auch per PHP Code gesteuert werden.

    PHP

    // --- Konfiguration ---
    define( 'MAX_LOGIN_ATTEMPTS', 5 );          // Max. Fehlversuche
    define( 'LOCKOUT_DURATION', 3600 );        // Sperr-Dauer in Sekunden (1 Stunde)
    define( 'TRANSIENT_PREFIX', 'limit_login_' );
    
    /**
     * 1. Zählt fehlgeschlagene Versuche und setzt die Sperre.
     * Wird NACH dem Fehlschlag ausgeführt.
     */
    function custom_increment_login_attempts( $username ) {
        $user_ip = $_SERVER['REMOTE_ADDR'];
        $transient_key = TRANSIENT_PREFIX . md5( $user_ip );
    
        // Zähler auslesen
        $attempts = (int) get_transient( $transient_key );
        $attempts++;
    
        if ( $attempts >= MAX_LOGIN_ATTEMPTS ) {
            // Sperren: Setze den Lockout-Transient
            set_transient( $transient_key . '_lockout', time() + LOCKOUT_DURATION, LOCKOUT_DURATION );
            // Zähler zurücksetzen/löschen
            delete_transient( $transient_key );
        } else {
            // Zähler erhöhen: Setze den Transient mit Ablaufzeit
            set_transient( $transient_key, $attempts, LOCKOUT_DURATION );
        }
    }
    // Hook zum Hochzählen des Fehlers
    add_action( 'wp_login_failed', 'custom_increment_login_attempts' );
    
    
    /**
     * 2. Prüft VOR der Anmeldung, ob die IP gesperrt ist.
     * Wird VOR der eigentlichen Authentifizierung ausgeführt.
     */
    function custom_check_ip_lockout( $user ) {
        // Wenn die Authentifizierung bereits fehlgeschlagen ist oder erfolgreich war, nichts tun
        if ( is_wp_error( $user ) || ( $user instanceof WP_User ) ) {
            return $user;
        }
    
        $user_ip = $_SERVER['REMOTE_ADDR'];
        $lockout_key = TRANSIENT_PREFIX . md5( $user_ip ) . '_lockout';
    
        $lockout_time = get_transient( $lockout_key );
    
        if ( $lockout_time ) {
            $remaining_time = $lockout_time - time();
    
            if ( $remaining_time > 0 ) {
                // Die IP ist gesperrt
                $minutes = ceil( $remaining_time / 60 );
                return new WP_Error(
                    'too_many_attempts_lockout',
                    sprintf(
                        '<strong>FEHLER</strong>: Zu viele fehlgeschlagene Login-Versuche. Bitte versuche es in %s Minuten erneut.',
                        $minutes
                    )
                );
            } else {
                // Sperre ist abgelaufen, den Lockout-Transient löschen
                delete_transient( $lockout_key );
            }
        }
    
        // Wenn nicht gesperrt, normal fortfahren
        return $user;
    }
    // Hook zum Blockieren der Anmeldung
    add_filter( 'authenticate', 'custom_check_ip_lockout', 1 ); // Hohe Priorität, um sehr früh zu laufen
    

    Zusammenfassung: Der Hook 'wp_login_failed' ist nützlich für das Zählen, und der Filter 'authenticate' ist unerlässlich für das Blockieren und die Ausgabe der Sperr-Meldung. Beide zusammen ergeben eine saubere, nicht-Plugin-basierte Lösung.


    5. Deaktiviere die Enumeration von Benutzernamen

    Standardmäßig ist es Angreifern leicht möglich, alle Benutzernamen deiner Seite zu ermitteln, indem sie spezielle URL-Parameter oder die REST API verwenden (z. B. /?author=1). Mit dem Wissen des Benutzernamens ist nur noch das Passwort für einen Login erforderlich. Das solltest du verhindern.

    PHP

    // Verhindert die Enumeration von Benutzernamen über die Author-URL
    if ( !is_admin() && isset( $_SERVER['REQUEST_URI'] ) ) {
        if ( preg_match( '/author=([0-9]*)/i', $_SERVER['REQUEST_URI'] ) ) {
            wp_die( 'Zugriff verweigert.', 'Sicherheitshinweis', array( 'response' => 403 ) );
        }
    }
    // Blockiert die REST API Endpunkte für Benutzer (wenn nicht benötigt)
    add_filter( 'rest_endpoints', function( $endpoints ) {
        if ( isset( $endpoints['/wp/v2/users'] ) ) {
            unset( $endpoints['/wp/v2/users'] );
        }
        if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) {
            unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
        }
        return $endpoints;
    } );
    

    Wichtiger Hinweis:
    Jede Änderung an der functions.php sollte in einem Child-Theme vorgenommen werden, damit die Änderungen bei einem Theme-Update nicht überschrieben werden! Fehler in dieser Datei können zum Absturz deiner gesamten Webseite führen.