Ich habe kürzlich von einer Browserfunktion erfahren, bei der, wenn Sie einen speziellen HTTP-Header bereitstellen, automatisch eine URL mit einem Bericht über nicht-HTTPS-Inhalte aufgerufen wird. Dies wäre beispielsweise eine großartige Sache, wenn eine Website zu HTTPS migriert wird, um Warnungen wegen *gemischtem Inhalt* zu beseitigen. In diesem Artikel werden wir diese Funktion über ein kleines WordPress-Plugin implementieren.
Was ist gemischter Inhalt?
„Gemischter Inhalt“ bedeutet, dass Sie eine Seite über HTTPS laden, aber einige der Assets auf dieser Seite (Bilder, Videos, CSS, Skripte, von Skripten aufgerufene Skripte usw.) werden über einfaches HTTP geladen.

Ich gehe davon aus, dass wir alle mit dieser Warnung bestens vertraut sind, und verweise den Leser für weitere Hintergrundinformationen zu gemischtem Inhalt auf diese ausgezeichnete Einführung.
Was ist Content Security Policy?
Eine Content Security Policy (CSP) ist eine Browserfunktion, die uns die Möglichkeit gibt, den Browser anzuweisen, wie er mit Fehlern bei gemischtem Inhalt umgehen soll. Durch die Einbindung spezieller HTTP-Header in unsere Seiten können wir dem Browser mitteilen, gemischten Inhalt zu blockieren, zu aktualisieren oder zu melden. Dieser Artikel konzentriert sich auf die Berichterstattung, da sie uns einen einfachen und nützlichen Einstieg in CSPs im Allgemeinen bietet.
CSP ist ein seltsam undurchsichtiger Name. Lassen Sie sich davon nicht einschüchtern, da die Arbeit damit sehr einfach ist. Laut caniuse scheint die Unterstützung hervorragend zu sein. Hier ist, wie der ausgehende Bericht in Chrome gestaltet ist
{
"csp-report": {
"document-uri":"https:///wp/2017/03/21/godaddys-micro-dollars/",
"referrer":"https:///wp/",
"violated-directive":"style-src",
"effective-directive":"style-src",
"original-policy":"default-src https: 'unsafe-inline' 'unsafe-eval'; report-uri https:///wp/wp-json/csst_consecpol/v1/incidents",
"disposition":"report",
"blocked-uri":"https:///wp/wp-includes/css/dashicons.min.css?ver=4.8.2",
"status-code":200,
"script-sample":""
}
}
Hier ist, wie es in seinem natürlichen Lebensraum aussieht

