Wie verhindere ich XSS (Cross-Site-Scripting) mit nur HTML und PHP?
Ich habe zahlreiche andere Beiträge zu diesem Thema gesehen, aber ich habe keinen Artikel gefunden, der klar und prägnant erklärt, wie XSS tatsächlich verhindert werden kann.
Wie verhindere ich XSS (Cross-Site-Scripting) mit nur HTML und PHP?
Ich habe zahlreiche andere Beiträge zu diesem Thema gesehen, aber ich habe keinen Artikel gefunden, der klar und prägnant erklärt, wie XSS tatsächlich verhindert werden kann.
Alix Axel
Grundsätzlich müssen Sie die Funktion verwenden htmlspecialchars()
wenn Sie etwas an den Browser ausgeben möchten, das aus der Benutzereingabe stammt.
Die richtige Art, diese Funktion zu verwenden, sieht ungefähr so aus:
echo htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
Die Google Code University hat auch diese sehr lehrreichen Videos zur Websicherheit:
@TimTim: Für die meisten Fälle, ja. Wenn Sie jedoch HTML-Eingaben zulassen müssen, werden die Dinge etwas kniffliger, und wenn dies der Fall ist, empfehle ich Ihnen, so etwas wie zu verwenden htmlpurifier.org
– Alix Axel
3. Januar 2010 um 20:23 Uhr
@Alix Axel, also ist Ihre Antwort, htmlspecialchars zu verwenden oder zu verwenden htmlpurifier.org?
– Tim Tim
3. Januar 2010 um 20:39 Uhr
Wenn Sie HTML-Eingaben akzeptieren müssen, verwenden Sie HTML Purifier, wenn nicht htmlspecialchars()
.
– Alix Axel
3. Januar 2010 um 20:41 Uhr
htmlspecialchars oder htmlentities ? Überprüfen Sie hier stackoverflow.com/questions/46483/…
– kiranvj
16. November 2012 um 6:19 Uhr
Meistens ist es richtig, aber so einfach ist es nicht. Sie sollten erwägen, nicht vertrauenswürdige Zeichenfolgen in HTML, Js, CSS einzufügen, und erwägen, nicht vertrauenswürdiges HTML in HTML einzufügen. Schau dir das an : owasp.org/index.php/…
– Bronzemann
29. Mai 2014 um 17:43 Uhr
James Kolpack
Einer der wichtigsten Schritte besteht darin, alle Benutzereingaben zu bereinigen, bevor sie verarbeitet und/oder an den Browser zurückgegeben werden. PHP hat einige “Filter“Funktionen, die verwendet werden können.
Die Form von XSS-Angriffen besteht normalerweise darin, einen Link zu einem Off-Site-Javascript einzufügen, das böswillige Absichten für den Benutzer enthält. Lesen Sie mehr darüber Hier.
Sie werden auch Ihre Website testen wollen – Ich kann das Firefox-Add-on empfehlen [XSS Me]. Sieht aus wie Einfaches XSS ist jetzt der richtige Weg.
Was muss ich beachten, damit ich den Eingang genau aus saniere. Gibt es ein bestimmtes Zeichen/eine bestimmte Zeichenfolge, auf die ich achten muss?
– Tim Tim
3. Januar 2010 um 20:14 Uhr
@TimTim – nein. Alle Benutzereingaben sollte immer als von Natur aus feindselig angesehen werden.
– Zombie
3. Januar 2010 um 20:28 Uhr
Außerdem könnten interne Daten (Mitarbeiter, Systemadministrator usw.) unsicher sein. Sie sollten die angezeigten Daten mit Interpretation identifizieren und überwachen (mit Protokolldatum und Benutzer).
– Samuel Dauzon
4. Oktober 2018 um 8:40 Uhr
Matt S
Querveröffentlichung als konsolidierte Referenz aus der Beta-Version der SO-Dokumentation, die offline geht.
Cross-Site-Scripting ist die unbeabsichtigte Ausführung von Remotecode durch einen Webclient. Jede Webanwendung kann sich XSS aussetzen, wenn sie Eingaben von einem Benutzer entgegennimmt und diese direkt auf einer Webseite ausgibt. Wenn die Eingabe HTML oder JavaScript enthält, kann Remotecode ausgeführt werden, wenn dieser Inhalt vom Webclient gerendert wird.
Wenn beispielsweise eine Drittanbieterseite eine JavaScript-Datei enthält:
// http://example.com/runme.js
document.write("I'm running");
Und eine PHP-Anwendung gibt direkt einen übergebenen String aus:
<?php
echo '<div>' . $_GET['input'] . '</div>';
Enthält einen ungeprüften GET-Parameter <script src="http://example.com/runme.js"></script>
dann wird die Ausgabe des PHP-Skripts sein:
<div><script src="http://example.com/runme.js"></script></div>
Das Drittanbieter-JavaScript wird ausgeführt und der Benutzer sieht auf der Webseite „I’m running“.
Vertrauen Sie grundsätzlich niemals dem Input eines Kunden. Jeder GET-Parameter, POST- oder PUT-Inhalt und Cookie-Wert kann alles mögliche sein und sollte daher validiert werden. Wenn Sie einen dieser Werte ausgeben, maskieren Sie sie, damit sie nicht auf unerwartete Weise ausgewertet werden.
Denken Sie daran, dass selbst in den einfachsten Anwendungen Daten verschoben werden können und es schwierig sein wird, alle Quellen im Auge zu behalten. Daher ist es eine bewährte Vorgehensweise immer Ausgang entkommen.
PHP bietet je nach Kontext einige Möglichkeiten, die Ausgabe zu maskieren.
Filterfunktionen von PHP erlauben die Eingabedaten in das PHP-Skript zu sein desinfiziert oder bestätigt in viele Möglichkeiten. Sie sind nützlich, wenn Sie Client-Eingaben speichern oder ausgeben.
htmlspecialchars
konvertiert alle “HTML-Sonderzeichen” in ihre HTML-Kodierungen, was bedeutet, dass sie es dann tun nicht als Standard-HTML verarbeitet werden. So beheben Sie unser vorheriges Beispiel mit dieser Methode:
<?php
echo '<div>' . htmlspecialchars($_GET['input']) . '</div>';
// or
echo '<div>' . filter_input(INPUT_GET, 'input', FILTER_SANITIZE_SPECIAL_CHARS) . '</div>';
Würde ausgeben:
<div><script src="http://example.com/runme.js"></script></div>
Alles drin <div>
Tag wird nicht vom Browser als JavaScript-Tag interpretiert werden, sondern als einfacher Textknoten. Der Benutzer wird sicher sehen:
<script src="http://example.com/runme.js"></script>
Bei der Ausgabe einer dynamisch generierten URL stellt PHP die urlencode
Funktion, um gültige URLs sicher auszugeben. Wenn ein Benutzer beispielsweise Daten eingeben kann, die Teil eines anderen GET-Parameters werden:
<?php
$input = urlencode($_GET['input']);
// or
$input = filter_input(INPUT_GET, 'input', FILTER_SANITIZE_URL);
echo '<a href="http://example.com/page?input="' . $input . '">Link</a>';
Jede böswillige Eingabe wird in einen verschlüsselten URL-Parameter umgewandelt.
Manchmal möchten Sie HTML oder andere Arten von Codeeingaben senden. Sie müssen eine Liste mit autorisierten Wörtern (weiße Liste) und nicht autorisierten (schwarze Liste) führen.
Sie können Standardlisten herunterladen, die unter verfügbar sind OWASP AntiSamy-Website. Jede Liste ist für eine bestimmte Art von Interaktion geeignet (ebay api, tinyMCE usw.). Und es ist Open-Source.
Es gibt Bibliotheken, die HTML filtern und XSS-Angriffe für den allgemeinen Fall verhindern und bei sehr einfacher Verwendung mindestens so gut wie AntiSamy-Listen funktionieren. Sie haben zum Beispiel HTML-Reiniger
In bevorzugter Reihenfolge:
{{ var|e('html_attr') }}
htmlentities($var, ENT_QUOTES | ENT_HTML5, $charset)
und stellen Sie sicher, dass der Rest Ihres Dokuments denselben Zeichensatz verwendet wie $charset
. In den meisten Fällen, 'UTF-8'
ist der gewünschte Zeichensatz.Stellen Sie außerdem sicher, dass Sie Escape bei der Ausgabe, nicht bei der Eingabe.
Webaholik
Viele Frameworks helfen auf verschiedene Weise beim Umgang mit XSS. Wenn Sie Ihr eigenes Rolling durchführen oder XSS-Bedenken bestehen, können wir davon profitieren filter_input_array (verfügbar in PHP 5 >= 5.2.0, PHP 7.) Normalerweise füge ich dieses Snippet meinem SessionController hinzu, da alle Aufrufe dort durchlaufen werden, bevor ein anderer Controller mit den Daten interagiert. Auf diese Weise werden alle Benutzereingaben an einem zentralen Ort bereinigt. Wenn dies zu Beginn eines Projekts geschieht oder bevor Ihre Datenbank vergiftet wird, sollten Sie zum Zeitpunkt der Ausgabe keine Probleme haben … stoppt Müll rein, Müll raus.
/* Prevent XSS input */
$_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
/* I prefer not to use $_REQUEST...but for those who do: */
$_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST;
Das obige wird entfernt ALLE HTML- und Skript-Tags. Wenn Sie eine Lösung benötigen, die sichere Tags basierend auf einer Whitelist zulässt, sehen Sie sich diese an HTML-Reiniger.
Wenn Ihre Datenbank bereits vergiftet ist oder Sie sich zum Zeitpunkt der Ausgabe mit XSS befassen möchten, OWASP empfiehlt das Erstellen einer benutzerdefinierten Wrapper-Funktion für echo
und wenn Sie es ÜBERALL verwenden, geben Sie vom Benutzer bereitgestellte Werte aus:
//xss mitigation functions
function xssafe($data,$encoding='UTF-8')
{
return htmlspecialchars($data,ENT_QUOTES | ENT_HTML401,$encoding);
}
function xecho($data)
{
echo xssafe($data);
}
Abdo-Host
<?php
function xss_clean($data)
{
// Fix &entity\n;
$data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data);
$data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
$data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
$data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
// Remove any attribute starting with "on" or xmlns
$data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
// Remove javascript: and vbscript: protocols
$data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
// Remove namespaced elements (we do not need them)
$data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
do
{
// Remove really unwanted tags
$old_data = $data;
$data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
}
while ($old_data !== $data);
// we are done...
return $data;
}
Chris
Sie können auch einige XSS-bezogene HTTP-Antwortheader über festlegen header(...)
X-XSS-Schutz “1; Modus=blockieren”
Allerdings ist der XSS-Schutzmodus des Browsers aktiviert.
Inhaltssicherheitsrichtlinie “default-src ‘self’; …”
zum Aktivieren der browserseitigen Inhaltssicherheit. Siehe diese für Details zur Inhaltssicherheitsrichtlinie (CSP): http://content-security-policy.com/
Besonders das Einrichten von CSP zum Blockieren von Inline-Skripten und externen Skriptquellen ist hilfreich gegen XSS.
Eine allgemeine Reihe nützlicher HTTP-Antwort-Header zur Sicherheit Ihrer Webanwendung finden Sie unter OWASP: https://www.owasp.org/index.php/List_of_useful_HTTP_headers
Nur eine Anmerkung, dass dies nicht den Fall löst, in dem Sie Benutzereingaben als HTML-Attribut verwenden möchten. Beispielsweise die Quell-URL eines Bildes. Kein häufiger Fall, aber leicht zu vergessen.
– Michael Mior
16. Mai 2011 um 17:12 Uhr
@MichaelMior hier ist eine Lösung, um XSS zu verhindern
href
odersrc
HTML-Attribut: stackoverflow.com/questions/19047119/…– tauf
20. Juli 2019 um 11:30 Uhr
Es gibt einen schönen Artikel Hier das erklärt XSS und wie man es in verschiedenen Sprachen verhindert (inkl. PHP).
– XCore
14. April 2020 um 20:12 Uhr