secaudit.eu
Absicherung

WordPress HTTPS: Mixed Content und Weiterleitungen beheben

WordPress auf HTTPS umstellen: kostenlose Zertifikate, sichere URL-Ersetzung mit WP-CLI, ein 301-Redirect, Proxy-Schleifen, Mixed Content und Ablaufkontrolle.

Von , AngelForce OÜ 7 Min. Lesezeit

Auch auf: English Français Español Italiano Polski Português Türkçe

Die meisten HTTPS-Probleme in WordPress entstehen durch eine halb erledigte Umstellung, nicht durch ein fehlendes Zertifikat. Das Zertifikat ist installiert, auf der Startseite erscheint das Schloss. Die Blogbeiträge zeigen aber ein Warnsymbol, im Inhalt stehen noch alte http://-Links, und wer example.com eintippt, landet erst nach zwei oder drei Weiterleitungen auf der eigentlichen Seite. Diese Anleitung bringt das in sicherer Reihenfolge in Ordnung.

WordPress HTTPS: Das Zertifikat ist erst der Anfang

Messen Sie zuerst. Diese beiden Befehle zeigen, was der Browser eines Besuchers durchläuft:

curl -sI http://example.com
curl -sIL http://example.com | grep -iE '^(HTTP|location)'

Der erste Befehl zeigt Statuscode und Location-Header der ersten Antwort. Der zweite folgt jeder Weiterleitung. Sehen Sie vor dem abschließenden 200 mehr als ein 301, haben Sie eine Weiterleitungskette. Öffnen Sie danach Ihre Website im Browser, drücken Sie F12 und sehen Sie sich die Konsole an. Dort tauchen die Mixed-Content-Warnungen auf.

Es hilft auch, klar zu sehen, was HTTPS leistet. Es verschlüsselt den Datenverkehr zwischen Browser und Server und schützt ihn davor, unterwegs verändert zu werden. Damit ist HTTPS eine der Maßnahmen, die die DSGVO in Art. 32 Abs. 1 lit. a ausdrücklich nennt: Verschlüsselung, hier für Login-Passwörter, Kontaktformulare und Bestelldaten. Über die Sicherheit der Website selbst sagt das Zertifikat nichts aus. Eine Seite mit gültigem Zertifikat kann trotzdem ein verwundbares Plugin betreiben, Schadcode enthalten oder ein Admin-Konto mit dem Passwort password123 haben. Wie Verschlüsselung mit den übrigen Sicherheitsmaßnahmen zusammenspielt, lesen Sie in DSGVO Artikel 32 für WordPress.

Diagramm: drei HTTP- und www-Varianten leiten jeweils mit genau einer 301-Weiterleitung auf eine einzige kanonische HTTPS-URL
Jede alte URL-Variante sollte die kanonische HTTPS-Adresse mit einem einzigen Sprung erreichen

Kostenloses Zertifikat vom Hoster oder per ACME

Die meisten Hosting-Oberflächen in der EU bieten ein kostenloses Let's Encrypt-Zertifikat per Schalter an, meist unter „SSL/TLS“ oder „Sicherheit“. Aktivieren Sie es und achten Sie darauf, dass es sowohl example.com als auch www.example.com abdeckt. Ein Zertifikat für nur einen der beiden Namen erzeugt auf dem anderen Browserfehler, selbst wenn dieser nur weiterleitet.

Auf einem eigenen Server nutzen Sie einen ACME-Client. Certbot ist die gängige Wahl und richtet die automatische Verlängerung gleich mit ein:

sudo certbot --nginx -d example.com -d www.example.com
sudo certbot renew --dry-run

Unter Apache verwenden Sie --apache statt --nginx. Der Probelauf prüft, ob die Verlängerung tatsächlich funktioniert. Scheitert er jetzt, scheitert auch die nächste echte Verlängerung.

Für das Schloss im Browser müssen Sie kein domainvalidiertes Zertifikat kaufen. Kostenpflichtige Zertifikate lohnen sich bei Supportverträgen oder besonderen Validierungsanforderungen. Bei der Verschlüsselung ist ein kostenloses Zertifikat genauso stark.

