Hier im Forum bekommt ihr bei euren fragen schnelle hilfe.Hier geht es rund um das Web SeitenProgrammieren.Alles rund ums Javascript,Html,Php,Css und Sql.Auf fast allen Fragen haben wir eine Antwort.
Der Soforthilfe-chat verspricht das ,was sein Name sagt. Hier sind Leute Online die sofort ihre hilfe anbieten.Seht in der OnlineListe nach und wenn einer Online ist werdet ihr auch antwort bekommen. Admine ,Moderatoren und Helfer sind unsere Spezialisten in Sachen Web Programierung
71 Unwetterwarnungen in Deutschland
Die Datenbank wurde zuletzt am 02.08.2020 17:34:28 aktualiesiert
71

Warum URL-Validierung mit filter_var keine gute Idee ist

Als uns mit PHP 5.2 die filter_var-Funktion geschenkt wurde, war die Zeit solcher Monster vorbei (hier entliehen):

$urlregex = "^(https?|ftp)\:\/\/([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)*(\:[0-9]{2,5})?(\/([a-z0-9+\$_-]\.?)+)*\/?(\?[a-z+&\$_.-][a-z0-9;:@/&%=+\$_.-]*)?(#[a-z_.-][a-z0-9+\$_.-]*)?\$";  if (eregi($urlregex, $url)) {echo "good";} else {echo "bad";}  

Die simple, aber effektive Syntax:

filter_var($url, FILTER_VALIDATE_URL)  

Als dritten Parameter können Filter-Flags übergeben werden, im Bezug auf die URL-Validierung gibt es die folgenden 4 Kandidaten:

FILTER_FLAG_SCHEME_REQUIRED  FILTER_FLAG_HOST_REQUIRED  FILTER_FLAG_PATH_REQUIRED   FILTER_FLAG_QUERY_REQUIRED   

Dabei sind die ersten beiden FILTER_FLAG_SCHEME_REQUIRED und FILTER_FLAG_HOST_REQUIRED default.

Ans Eingemachte

So, dann schauen wir uns doch mal ein paar kritische Kandidaten an:

filter_var('http://example.com/"><script>alert("xss")</script>', FILTER_VALIDATE_URL) !== false; //true  

Gut, hat ja auch niemand gesagt, dass der URL-Filter XSS bekämpfen soll – also ok. Weiter im Takt:

filter_var('php://filter/read=convert.base64-encode/resource=/etc/passwd', FILTER_VALIDATE_URL) !== false; //true  

Schon kritischer. Ein beliebiges Schema macht den Filter glücklich. http(s) und ftp hätte ich mir ja noch gefallen lassen. Potentiell problematisch. Demnach dann auch ok:

filter_var('foo://bar', FILTER_VALIDATE_URL) !== false; //true  

Und die Krönung zum Schluss

filter_var('javascript://test%0Aalert(321)', FILTER_VALIDATE_URL) !== false; //true  

Schauen wir grad mal genauer hin: javascript ist das Schema. Klar, in die Browser-Adresszeile javascript:alert(1+2+3+4); eingeben und los gehts:

Javascript-URL

Javascript-URL

Ist das Grundprinzip von Bookmarklets und auch kein Geheimnis. Aber weiter: Der doppelte // ist ein gewöhnlicher Javascript-Kommentar, überzeugt aber filter_var davon, dass es sich um ein valides URLSchema handelt – siehe die Beispiele oben. Dann kommt die Zeichenfolge %0A, was genau der Output des folgenden Codes ist:

echo urlencode("\n");  

Dämmerts? Durch das URL-encoded newline wird der eingeleitete Javascript-Kommentar beendet und es folgt beliebiger Javascript-Code. Stellen wir uns eine Dating-Seite vor, bei der Nutzer-URLs mit filter_var validiert werden und dann 1:1 dargestellt werden. Böses Einfallstor.

Und nun?

Zumindest eine händische Anpassung folgender Form könnte sich bewähren:

function validate_url($url)  {  	$url = trim($url);  	  	return ((strpos($url, "http://") === 0 || strpos($url, "https://") === 0) &&  		    filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED) !== false);  }  

Aber selbst nach dieser Anpassung kommt die doch sehr ungewöhnliche URL http://x durch die Validierung durch. Vielleicht sind die Regex-Monster doch nicht so schlecht ;). Ach, bevor ichs vergesse: filter_var ist nicht Multibyte-URL-fähig. Die absolut korrekte URL http://???????.com wird rejected:

var_dump(filter_var("http://???????.com", FILTER_VALIDATE_URL) !== false); //bool(false)  

Also: filter_var mit Bedacht einsetzen und an den jeweiligen Kontext anpassen. Abschließend möchte ich noch auf diese schöne Aufstellung an URLs in Abhängigkeit der verschiedenen filter_var – Flags verweisen.