Archiv der Kategorie: Security

PHP Hashes und ihre Probleme

Ein schon ein etwas älteres Phänomen, welches mir demletzt erneut über den Weg gelaufen ist und ich es deswegen für „verbloggenswert“ halte:

if (md5('240610708') == md5('QNKCDZO'))
{
	echo "yep equal";
}

Ups? Eine MD5-Kollision? Nein. Eine Eigenart von PHP.

var_dump(md5('240610708')); //string(32) "0e462097431906509019562988736854"
var_dump(md5('QNKCDZO'));   //string(32) "0e830400451993494058024219903391"

2 verschiedene Strings, die aber laut PHP-Vergleich identisch sein sollen? Genau da liegt der Knackpunkt: Die Strings sind gleich, aber nicht identisch. Da beide mit 0e anfangen, werden sie als Exponentialdarstellung einer Zahl aufgefasst. Und da 0irgendwas immer 0 ergibt, sind die beiden Hashes im Vergleich auch gleich.

Das „Problem“ lässt sich einfach lösen, indem mit === verglichen wird. Dann evaluiert PHP den Zahlenwert des Strings nicht mehr. Oder indem strcmp verwendet wird:

Veröffentlicht unter php, Security, Quicktips, webdev | 1 Kommentar

Hacker spielen mit WebGoat

OWASP (The open web application security project) sollte ja jedem bekannt sein – OWASP hat sich besonders durch die OWASP Top 10 hervorgetan, in der die 10 größten Security-Risiken zusammengestellt sind. Ebenfalls von OWASP gibt es das WebGoat Project – eine Webseite, die step by step an die Websecurity heranführt. Von XSS über Session Fixation bis zu DOS kann man mit WebGoat alles geführt in Form einer Anleitung nachvollziehen.

Also: WebGoat hier herunterladen und entpacken, die Datei webgoat_8080.bat startet den integrierten Tomcat-Server auf Port 8080. Ist das getan, gilt es die URL http://localhost:8080/WebGoat/attack aufzurufen und sich mit webgoat – webgoat anzumelden.

Veröffentlicht unter Security, webdev | Hinterlasse einen Kommentar

MySQL-Injection mal anders

Man nehme folgenden Script-Aufbau:

<?php
$mysqli = new mysqli('localhost', 'root', '', 'datatabletest');
$rating = $mysqli->real_escape_string($_GET['rating']);
$sql = "SELECT name, rating FROM movies WHERE rating > " . $rating;

Da wir ja mustergültig escapen, sollte eigentlich nichts schief gehen – oder? Nun, der Benutzer übermittelt in $_GET[‚rating‘] folgenden Wert:

3 AND 0 = IF(1, BENCHMARK(1000000, MD5(REPEAT(CONVERT(1, CHAR), 1000))), 0)

Der Wert von $sql lautet danach:

SELECT name, rating FROM movies WHERE rating > 3 AND 0 = IF(1, BENCHMARK(1000000, MD5(REPEAT(CONVERT(1, CHAR), 1000))), 0)

Ein astreines DoS-Einfallstor. In solchen Fällen besser intval verwenden.

Original entdeckt von ulf-wendel.de.

Veröffentlicht unter Datenbanken, Security, webdev | 4 Kommentare

Sicheres Hashing in PHP

PHP bringt prinzipiell alles mit, um anständiges Hashing zu betreiben. bcrypt ist der Way To Go, aber auch ohne bcrypt kann man mit vernünftigem Einsatz der vorhanden Hashing-Algorithmen (Iterationen + Salt) gut zurechtkommen – Symfony machts im MessageDigestPasswordEncoder.php richtig. Hauptproblem ist aber, dass vom Durchschnitts-Nutzer zuviel Wissen abverlangt wird, um wirklich sicheres Hashing zu betreiben. Deswegen schickt sich jetzt in PHP 5.5 eine Hashing-Library an, es besser zu machen. Bis es soweit ist und die Funktionalität im Core ankommt, gibt es für PHP >= 5.3.7 eine Compatiblity-Library, die das Verhalten der kommenden Hashing-Funktionen nachbildet.

Die Signaturen der Funktionen aus der Compat-Library sind wie folgt: password_hash($password, $algo, $options = array())

Veröffentlicht unter php, Security, webdev | 2 Kommentare

htmlspecialchars richtig nutzen – Fallstricke

In der PHP-Welt scheint der Mythos vorzuherrschen, dass die Nutzung von htmlspecialchars sämtlichen Input in sämtlichen Situation sicher macht. Quasi die „one fits all“ – Funktion. Beginnen wir gleich mal mit einem Beispiel. Kein Witz, so gesehen:

function get_user_id($db)
{
	$username = htmlspecialchars(trim($_POST['username']));
	$res = $db->query("SELECT `id` FROM `accounts` WHERE `login` = '$username' LIMIT 1");
	return $res[0]['id'];
}

Cool! Schauen wir uns doch mal die Signatur von htmlspecialchars an:

string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' [, bool $double_encode = true ]]] )

Das verflixte Hochkomma

Besonderes Augenmerk sei auf die Flags gelegt. ENT_COMPAT heißt „Konvertiert nur doppelte Anführungszeichen und lässt einfache Anführungszeichen unverändert.„. Also: Perfektes Einfallstor für SQL-Injection.

Gleiches ergibt sich im Formularhandling:

<?php
$_GET['firstname'] = "'onmouseover='alert(/xss!/)'";
$firstname = htmlspecialchars($_GET['firstname'], ENT_COMPAT);
?>
<input name='firstname' value='<?php echo $firstname ?>'>

Veröffentlicht unter php, Security, webdev | 4 Kommentare

Content Security Policy – Tutorial

Das Problem Cross-Site-Scripting / XSS ist präsenter denn je – ständig hört man von neuen Angriffen mit teils verheerenden Folgen, die weit über das Entstellen von Gästebüchern hinausgehen. Seit 2009 in der Entwicklung und mittlerweile mit einer fast vollständigen Implementierung in Chrome und Firefox schickt sich die Content Security Policy nun an, XSS den Kampf anzusagen. Aktuell befindet sich die CSP noch im Status W3C Working Draft und wird speziell um HTML5-relevante Features wie etwa Web-Sockets ergänzt. Das heißt umgekehrt, dass man sie bereits heute problemlos verwenden kann. Aber von vorne.

Veröffentlicht unter php, Security, webdev | 5 Kommentare

Why URL validation with filter_var might not be a good idea

Since PHP 5.2 brought us the filter_var function, the time of such monsters was over (taken from here):

$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";}

The simple, yet effective syntax:

filter_var($url, FILTER_VALIDATE_URL)

As third parameter, filter flags can be passed. Considering URL validation, the following 4 flags are availible:

FILTER_FLAG_SCHEME_REQUIRED
FILTER_FLAG_HOST_REQUIRED
FILTER_FLAG_PATH_REQUIRED 
FILTER_FLAG_QUERY_REQUIRED 

The first two FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED are the default.

Get started!

Alright, let’s look at some critical examples.

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

Well, nobody said that filter_var was built to fight XSS. Let’s accept this and move on:

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

Veröffentlicht unter php, Security, PHP-WTF, webdev | 7 Kommentare

IE und Chrome mit Standard-XSS-Filter (X-XSS-Protection)

Ich war gerade sehr überrascht, als ich im Zuge des Herumexperimentierens mit der Content Security Policy (kommt auch bald noch ein Artikel dazu – Update: Content Security Policy – Tutorial) folgendes Standard-Beispiel aufgebaut habe …

<input type="text" value="<?php echo $_GET['value']; ?>" />

… und dann das Standard-XSS-Pattern ?value=“><script>alert(1234)</script> übermittelt habe. Resultat im Chrome:

Chrome Filter

Chrome Filter

Bezieht sich übrigens nur auf die Injection von <script>-Tags, ein <b> – Tag geht also durch. Soweit ganz sinnvoll, kann mir jedenfalls keinen legitimen Fall vorstellen, wo ein script-Tag per URL-Parameter benötigt werden könnte. Im IE (ab Version 8) dasselbe Spiel:

IE XSS Filter

IE XSS Filter

Veröffentlicht unter php, Security, Quicktips, webdev | 1 Kommentar

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:

Veröffentlicht unter php, Security, webdev | 1 Kommentar

Interessante Testarten: Mutationstest und Fuzzing

Bin heute über 2 Testverfahren gestolpert, die ich vorher noch nicht auf der Rechnung hatte. Fangen wir beim Mutationstest an.

Mutationstest

Dabei wird die zu testende Applikation vollautomatisch von einem Programm abgeändert. Das kann etwa so aussehen, dass in einer Schleife aus einem <= ein < gemacht wird. Hier orientiert sich die Art der eigebauten Fehler an den gern von Programmierern gemachten, also z.B. Schleifengrenzen und Verschachtelungen. Wichtig ist hierbei, dass pro Durchlauf immer nur eine Manipulation vorgenommen wird, sonst lässt sich die Auswirkung schließlich schlecht lokalisieren.

Veröffentlicht unter php, Software Engineering, Security, webdev | Hinterlasse einen Kommentar