Erst sichern, dann WordPress- und Website-Adresse umstellen

Sichern Sie die Datenbank, bevor Sie irgendetwas ändern. Die folgenden Schritte schreiben Tausende Zeilen um, und das Backup ist Ihre Rückgängig-Taste. Wie Sie Sicherungen anlegen, auf die Sie sich verlassen können, steht in WordPress-Backups, die sich wirklich wiederherstellen lassen. Mit WP-CLI genügt eine Zeile:

wp db export before-https.sql

Gehen Sie dann zu Einstellungen > Allgemein und ändern Sie WordPress-Adresse (URL) und Website-Adresse (URL) von http:// auf https://. Liegt WordPress in einem Unterverzeichnis, behalten Sie den Pfad bei. Auf der Kommandozeile geht das so:

wp option update home 'https://example.com'
wp option update siteurl 'https://example.com'

Sind die beiden Felder ausgegraut, stehen WP_HOME und WP_SITEURL in der wp-config.php. Ändern Sie die Werte dann dort. Einstellungen im Dashboard können sie nicht überschreiben.

Wurden Sie abgemeldet und kommen nicht mehr hinein, etwa weil das Zertifikat noch nicht funktioniert, definieren Sie WP_HOME und WP_SITEURL vorübergehend in der wp-config.php mit der alten http://-Adresse (oder setzen Sie sie zurück, falls sie dort schon stehen). Alternativ führen Sie die beiden wp option update-Befehle mit den alten Werten aus. Bringen Sie zuerst das Zertifikat in Ordnung und versuchen Sie es dann erneut.

Alte http://-URLs sicher mit wp search-replace ersetzen

Beiträge, Menüs, Widgets und Theme-Optionen enthalten noch Hunderte http://example.com-Links. Reparieren Sie diese nicht mit einem rohen SQL-REPLACE. WordPress und viele Plugins speichern Einstellungen als serialisiertes PHP, und dabei wird die Länge jeder Zeichenkette mitgespeichert, zum Beispiel s:22:"http://example.com/img". Durch das zusätzliche „s“ wird die Zeichenkette ein Zeichen länger. Die gespeicherte Länge stimmt nicht mehr, PHP kann den Wert nicht lesen, und Widgets, Page-Builder-Layouts oder Theme-Einstellungen verschwinden kommentarlos.

[wp search-replace](https://developer.wordpress.org/cli/commands/search-replace/) entpackt die serialisierten Daten, ersetzt den Text und serialisiert sie mit korrekten Längen neu. Machen Sie immer zuerst einen Probelauf:

wp search-replace 'http://example.com' 'https://example.com' --all-tables --skip-columns=guid --dry-run

Prüfen Sie die Trefferzahlen pro Tabelle. Wirken sie plausibel, führen Sie denselben Befehl ohne --dry-run aus. Ein paar Hinweise dazu:

  • --skip-columns=guid lässt die GUIDs der Beiträge unangetastet. Sie sind Kennungen, keine Links, und werden üblicherweise nicht geändert.
  • --all-tables bearbeitet jede Tabelle der Datenbank. Teilt sich die Datenbank mit einer anderen Website oder Anwendung, verwenden Sie stattdessen --all-tables-with-prefix.
  • Ist Ihr kanonischer Host ohne www, führen Sie eine zweite Ersetzung von http://www.example.com nach https://example.com aus.
  • Manche Page Builder speichern JSON mit maskierten Schrägstrichen (http:\/\/example.com), die eine einfache Suche nicht findet. Machen Sie für diese Schreibweise einen eigenen Probelauf oder nutzen Sie das URL-Ersetzungswerkzeug des Page Builders.

Leeren Sie danach sämtliche Caches: wp cache flush, Ihr Page-Cache-Plugin, einen eventuellen Server-Cache und das CDN. Lassen Sie die CSS-Dateien des Page Builders neu erzeugen, falls er das anbietet. Ohne SSH-Zugang erledigt ein Such-und-Ersetz-Plugin, das serialisierte Daten korrekt behandelt, etwa Better Search Replace, dieselbe Aufgabe. Löschen Sie es anschließend wieder.

Eine einzige 301-Weiterleitung zum kanonischen HTTPS-Host

Legen Sie sich auf eine kanonische Adresse fest, mit oder ohne www, und bleiben Sie dabei. Jede andere Variante sollte mit einer einzigen 301-Weiterleitung direkt dorthin führen. Eine Kette wie http → https → www → Ziel bremst jeden Erstbesuch, verschwendet das Crawl-Budget der Suchmaschinen und macht Fehler schwer nachvollziehbar.

Apache, oberhalb des Blocks # BEGIN WordPress in der .htaccess:

RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [L,R=301]

nginx:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name www.example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    return 301 https://example.com$request_uri;
}

