{the magic lies between the brackets}

Schlagwort: Security (Seite 1 von 1)

[PHP] Nutzung eines CAPTCHA Bildes

Wir erstellten ein CAPTCHA Bild im vorigen Beitrag. Nun wollen wir dieses natürlich auch nutzen. Zuerst benötigen wir die PHP-Datei (im folgenden Beitrag generatecaptcha.php). Diese binden wir nun ein. Wir erstellen eine simple HTML-Datei (hier jetzt: index.html). Da die php-Datei eine Bilddatei ausgibt, können wir das Bild einfach per HTML einbinden. Dazu benutzen wir den HTML Image-tag:

<img id="captcha" title="Captcha-Code" alt="" src="generatecaptcha.php" /> 

Dem Image weisen wir nun noch eine ID zu. Wieso? Dazu kommen wir noch. Ein Feld, in welches wir das CAPTCHA eintragen können und einen Button, welcher die Daten absendet, benötigen wir nun noch:

 CAPTCHA Abfrage <img id="captcha" title="Captcha-Code" alt="" src="generatecaptcha.php" /> <form action="checkcaptcha.php" method="POST"><input type="text" name="captcha_solve" /> <input type="submit" /></form> 

Nun gehen wir noch einmal in die generatecaptcha.php: Denn wie soll der Server wissen, welches CAPTCHA wir generiert haben bzw. welcher Text der richtige ist? Wir benötigen sogenannten Session-Variablen. Diese sehen wie folgt aus:

 $_SESSION['mySessionVar'] 

Es ist zu beachten, dass diese Session-Variablen immer global zugänglich sind. Sie müssen also nicht per Schlüsselwort global definiert werden.
Bevor man solche Variablen jedoch nutzt, muss man eine Session auf dem Server starten, dazu folgende Funktion aufrufen:

session_start();
unset($_SESSION['captcha_spam']);

Hier resette ich gleich die Session-Variable captcha_spam, um sicher zu gehen, dass diese nicht mehr gefüllt ist (unnötig, aber sicher ist sicher.)

Nun erstelle ich das Bild in der generatecaptcha.php und schreibe den Text in die Sessionvar:

 $_SESSION['captcha_spam'] = $text; 

Die generatecaptcha.php ist nun fertig, zurück zur index.html.
Hier verweisen wir im form-Tag auf die checkcaptcha.php.
Diese erstellen wir nun:
Da wir in der HTML-Datei die Daten per POST übergeben und der Name des Feldes captcha_solve lautet, holen wir die wie folgt aus dem HTTP-Paket:

 $_POST['captcha_solve'] 

Die Sessionvar holen wir, wie oben beschrieben, per

 $_SESSION['captcha_spam'] 

Sollten der Text in der $_POST-Var und der in der $_SESSION-Var identisch sein, so hat der User den richtigen CAPTCHA-Text eingegeben:

session_start();
if($_SESSION['captcha_spam'] == $_POST['captcha_solve']){
	echo 'RIGHT';
        //TODO HERE
}else{
	echo 'WRONG';
       //FALSCHER CAPTCHA EINGEBEN
}

Jetzt nochmal zu der vorhin genannten ID des Image-Tags.
Will man jetzt noch, dass das CAPTCHA erneuerbar ist, falls es nicht lesbar sein sollte, so sollte dieser Code genügen. Er erneuert das Bild und gibt es aus (ein simpler refresh):

 <img style="cursor: pointer;" onclick="document.getElementById(&quot;captcha&quot;).src = &quot;generatecaptcha.php?r=&quot;+Math.random();" alt="" src="refresh.png" />

Das Math.Random() war nötig, da der Internet Explorer nur Links aufruft/aktualisert, welche sich ändern.

[PHP] Erstellen eines CAPTCHA Bildes

Um Spam zu vermeiden, gibt es viele Möglichkeiten.
Eine der bekanntesten ist das Captcha Bild, in welchem ein Text zu finden ist. Diesen muss man dann einfach in ein Textfeld eintragen.
Aber wie erstellt man ein einfaches Captcha Bild? PHP bietet dafür einige Funktionen, die sogenannten Image-Funktionen.