Was mache ich damit?
Sie müssen dem Browser mitteilen, an welche URL dieser Bericht gesendet werden soll, und dann auf Ihrem Server eine Logik haben, die ihn empfängt. Von dort aus können Sie ihn in eine Log-Datei, eine Datenbanktabelle, eine E-Mail oder was auch immer schreiben lassen. Seien Sie sich nur bewusst, dass Sie wahrscheinlich eine überwältigende Menge an Berichten generieren werden. Seien Sie sehr auf der Hut vor Selbst-DoS!
Kann ich ein Beispiel sehen?
Das können Sie! Ich habe ein kleines WordPress-Plugin erstellt, um es Ihnen zu zeigen. Das Plugin hat keine Benutzeroberfläche, aktivieren Sie es einfach und legen Sie los. Sie könnten die meisten Teile davon herausnehmen und in einer Nicht-WordPress-Umgebung recht direkt verwenden, und dieser Artikel setzt keine besonderen WordPress-Kenntnisse voraus, abgesehen vom Aktivieren eines Plugins und einer gewissen Navigation im Dateisystem. Den Rest dieses Artikels werden wir damit verbringen, uns mit dem besagten Plugin zu beschäftigen.
Senden der Header
Unser erster Schritt wird darin bestehen, unsere Content Security Policy als HTTP-Header einzubinden. Schauen Sie sich diese Datei aus dem Plugin an. Sie ist ziemlich kurz, und ich denke, Sie werden erfreut sein zu sehen, wie einfach sie ist.
Der relevante Teil ist diese Zeile
header( "Content-Security-Policy-Report-Only: default-src https: 'unsafe-inline' 'unsafe-eval'; report-uri $rest_url" );
Es gibt viele Argumente, mit denen wir herumspielen können.
- Mit dem Argument
Content-Security-Policy-Report-Onlysagen wir, dass wir einen Bericht über die Assets erhalten möchten, die unsere Richtlinie verletzen, aber wir möchten sie nicht tatsächlich blockieren oder anderweitig beeinträchtigen. - Mit dem Argument
default-srcsagen wir, dass wir nach allen Arten von Assets Ausschau halten, im Gegensatz zu nur Bildern oder Schriftarten oder Skripten, zum Beispiel. - Mit dem Argument
httpssagen wir, dass unsere Richtlinie nur Assets genehmigt, die über https geladen werden. - Mit den Argumenten
unsafe-inlineundunsafe-evalsagen wir, dass wir uns sowohl für Inline-Ressourcen wie ein normales Bild-Tag als auch für verschiedene Methoden zur Erzeugung von Code aus Zeichenketten interessieren, wie dieeval()-Funktion von JavaScript. - Schließlich, und das ist am interessantesten, geben wir mit dem Argument
report-uri $rest_urldem Browser eine URL, an die er den Bericht senden soll.
Wenn Sie weitere Details zu den Argumenten wünschen, gibt es ein exzellentes Dokument auf Mozilla.org. Es ist auch erwähnenswert, dass wir unsere CSP stattdessen als Meta-Tag senden könnten, obwohl ich die Syntax umständlich finde und Google anmerkt, dass dies nicht ihre bevorzugte Methode ist.
Dieser Artikel wird nur die HTTP-Header-Technik verwenden, und Sie werden feststellen, dass ich in meinem Header etwas Arbeit leiste, um die Berichts-URL zu erstellen. Es handelt sich zufällig um eine WP API-URL. Das werden wir als Nächstes untersuchen.
Registrierung eines Endpunkts
Sie sind wahrscheinlich mit der WP API vertraut. In den alten Tagen, bevor es die WP API gab, habe ich oft eine Seite oder einen Beitrag eines benutzerdefinierten Post-Typs erstellt, wenn ich eine beliebige URL benötigte, um auf eine Formularübermittlung zu reagieren. Das war ärgerlich und fehleranfällig, weil es zu einfach war, die Seite im wp-admin zu löschen, ohne zu merken, wofür sie bestimmt war. Mit der WP API haben wir eine viel stabilere Möglichkeit, einen Listener zu registrieren, und das tue ich in dieser Klasse. In dieser Klasse gibt es drei interessante Punkte.
In der ersten Funktion rufe ich nach einer Überprüfung, ob mein Protokoll nicht zu groß wird, register_rest_route() auf, was eine Kernfunktion von WordPress zum Registrieren eines Listeners ist.
function rest_api_init() {
$check_log_file_size = $this -> check_log_file_size();
if( ! $check_log_file_size ) { return FALSE; }
...
register_rest_route(
CSST_CONSECPOL . '/' . $rest_version,
'/' . $rest_ep . '/',
array(
'methods' => 'POST',
'callback' => array( $this, 'cb' ),
)
);
}
Diese Funktion erlaubt mir auch, eine Callback-Funktion zu registrieren, die den gesendeten CSP-Bericht bearbeitet.
function cb( \WP_REST_Request $request ) {
$body = $request -> get_body();
$body = json_decode( $body, TRUE );
$csp_report = $body['csp-report'];
...
$record = new Record( $args );
$out = $record -> get_log_entry();
}
In dieser Funktion bearbeite ich den Bericht in seinem Rohformat zu einem PHP-Array, das meine Logging-Klasse verarbeiten wird.
Erstellung einer Log-Datei
In dieser Klasse erstelle ich ein Verzeichnis im wp-content-Ordner, in dem meine Log-Datei liegen wird. Ich bin kein großer Fan davon, solche Dinge bei jedem Seitenaufruf zu überprüfen. Beachten Sie daher, dass diese Funktion zuerst prüft, ob es sich um den ersten Seitenaufruf seit einem Plugin-Update handelt, bevor sie sich die Mühe macht, das Verzeichnis zu erstellen.
function make_directory() {
$out = NULL;
$update = new Update;
if( ! $update -> get_is_update() ) { return FALSE; }
$log_dir_path = $this -> meta -> get_log_dir_path();
$file_exists = file_exists( $log_dir_path );
if( $file_exists ) { return FALSE; }
$out = mkdir( $log_dir_path, 0775, TRUE );
return $out;
}
Diese Update-Logik befindet sich in einer anderen Klasse und ist für viele Dinge äußerst nützlich, aber für diesen Artikel von keinem besonderen Interesse.
Protokollierung von gemischtem Inhalt
Nachdem wir nun CSP-Berichte erhalten und ein Verzeichnis zur Protokollierung haben, sehen wir uns an, wie ein Bericht tatsächlich in einen Protokolleintrag umgewandelt wird.
In dieser Klasse habe ich eine Funktion zum Hinzufügen neuer Datensätze zu unserer Log-Datei. Es ist interessant, dass ein Großteil der Schwerstarbeit einfach darin besteht, das Argument a für die Funktion fopen() bereitzustellen.
function add_row( $array ) {
// Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it.
$mode = 'a';
// Open the file.
$path = $this -> meta -> get_log_file_path();
$handle = fopen( $path, $mode );
// Add the row to the spreadsheet.
fputcsv( $handle, $array );
// Close the file.
fclose( $handle );
return TRUE;
}
Hier gibt es nichts Besonderes an WordPress, nur einen Typen, der eine Zeile zu einer CSV-Datei auf normale PHP-Art hinzufügt. Auch hier gilt: Wenn Sie die Idee einer Log-Datei nicht mögen, könnten Sie eine E-Mail senden oder in die Datenbank schreiben lassen, oder was auch immer Ihnen am besten erscheint.
Einschränkungen
An diesem Punkt haben wir alle interessanten Highlights aus meinem Plugin behandelt, und ich möchte noch ein paar Stolpersteine erwähnen, auf die Sie achten sollten.
Erstens sollten Sie bedenken, dass CSP-Berichte, wie jede Browserfunktion, plattformübergreifenden Unterschieden unterliegen. Sehen Sie sich diesen schockierend, sorgfältig detaillierten Bericht über solche Unterschiede an.
Zweitens sollten Sie bedenken, dass, wenn Ihre Serverkonfiguration die Anforderung von gemischtem Inhalt verhindert, der Browser nie die Möglichkeit hat, darüber zu berichten. In einem solchen Szenario sind CSP-Berichte nützlicher als Mittel zur Vorbereitung auf eine Migration zu HTTPS, als als Mittel zur Überwachung der HTTPS-Konformität. Ein Beispiel für diese Konfiguration ist Cloudflares "Immer HTTPS verwenden".
Schließlich muss **das Problem der Selbst-DoS noch einmal wiederholt werden**. Es ist völlig vertretbar anzunehmen, dass eine beliebte Website Millionen von Berichten pro Monat ansammeln wird. Betrachten Sie daher anstatt die Berichte auf Ihrem eigenen Server oder Ihrer Datenbank zu verfolgen, die Auslagerung an einen Dienst wie httpschecker.net.
Nächste Schritte
Einige nächste Schritte für WordPress wären, eine Benutzeroberfläche zum Herunterladen der Berichtsdatei hinzuzufügen. Sie könnten die Berichte auch in der Datenbank statt in einer Datei speichern. Dies würde es wirtschaftlich machen, beispielsweise zu ermitteln, ob ein neuer Datensatz bereits existiert, bevor er als Duplikat hinzugefügt wird.
Allgemeiner ermutige ich den neugierigen Leser, mit den vielen möglichen Argumenten für den CSP-Header zu experimentieren. Es ist beeindruckend, dass so viel Macht in einer so knappen Syntax verpackt ist. Es ist möglich, Anfragen nach Asset-Typ, Domain, Protokoll zu verarbeiten – wirklich fast jede erdenkliche Kombination.
guter Artikel Scott bro… und wie sieht es mit Force SSL Plugins aus?
https://wordpress.org/plugins/force-https-littlebizzy/
Ist das die gleiche Funktion? Danke für die Antwort.
Danke!
Das könnte ein großartiges Plugin sein, ich habe keine Ahnung. Ich würde ehrlich gesagt lieber meine IQ-Punkte darauf verwenden, zu lernen, was CloudFlare in ähnlichen Bereichen leisten kann.
Schöner Artikel, gut geschrieben und zugänglich. :) Ein paar Punkte, die erwähnenswert sind
CSP ist viel mehr als nur eine Möglichkeit, Warnungen wegen „gemischtem Inhalt“ zu verwalten; dies ist eher ein „Nebeneffekt-Nutzen“. CSP ist tatsächlich eine sehr leistungsstarke Sicherheitsfunktion für das Web: Es ist eine starke Verteidigung gegen verschiedene böswillige Angriffe (insbesondere Cross-Site-Scripting).
Die richtige Konfiguration von CSP ist etwas knifflig. Um den vollen Nutzen zu erzielen, ist es wichtig, Dinge wie Inline-Skripte zu blockieren, aber dies kann für viele Websites (insbesondere WordPress-Websites) unpraktisch sein.
Das Mozilla Observatory ist eine nützliche Ressource, um zu überprüfen, wie gut Ihre CSP konfiguriert ist, sowie mehrere andere wichtige SSL (TLS)-Probleme.
Wie Sie im Artikel erwähnt haben, können CSP-Berichte extrem laut sein, und es besteht sogar die Gefahr, Ihren Server zu überlasten. Das Schreiben eines guten CSP-Logging-Dienstes ist ebenfalls sehr schwierig. Es ist viel besser, ReportURI zu verwenden. Obwohl dies jetzt ein kostenpflichtiger Dienst ist, hat er eine ausgezeichnete kostenlose Stufe, die für die meisten Websites mehr als ausreichend sein sollte.
Sie haben absolut Recht. Ich hoffte, hier einen Ankerpunkt für die Tiefentaucher der Welt zu bieten (verzeihen Sie die gemischte Metapher :D).