Halten Sie die Weiterleitung an genau einer Stelle. Leiten ein Plugin, die .htaccess und das CDN gleichzeitig um, entstehen Ketten oder Schleifen. Entscheiden Sie sich für den Server oder das CDN und entfernen Sie die übrigen Regeln.

Weiterleitungsschleifen hinter CDN oder Reverse Proxy

Der Klassiker ist der SSL-Modus „Flexible“ bei Cloudflare. Der Browser spricht HTTPS mit Cloudflare, Cloudflare aber unverschlüsseltes HTTP mit Ihrem Server. Der Server sieht HTTP, leitet auf HTTPS um, und das Spiel beginnt von vorn. Installieren Sie ein Zertifikat auf dem Server und stellen Sie in den SSL/TLS-Einstellungen von Cloudflare den Modus Full (strict) ein. Dann ist auch die Verbindung zum Server verschlüsselt, und das Server-Zertifikat wird geprüft.

Andere Proxys und Load Balancer übergeben das ursprüngliche Schema im Header X-Forwarded-Proto. WordPress wertet ihn standardmäßig nicht aus. Fügen Sie in der wp-config.php oberhalb der Zeile „That's all, stop editing!“ Folgendes ein:

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
    $_SERVER['HTTPS'] = 'on';
}

FORCE_SSL_ADMIN und die Login-Seite

define( 'FORCE_SSL_ADMIN', true );

Damit liefert WordPress die Login-Seite und das Dashboard nur noch über HTTPS aus. Passwörter und Admin-Cookies gehen nie unverschlüsselt über die Leitung, auch wenn jemand ein altes http://-Lesezeichen öffnet. Das ist ein Sicherheitsnetz, kein Ersatz für Ihre Weiterleitung, und für die öffentlichen Seiten bewirkt es nichts. Weitere Einstellungen in der wp-config.php behandelt wp-config.php härten: 10 Einstellungen, die Sie prüfen sollten.

Verbleibenden Mixed Content in den Entwicklertools finden

Mixed Content bedeutet: Eine HTTPS-Seite lädt eine Ressource über HTTP. Browser blockieren unsichere Skripte und Frames und warnen bei Bildern oder laden sie per HTTPS nach. Deshalb verschwindet das Schloss. Öffnen Sie auf einer betroffenen Seite die DevTools. Die Konsole listet jede unsichere Anfrage samt URL auf. In Chromium-basierten Browsern sehen Sie alle auf einmal, wenn Sie im Netzwerk-Tab scheme:http in den Filter eingeben.