Als erstes braucht man für ein Bild natürlich eine Größe, bestehend aus der vertikalen Höhe und horizontalen Breite des Bilds:

$width = 150;
$height = 60; 

Da ein Captcha eher in die Breite als in die Höhe geht, wird das Bild natürlich breiter als hoch.

Nun müssen wir erstmal ein (leeres) Bild erstellen, bzw. den Speicher dafür bereitstellen.
Dazu bietet PHP die Funktion:

 $image = imagecreatetruecolor ($width, $height);
$colorbg = imagecolorallocate ( $image, 243, 243, 243 );

Diese nimmt die Höhe und Breite des Bildes als Parameter.
Danach setzen wir die Hintergrundfarbe des Bildes (hier ein Grauton).

Nun zeichnen wir einfach mal einen Text in das bestehende Bild:

$color = imagecolorallocate ( $image, 10, 36, 106 );
imagestring ($image, 5,30, 70, 'This is my text', $color);
//$image = Referenz auf das Bild
//5 (zweiter Parameter) = Der Font
//30 (dritter Parameter) = horizontaler Abstand
//70 (vierter Parameter) = vertikaler Abstand 

Das Ergebnis sieht in etwa so aus:
captcha_mytext_easy

Nun müssen wir es den Bots etwas schwerer machen:
Einen einfach String zu zeichnen und diesen auszugeben ist zwar einfach, aber jedes halbwegs gute AntiCaptcha Programm würde das sofort auslesen können, zumal ständig der gleiche dastehen würde.

Deshalb fügen wir dem Bild noch einige Verzerrungen hinzu.
Lasst uns zuerst mit dem Hintergrund anfangen. Diesen zeichne ich jetzt völlig random Pixel für Pixel.
Dazu durchlaufen wir das Bild einfach Pixel für Pixel (ein Bild ist ja nichts weiter als ein zweidimensionales Pixelarray).
Setzen einen Pixel in einer random ausgewählten Farbe und laufen zum nächstenPixel

 for($y = 1; $y <= $height; $y++) {
    for($x= 1; $x <= $width; $x++) {
        $r = mt_rand(0,255);
        $g = mt_rand(0,255);
        $b = mt_rand(0,255);
        $color = imagecolorallocate ($image, $r , $g , $b);
        imagesetpixel($image,$x - 1 , $y - 1, $color);
    }
}

Das Ergebnis könnte dann so aussehen:
captcha_randombg

Nun machen wir es nochmals schwerer:
Wir zeichnen einfach noch ein paar Striche durch’s Bild.

 for($ctr = 1; $ctr <= 4; $ctr++){
	imagesetthickness($Image, rand(0,10));
	imageline($image, rand(0,$width),rand(0,$height),rand(0,$width), rand(0,$height),imagecolorallocate ( $image, rand(0,255), rand(0,255), rand(0,255) ));
}

Hier werden 4 Striche gezeichnet, welche irgendwo durch das Bild verlaufen und eine Dicke von 0 – 10 haben.
Die Farbe ist auch wieder random.
Die Funktion dafür lautet:

imageline($image, $startposx, $startposy, $endposx, $endposy , $farbe);

Ergebnis:
captcha_bgstripes

Nun zum wohl wichtigsten Part des Bildes, dem Text:

 function generateRandomString($length) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = "";
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $randomString;
}

Hier generieren wir einen String mit der Länge x (als Parameter).
Dazu erstellen wir solange einen String aus den oben gelisteten chars, bis wir die Länge erreicht haben.
Auch ist es wichtig zu wissen, dass wir einfach auf den einzelnen char im string zugreifen können, da ein string ein Array von chars ist (char[]).
Nun weisen wir diesen Text einer Variable (für die Übersichtlichkeit) und erstellen die Farbe des Strings auf dem Bild:

$text = generateRandomString(5); //Random String mit der Länge 5 erstellen
$color = ImageColorAllocate($image, rand(64,255),  rand(128,255) , rand(128,255)); //Farbe des Strings 