Nach einem sauberen search-replace liegen die restlichen Ursachen meist außerhalb der Datenbank. Typisch sind fest eingetragene URLs in Theme-Dateien, Widgets vom Typ „Individuelles HTML“, eigenes CSS (background: url(http://...)), CSS-Dateien des Page Builders und alte Einbettungen von Drittanbietern. Im Theme finden Sie sie so:

grep -rn "http://" wp-content/themes/your-theme/
wp db search 'http://example.com'

Beheben Sie das Problem an der Quelle. Plugins, die URLs bei jedem Seitenaufruf umschreiben, verdecken den Fehler nur und wirken nicht mehr, sobald sie deaktiviert sind. Die CSP-Direktive upgrade-insecure-requests kann als Übergangslösung dienen, während Sie aufräumen. Sie wird in WordPress-Sicherheitsheader erklärt.

Prüfen Sie mehr als die Startseite: den Checkout, das Kontaktformular, die Login-Seite, einen Blogbeitrag, ein Kategoriearchiv und jede Landingpage, die mit einem anderen Template gebaut ist.

Zertifikatsablauf überwachen, dann HSTS aktivieren

Die automatische Verlängerung kann scheitern, ohne dass es jemand merkt. Häufige Ursachen sind eine DNS-Änderung, der Wechsel zu einem neuen CDN oder eine Firewall- bzw. Weiterleitungsregel, die /.well-known/acme-challenge/ blockiert. Richten Sie ein externes Monitoring ein, das das Zertifikat prüft und Sie spätestens zwei Wochen vor Ablauf warnt. Viele Uptime-Dienste haben diese Prüfung eingebaut. Das Ablaufdatum können Sie auch selbst auslesen:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate

HSTS (RFC 6797) kommt zuletzt. Es weist Browser an, nur noch HTTPS zu verwenden. Ein defektes Zertifikat wird damit für Besucher zum harten Fehler, und mit includeSubDomains gilt das auch für jede vergessene Subdomain, die nur über HTTP läuft. Aktivieren Sie HSTS erst, wenn alle Subdomains und Weiterleitungen funktionieren, und beginnen Sie mit einem kurzen max-age. Die Werte und die Warnung zur Preload-Liste finden Sie in WordPress-Sicherheitsheader.

Das Audit-Plugin von secaudit.eu prüft Härtungs- und Konfigurationseinstellungen sowie Dateiintegrität und veraltete Plugins. Nach der Umstellung haben Sie damit eine Momentaufnahme des Zustands Ihrer Website, die Sie für Ihre Dokumentation aufbewahren können. → secaudit.eu

Nächster Schritt: Führen Sie die Prüfung mit curl -sIL für alle vier Varianten aus (http, http://www, https://www, https). Öffnen Sie dann Ihre fünf wichtigsten Seiten mit geöffneter DevTools-Konsole. Höchstens ein 301 pro Variante, ein direktes 200 für die kanonische HTTPS-URL und keine Mixed-Content-Meldungen: Dann ist die Umstellung abgeschlossen.

FAQ

Reicht ein kostenloses Zertifikat für einen Onlineshop?

Ja. Ein kostenloses domainvalidiertes Zertifikat verschlüsselt genauso stark wie ein kostenpflichtiges. Die Sicherheit des Shops hängt von Plugins, Updates, Logins und der Zahlungsanbindung ab, nicht vom Preis des Zertifikats.

Warum verschwindet das Schloss nur auf einigen Seiten?

Diese Seiten laden mindestens eine Ressource über HTTP. Meist ist das ein Bild, ein Skript oder eine Einbettung aus einem Widget, einem Template oder einem Page-Builder-Abschnitt, den die anderen Seiten nicht verwenden. Die DevTools-Konsole auf dieser Seite zeigt Ihnen die genaue URL.

Macht HTTPS meine Website DSGVO-konform?

Nein. HTTPS ist eine technische Maßnahme nach Art. 32, nämlich die Verschlüsselung bei der Übertragung. Die DSGVO verlangt außerdem, dass Sie die Systeme selbst absichern, Daten nach Zwischenfällen wiederherstellen können, Ihre Maßnahmen regelmäßig überprüfen und all das dokumentieren.

Dieser Artikel ist eine allgemeine Information und keine Rechtsberatung.

Prüfen Sie Ihre eigene Website

Security Audit & Compliance ist das WordPress-Plugin von secaudit.eu: Es sucht nach Malware, verstecktem Spam, veränderten Kerndateien und unsicherem Code und ordnet seine Befunde DSGVO Art. 32, NIS2 Art. 21 und den OWASP Top 10 zu.

Sehen, was das Plugin prüft
Melike Görel

Melike Görel schreibt die secaudit.eu-Ratgeber zu WordPress-Sicherheit und EU-Compliance für die AngelForce OÜ, das Softwareunternehmen aus Tallinn hinter secaudit.eu.

Mit KI-Unterstützung erstellt und vor der Veröffentlichung auf Fakten geprüft. Dieser Artikel ist eine allgemeine Information und keine Rechtsberatung.