Nun nutzen wir, anders als vorhin, eine andere Funktion, um den Text auf das Bild zu schreiben:

 imagettftext($im, $ttfsize, $angle, $x, $y, $color, $ttf, $text); 

Diese bietet einige Vorteile gegenüber

imagestring ($image, $font, $x , $y , $color);

Zum einen kann man einen Winkel definieren, den Text als schräg stellen, zum anderen kann man einen eigenen Font einbinden.
Der Text wird also noch etwas verzerrter dargstellt, bspw.:
captcha_imagestringttf

Fügt man nun all die Funktionen zusammen, die wir in diesem Post behandelt haben, bekommt man ca. folgenden Code (+ einige Anpassungen).
Das Ergebnis sieht wie folgt aus:
captcha_fullcaptcha
[spoiler title=“Vollständiger Code“]


function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $randomString;
}

$Width = 150;
$Height = 60;

$Image = imagecreatetruecolor ($Width, $Height);
for($Row = 1; $Row <= $Height; $Row++) {
    for($Column = 1; $Column <= $Width; $Column+=rand(0,5)) {
        $Red = mt_rand(0,255);
        $Green = mt_rand(0,255);
        $Blue = mt_rand(0,255);
        $Colour = imagecolorallocate ($Image, $Red , $Green, $Blue);
        imagesetpixel($Image,$Column - 1 , $Row - 1, $Colour);
    }
}
for($ctr = 1; $ctr <= 4; $ctr++){
	imagesetthickness($Image, rand(0,10));
	imageline($Image, rand(0,$Width),rand(0,$Height),rand(0,$Width), rand(0,$Height),imagecolorallocate ( $Image, rand(0,255), rand(0,255), rand(0,255) ));
}
header('Content-type: image/png');
ob_start();
imagepng($Image);
$data = ob_get_clean();
$im = imagecreatefromstring($data); //Erstelltes Bild von oben aus dem Speicher aufrufen
$text = generateRandomString(5);
$color = ImageColorAllocate($im, rand(64,255),  rand(128,255) , rand(128,255)); //Stringfarbe
$ttf = $_SERVER['DOCUMENT_ROOT']."/assets/font/Fluox.TTF"; //Schriftart
$ttfsize = 25; //Schriftgröße
$angle = rand(0,10);
$t_x = rand(5,30);
$t_y = 40;
imagettftext($im, $ttfsize, $angle, $t_x, $t_y, $color, $ttf, $text);
// Ausgabe des Bildes
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);

[/spoiler]

 

Wie man dieses CAPTCHA Bild nun nutzt, steht im nächsten Beitrag.

Cross Site Scripting #2 – Bekannte Beispiele

Um sich die Wirkung und das Ausmaß eines XSS-Angriffs auszumalen, möchte ich einige Beispiele aus den letzten Jahren einbringen:

Im Jahre 2010 verschafften sich Cracker (im Sinne von destruktiven Hackern) Zugang zu verschiedenen Servern der Apache Foundation [1].
Dieser Angriff wurde durch ein Ticket mit manipulierte Webadresse durchgeführt.
Durch dieses Ticket sollte die Cookie-Session des angemeldeten Users gestohlen werden (Session stealing).

Durch diesen und einen zweiten, parallelen Bruteforce-Angriff erlangten die Angreifer dann die Kontrolle über den JIRA-Server, wo sie ungehindert Dateien durchstöbern und herunterladen konnten. Zusätzlich wurden Passworteingaben abgefangen.

Die Folgen waren, dass die Server für einige Stunden offline waren, die Passwörter geändert, die Sicherheitslücken gestopft und der Hauptserver komplett ausgetauscht werden musste.


Im Oktober 2005 wurde ein XSS-Wurm in MySpace entdeckt, welcher innerhalb von 20 Stunden über eine Millionen Profile befiel.

Der Entwickler des Wurms Samy Kamkar, dessen Vorname auf der Bezeichner des Wurms ist, zielte darauf ab, die Freundesliste des Entwicklers zu füllen.
Sobald jemand auf ein „infiziertes“ Profil klickte, lud das JavaScript-Script und addete Samy Kamkars Account zur Friendlist hinzu.
Zudem erschien ein „Status“-Post mit dem Inhalt: „but most of all, Samy is my hero“.

Nachdem MySpace den Wurm entdeckte, schlossen sie die Lücke und verklagten Kamkar.
Der Entwickler wurde zu drei Jahren Computerabstinenz, 90 Tagen gemeinnütziger Arbeit und einer Entschädigung in unbekannter Höhe verurteilt.
Der Wurm ist und bleibt trotzdem der sich am schnellsten verbreitende Wurm in der Computergeschichte.


Cross Site Scripting #1 – Definition und Einführung

Wer einmal Webseiten gebaut hat oder Datenbanken in seine Homepage integrierte, der wird sicher auch über das Thema XSS (Cross Site Scripting) gestolpert sein.
Aber was ist eigentlich XSS?

Definition
Es ist das Ausnutzen einer Sicherheitslücke über diese man Daten andere Nutzer ausspähen oder manipulieren kann.
Das Scripting kommt daher, dass zur Ausnutzung der Lücken meist Scripts genutzt werden, bspw. in Javascript.

Einführung
Erst einmal. Wessen Schuld ist es, wenn XSS nutzbar ist?
Hier liegt die Schuld ganz beim Admin oder Developer der Seite, denn mit relativ einfachen Mitteln kann man es den Hackern und Scriptern (das schließt Scriptkiddies mit ein) ziemlich schwer machen.
Denn eine Eingabe eines Users, sei es über eine Kommentarfunktion oder über die GET/POST-Parameter in PHP müssen gefiltert, d.h. nach unerlaubten Zeichen, Scripts etc. durchsucht werden.
Achtung: Auch wenn man eines der großen CMS nutzt, ist man davor nicht sicher. Deshalb immer auf neue Versionen updaten! Dort werden dann bekannte Sicherheitslücken geschlossen

Arten:
reflective/non-persistend XSS:
Hier wird ein GET-Parameter auf einer Seite manipuliert um Schadcode auszuführen.
Dies funktionert bspw. so:
Wir haben eine Seite mit einer Suchfunktion, welche den eingegebenen Suchbegriff als GET-Parameter weiterverarbeitet.
http://www.xyztestsiteabc123.com?search=Hier ist mein Suchbegriff
Falls die Seite den Suchbegriff irgendwann also wieder ausgibt, würde das auf der Seite so aussehen:

Sie suchten nach: Hier ist mein Suchbegriff

Nun kann man, falls die Eingaben der Suchfunktion nicht gefiltert werden, jeglichen Code eingegeben:

 http://www.xyztestsiteabc123.com?search=<img alt="" src="http://abouchleih.de/spaceinv_code1.png" width="42" height="42" /> 

Das ist noch nicht so schlimm, denn es wird hier „nur“ ein Bild auf eine Seite eingefügt, dennoch sollten solche Eingaben verboten werden, da sie erstens störend wirken und zweitens auch JavaScript so ausgeführt werden kann.

Das Ergebnis würde also beim obigen eingeben so aussehen:

Sie suchten nach:

Allerdings ist diese Methode recht harmlos, da man die User erst auf die manipulierte Seite locken müsste und die Seite auch nicht gespeichert ist.

persistend XSS:
Hier wird im Gegensatz zu oben, der Code in der Website gespeichert und bleibt so sichtbar.
Nutzbar ist dies bei ungefilterten Kommentarfunktionen in einem Gästebuch.
Wird nun ein Kommentar mit Code gepostet, so wird dieser bei jedem Aufruf der Website ausgeführt.

Beispielcode:

Hallo!<script type="“text/javascript“">
alert("Dies ist ein Script, welches zur anschaulichen Darstellung von XSS auf einer Website verwendet wurde. Lies den Artikel für mehr Info ;) ");
</script>

Das Ergebnis könnt ihr beim Klick auf den Button begutachten.

dombasiertes XSS:
Ähnlich dem reflective XSS, nur dass hier die Webanwendung/-site nicht beteiligt ist.
Der Code wird also nur auf dem Clientrechner verarbeitet.

Zu Part 2 hier geht’s hier entlang.