 Okay, guten Morgen! Willkommen bei der Übersetzung für den Vortrag Exploiting PHB7 Unserialized von Yane Livni. Wir sind Waffle und Meoblast und wir sind froh über Feedback auf Twitter mit dem Hashtag C3T. Genau, heute geht es darum, wie man den PAP7 Unserialized Mechanismus ausnutzen kann. Es gibt einen großen Applaus für Yane Livni. Willkommen zu meinem Vortrag, wie man einen alten und neuen Tricks beibringt. Das geht um PAP7 Unserialized und ich muss zuerst etwas vorausschicken. Es geht nicht um PAPCode, sondern um PAP7 Interpreter. Ich bin Yane. Ich arbeite beim Checkpoint. Mein Team befasst sich mit Exploits und Memory Corruption. Zuerst gibt es eine kurze Einführung in PAP und dann in PAP Unserialized Mechanismen. Dann geht es um die Implementierung des Siebel-Systems. Da raus können wir auf einige Bugs und Verwundbarkeiten schließen. Danach geht es um den Alkator in PAP7 und mit diesem Wissen über den Alkator können wir dann sehen, wie wir diese Bugs ausnutzen können und Remote Execution Export schreiben können. Danach haben wir eine Zeit für Fragen. PAP ist die meist genutzte Sprache in Web Anwendung. Es ist eine Serversprache und alle Daten und Informationen, die es in der Welt gibt, liegen irgendwo auf Servern. Es ist natürlich sehr interessant für bestwillige Angreifer, die die Server übernehmen wollen. Wenn ich sage, dass es die meist genutzte Sprache ist, dann meine ich, dass die meist genutzte Version momentan Version 5 ist, aber inzwischen ist die neueste Version PAP7. Darum geht es heute. Es ist also eine der meist genutzten Sprachen heutzutage. Wie steht es mit der Sicherheit von PAP und PAP Anwendung? Jede beliebtere Sprache hat Verwundbarkeiten. Es gibt zum Beispiel SQL, Injection oder Cross-File-Tripping. Das hängt aber von dem Code, ab den du selber schreibst. Es gibt aber auch Memory-Korrupten. Wie kann das in High-Level-Sprachen passieren? Ein Teil von PAP ist im Interpreter selbst implementiert, der in C geschrieben ist. Wenn es darin Bugs gibt, dann kannst du Memory-Korrupten bekommen. Am gefährlichsten ist die Unserialize-Funktion, die in den vergangenen Jahren am häufigsten ausgenutzt wurde. Was ist die Geschichte von Unserialize? Die meisten Verwundbarkeiten kamen aus Object-Injection. Das ist eine logische Ausnutzung. Es hängt davon ab, wie die Anwendung geschrieben ist. Aber es gab auch Memory-Korrupten. Die hängt nicht von der Anwendung ab, sondern nur von der PAP Version. Für Memory-Korrupten gab es einen generischen Exploit von Ionic. Die wurde 2010 beschrieben. Und dieser Exploit hat in allen PAP 5-Versionen funktioniert. Das ist ein sehr altes Problem. Hier ist ein Beispiel aus diesem Jahr. Von dieser Website, die ihr vielleicht kennt. Sie hat die Aufmerksamkeit von einer Firma von Evernight auf sich gezogen. Sie haben sich die API angeschaut und haben diesen Post repräszt gesehen. Sie hat ein interessantes Format. Das ist das Unserialize-Format. Sie kriegt eine Antwort zurück. Der Server verarbeitet dieses Cookie. Da kam also die Unserialize-Vernibility her. So haben sie eine neue Verwundbarkeit gefunden. Sie haben den Backbound-Tier bekommen. Wie ist es mit PHP 7? Es ist eine neue Version der Sprache. Sie haben alles neu implementiert. Sie haben das auf Performance optimiert. Aus diesem Grund funktioniert die Memory-Korruption nicht mehr. Sie sind sehr stark vom Layout des Speichers abhängig. Das ändert nichts mehr. Aber trotzdem gibt es Verwundbarkeiten. Es gibt Abwehrskomplatibilität. Es gab ein ESCVEs. Die Memory-Korruption kann man immer noch finden in Unserialize. Es gibt bisher noch keine Remote-Exploits. Lass uns über Unserialize reden. In Unserialize muss ich zuerst etwas klarstehen. Man sollte die Unserialize sagen, Unserialize ist grammatisch korrekt. Wenn euch das stört, das ist trotzdem das, was ich für den Rest meines Tocks benutzen werde. Aber PHP ist PHP, also können wir weiter machen. Das ist also die Implementierung dieses Algorithmus in PHP. Unserialize nimmt einen Wert und wandelt sie in einen String, um jemanden zu speichern. Unserialize macht genaues Gegenteil. Man hat also einen String in diesem spezifischen Unserialize-Format. Man kann es dann zurückwandeln in einen Wert. Das ist sehr einfach, könnte man meinen. Aber es gab schon viel zu viele Verwundbarkeiten. Wie sieht Unserialization also auch aus? Zum Beispiel haben wir hier dieses Array mit noch einem Array drin. Da gehen wir Schritt für Schritt durch und Unserialize das. Also ein Array mit vier Elementen. Hier unten haben wir diesen String, der so aussieht, wie er das auf der Folie sieht. In PHP ist jedes Array tatsächlich ein Hashtable oder ein Diction. Es ist also ein Key-Value Stone. Aber wenn du ein Array hast, dann sind die Schlüsse implizit. Das heißt, wir serialisieren den ersten Eintrag. Das heißt, 1, 0, und dann serialisieren wir 1 als Key und 1, 7 den Integer als Wert. Dann geht es weiter mit 2S, 5Apple, dann Integer. Dann haben wir ein genestetes Array. Das heißt, es geht wieder weiter mit dem Standard Unserialize-Format, wie ihr das auf der Folie sehen könnt. Als nächstes serialisieren wir ein Klasse oder ein Objekt. Das heißt, wir gehen wieder zurück zu den impliziten Keys. Das heißt, wir haben Integer 0 als impliziten Key und dann haben wir den ... ... dann der Klassenname hat acht Buchstaben. Das heißt, acht Doppelpunkt der Klassenname, dann Doppelpunkt 0. 0 ist die Anzahl der Properties in dem Objekt. Das Objekt ist also leer. Dann haben wir gescheite Klammern. Dann Integer 1 als Key und Integer 7, 3, 3, 1 als Wert. Das ist die Serialisierung. Das ist also relativ simpel und jetzt haben wir das nette Format, das ihr hier kennt. Anserialize ist genau das Gegenteil. Das ist also ein bisschen langweilig, aber ich will euch eine Sache zeigen. PRP unterstützt ein Feature namens Reference. Das heißt, während der Anserialisierung wir eine Referenz angehen können anstatt eines Integers oder eines Strings. Das heißt einfach, das sagt der Interpreter geht zurück und guckt, was wir gerade gepasst haben. Und ich will einen Kopie dieses Wertes oder eine Referenz dieses Wertes. Und um dieses Feature unterstützen zu können, muss während der Anserialization jedes Objekt, das passwert, als mit einer Referenz abgespeichert werden. Jetzt haben wir also eine Referenz, die jeder gepasst wird. Also angenommen, wir ansterialisieren ein Array mit mehreren Elementen. Und jetzt haben wir ein Pointer auf das Element, das wir gerade instanziert haben. Und als nächstes haben wir wieder Key 0, Wert 0. Key ist Interpreter 1, Wert ist 137. Dann haben wir den String Apple als Wert. Und der Viertepointer zeigt auf diesen Wert. Jetzt haben wir ein Internets Array und das Hash Array ist ein Flachers Array. Obwohl wir also ein Array in einem Array haben, ist das Hash Array flach der fünfte Pointerzeit auf dieses Array. Anschließend haben wir Key A, Wert 1. Dann instanzieren wir das STD Objekt und der siebte Pointerzeit auf dieses instanziert Objekt. Und jetzt passiert etwas Interessantes. Jetzt unrealisieren wir einen Wert auf eine Referenz auf dieses Objekt. Was passiert also? Jetzt guckt per Peer nach und schaut, was dieser Wert war. Dieser Wert war eine Referenz auf den Interessant 1, 3, 7. Jetzt ansterialisieren wir diesen Wert und erstellen eine Referenz auf den Wert, den wir gerade ansterialisieren. So unterstützt PRP, also dieses Feature. Und dieses Feature hat in der Vergangenheit viele Bugs hervorgebracht. Denn ihr seht, wir bewahren also Punkte auf, die wir vielleicht noch mal brauchen, vielleicht auch nicht. Und das hat einiges an Verwirrung erzeugt. Wenn euch das ein bisschen zu viel war, dann gibt es ein paar Sachen, die ihr behalten solltet. Zuerst ist es ein kompliziertes Format und da komplizierte Formate führen zum Bugs. Und das werden wir gleich sehen. Wir haben viele Wege, um Allocation zu kontrollieren. Das heißt, wir ansterialisieren Strings, wir ansterialisieren Hashtables und so weiter. Das heißt, wir haben relativ viel Kontrolle als User und wir behalten diese Referenzen. Das heißt, wir behalten Referenzen auf Dinge, die wir in der Vergangenheit entpackt haben. Und falls wir irgendwie ein Objekt magisch entpacken können, dann haben wir noch ein Pointer darauf und dann können wir das exploiten. Sehen wir aus, dass die PRP dann variabend enthält. Das hier ist eine PRP variabend. Entschuldigung, dass wir das haben hier. Es wird nicht so viel PRP Code hier drin geben. Als ein heilerer Sprache haben wir ein paar Features für uns variabend. Wir haben erstmal automatische Speicherverwaltung und wir haben auch Referenzen. Wenn zum Beispiel Y eine Referenz von X ist, das heißt, der Wert von Y ändert, wenn der Wert von X ändert. Und das auch andersrum. Hier ist wie CV in PRP 5 funktioniert. Es gibt hier einen Struct. Es gibt hier etwas auf dem Hebel, der Riff gecountet. Und jedes CV war ein Pointer drauf und um ein CV zu erstellen, mussten wir das zuweisen auf dem Stack. Wir hatten dann einen Riff-Count drin und Zuglisserkennung, damit zwei Variabeln auf den selben Wert hinderenden könnten, mussten wir dann zwei Pointer nach und auf dem selben Wert stockt. In PRP 7 gab es einige, die es ändern wollten. Das ist Less Dereferences, also weniger Dereferenzierung. Sogar wenn wir einen neuen Wert erstellen, sogar für eine kleine Zeit, mussten wir auch Allocation machen, wir wollten weniger davon. Wir wollten nicht CVs nur auf dem Hebel, wir wollten das auch in Stocks und Rays. Und hier ist wie die neue CV System implementiert wird. Hier ist der Stock dafür. Und CVs nur ein Stockt und es hat nur ein Wert und ein Typ. Es gibt kein Riff-Count drin und wir können diesen Stock irgendwo stellen, wo wir wollen. Der Wert kann eine von zwei Sachen sein. Es kann entweder ein einfacher C-Daten-Tub sein, wie Float und PRP unterstützt auch Cs. Und wenn wir komplexe Typen wie Stringes untersuchen wollen, mussten wir das dann auch in Heap machen. Und es wird auch ein Riff-Count haben. Hier ist eine Zahl und hier ist der Wert 1, 3, 3, 7 und der Typ Long. Wir wissen nicht genau, wo das ist und es ist relativ einfach. Um ein Riff-Count zu unterstützen, ist der Stelle von dem CV dafür zuständig. Es gibt aber eine komplexe Sache damit. Wenn es ein einfacher Datentyp ist, ist es einfach. Aber wenn es ein Pointer ist zu einem anderen Stockt, muss dieser Stockt auch ein Riff-Count haben. So wie Garbage Collection funktioniert, muss dann auch den CV darauf ein Riff-Count machen. Hier gesagt, ein String ist ein komplexer Typ und der erste Wert in diesem Typ ist der Riff-Count. Wenn wir also ein String allocieren, dann allocieren wir mehr Daten. Das heißt, wir allocieren genügend Speicher, damit wir den ganzen String variieren können. Und so sieht das im Speicher aus. Wenn wir eine Stringvariable initialisieren, dann haben wir das CV-String. Das ist vom Typ String. Wir initialisieren das auf dem Heap mit der Wert Apple und wir zeigen den CV auf diesem String und dann ist der Riff-Count 1 und das liegt auf dem Heap. Wie können wir die Referenzen verweiten, wie wurde dieses Referenz-Feature implementiert? Diesmal können wir nicht nur ein CV auf einen anderen zeigen lassen, weil sie vielleicht in verschiedenen Scopes sind, der eine könnte in einem Stock sein, der andere auf dem Stock. Das heißt, wir müssen sie irgendwie verweiten. Es gibt eine Lösung in PHP. Sie haben einen anderen Typen implementiert. Der Referenz heißt, es ist leichter zu zeigen, als zu erklären. Ihr habt zum Beispiel diese Variable x mit dem Wert 1, 3, 7. Und jetzt haben wir die Variable y, die eine Referenz auf x ist. Jetzt ist das im Speicher und jetzt initialisieren wir einen neuen Struck auf dem Heap. Das ist die Referenz. Das erste Feld ist der Riff-Count und das zweite ist wieder eine Sieval. Die initialisieren wir so, dass es die Variable x hat. Jetzt ändern wir den Typen von x zu einer Referenz und jetzt können wir y initialisieren und es wird das Gleiche sein. Das wird also eine Referenz auf etwas aus dem Heap sein. Jetzt haben wir den Wert von x auf den Heap verschoben und jetzt haben wir die beiden Sieval, die beide auf den Heap zeigen, so wie zuvor auch. Über Sie was müsst ihr wissen, dass sie für Embeddingen designt wurden. Das heißt, das kann zu einem Wachs führen. Wir wollen weniger Dereferenzierung und weniger Heap aus uns zu haben, aber Referenz zu erstellen ist ein bisschen kompliziert. Das ist kein Feature, das also viel benutzt wird, außer vielleicht den Exploits. Es gibt ja also eine Abwägung zwischen Sieval und Referenz. Sieval sind einfacher und Referenz ist ein bisschen komplizierter. Jetzt wissen wir also über Anserialis und Sieval und jetzt wollen wir mal noch ein paar Bugs schon. Zuerst benutzt einer uninitialisierten Wert. Jeder weiß, wenn ein Pointer initialisiert. Wenn ein Pointer ist einfach auf nahe und fertig. Structs zu initialisieren, das ist ein bisschen komplizierter. Wir müssen sie mit Konstanten initialisieren. Das kann ein bisschen Zeit dauern und Programmierer überspringen das gerne. Man initialisiert seine Structs nicht, wenn man nicht muss. Das ist aber ein Problem. Das kann zu Verwundbarkeiten führen und dafür gibt es hier ein Beispiel. Es gibt hier diese Funktion SPL Object Storage. Das ist die Initialisierung des Objekts SPL Object Storage. Das ist in SPL implementiert. In der ersten Zeile seht ihr, dass zwei Variablen deklariert werden, nämlich Entry und Infos. Sieval, sie sind das vom Typ sieval struct. Sie werden in diesem Code nirgendwo initialisiert. Nach anigen Zeilen kommen wir zu diesem Statement, dass die Funktion PHP war an Serialize-Aufruft. Das ist die C-Implementierung der Anserialize-Funktion. Und der erste Wert ist eine Referenz auf eine nie initialisierte Variable. Und da wird der String gespeichert, den wir anserialisieren wollen. Das nächste ist P. Das zeigt auf dem String, den wir anserialisieren. Das ... Intern kommen wir aber zu dieser Zeile. Sieval, pointer, destroy. Was sagt ... Bitte lösche den, das sieval, das wir referenziert haben. Das ist genau dieser Inf, den wir nie initialisiert haben. Und das sorgt einfach dafür, dass nie ein Wert in dem sieval ist, bevor wir da reinschreiben. Das heißt aber, weil das nicht initialisiert ist, dann ist da einfach Müll aus dem Stack noch drin. Das war CVI 2016 7480. Das nächste Beispiel ist Typeverwirrung. Und wir sehen, dass eine Referenz zu erstellen sehr kompliziert ist. Das ändert den Typen der Sieval. Ich vermute, dass jemand diese Möglichkeit vergessen hat. Und genau das ist passiert. Wir haben das gleiche wieder. Das ist anserialisiert von dem SPL Object Storage. Und in der zweiten Seite seht ihr, dass wir das interne anserialisieren, aufrufen. Und wir konvertieren wieder den String namens P und speichern das Ergebnis in dem Sieval-Eintrag. Zweitens, ein später überprüfen wir den Typen von dem, was wir gerade anserialisiert haben und schauen, dass es wirklich ein Objekt ist. Wenn es kein Objekt ist, dann sagt die Funktion omist und nichts passiert. Aber wenn es ein Objekt ist, dann geht es weiter. Und da anzuleisen wir den nächsten Wert. P ist jetzt fortgeschritten. Und jetzt konvertieren wir den String in P und speichern ihn wieder in Inf. Was passiert aber, wenn Inf eine Referenz ist, dann wird sich der Attac verändern. Jetzt überprüfen wir, dass es tatsächlich ein Objekt ist und alles gut ist. Aber als nächstes anserialisieren wir Inf. Und das ist eine Referenz auf Entry. Als erstes adokieren wir also eine Referenz auf dem Hip und sorgen dafür, dass es ein Entry ist. Dann ändern wir den Typen von Entry und zeigen es auf diese Referenz. Und als letztes ändern wir den Typen der Referenz, nachdem wir es überprüft haben. Das ist ein Bug. Und das war ein Bug, der war nicht exploitable, aber es war trotzdem ein Bug. Das ist der letzte Bug für heute. Das ist User of the Free. Und Structs haben ihre eigenen Regeln, wie sie sich verändern. Manche ändern ihren Ort im Memory, ohne dass sie das mitteilen. Und wenn wir diese pointer weiter verwenden, dann zeigen wir auf Speicher, der nicht mehr grötig ist. So ein dynamisches Struct kann zum Beispiel eine Hashtable sein. Diese Funktion ist eine Funktion, die alle Hashtables verarbeitet werden während der Anserialisierung. In der ersten Zeile deklarieren wir die Variablen und in der nächsten Zeile fügen wir einen neuen Eintrag zu einer Hashtable hinzu. Das erste ist den Hashtable, der erste Argument und das zweite ist der Key. Wir bekommen also Pointer auf diese Siva und dann in der letzten Zeile rufen wir die interne Anserialisfunktion auf und das konvertiert weder den String aus P und speichert sein Wert in der Anserialisierung. Das ist ein Struct, und speichert sein Wert in Data. Das war Data in Zeit. Das letzte hier ist aber der Hasht, den Hasht, über den wir gerade gesprochen haben. Und WarHash verheilt Pointer auf jeden Wert, den wir gepasst haben, also auch Daten. Das wird also in unserem Hasheray gespeichert, aber was passiert, wenn du einen neuen Wert in die Hashtable speicherst, dann wird sie erweitert nünendlich und wachsen man für einen Speicher. So sieht das ein Speicher aus. Erst anserialisen wir ein Objekt. Das hat einige Properties, zum Beispiel 0 und 1. Und jetzt gelingt es uns magisch, einen neuen Wert in die Hashtable einzufügen und jetzt zeigt der Hasch auf den neuen Wert, den wir gerade an Serialize haben, aber die zwei Werte davor sind nicht mehr gut. Das ist relativ schwierig, auszulösen diese Vulnerability, denn wenn ihr euch an das Format erinnert, bevor wir ein Objekt an uns realisieren, dann gibt es einige Properties in einem Objekt und PRP sorgt dafür, dass die Hashtable genug Platz hat, um all diese Properties zu fassen. Es gibt zwei Wege, wie man diese Vulnerability triggern kann. Das erste ist die Wakeup Funktion, dass eine Funktion die Objekte definieren können und diese Methode wird aufgerufen nach den, was Objekt anserialisiert wurde. Wenn aus irgendeinem Grund die Funktion ein neues Objekt beklariert, wenn wir eine neue Property einfügen, dann können wir diese Verwundbarkeit auslösen. Und es gibt auch noch die Date-Interval-Klasse, die ein sehr interessantes Verhalten hat. Erst wenn wir die Properties dieses Objektes aufrufen, dann werden sie definiert und zu der Hashtable hinzugefügt. Das heißt, wenn wir etwas kommen wie Two-String oder Wakeup, das manches an triggert, dann können wir auch damit diese Verwundbarkeit triggern. Und das war es hier wie 2016, 7, 4, 7, 9. Diese Bugs sind kompliziert. Es gibt immer noch an Serialize-Verwundbarkeiten. Und sogar in der Zwischenzeit, seit ich diesen Talk vorbereitet habe, wurde schon wieder eine veröffentlicht. Das SIVA-System ist ein bisschen anders, aber es gibt andere Korruption. Und es lässt uns befreite Werte nutzen. Und das ist eine Eigenschaft, die wir brauchen, um diese Vulnerabilities auszunutzen. Wir werden gerade über den Alakator reden. Wenn man einen Exploit auf Speicherkorruption macht, kann man wissen, wie den Alakator funktioniert und wie der Speicher aussieht. Im PRP5 hatten wir den vorherigen Alakator. Das war hip-basiert. Jedes Slot, was die Alakashund-Einheit ist, es hatte eine Größe und die Flags für jede Alakashund. Und das war einfach zu exportieren. Aber jetzt haben wir die neuen. Es wurde komplett neu geschrieben. Nichts ist ähnlich wie der Alte. Es ist eine Bind- oder Speicherpulse. Und das hier ist die Basis, wie er darauf gebaut ist. Es arbeitet in Chunks von zwei Megabytes vom Betriebssystem. Und die sind in Pages geteilt. Die erste Page beschreibt den Chunk. Es beschreibt, welche Pages frei sind und es hat Pointers zu den Binds, die initialisiert worden sind. Die erste Bind ist eine freie Liste mit einer Größe. Und es kann über mehrere Pages gesetzt werden. Wir haben hier einen Chunk. Das ist geteilt über mehrere Pages. Die erste Page hat die freie Slots und die Pointers zu den Fühlen. Und hier ist die sechste Bind über mehrere Pages. Und jeder hat ein Pointer zu dem Nächsten. Wir haben die Page-Infomation, die dann... Sobald wir ein... Wenn wir einen Slot von der Größe 13 alukieren werden, dann schauen wir, ob der Bind passt und anschließend schauen wir, ob es eine freie Liste gibt, ob der Bind schon initialisiert ist. Wenn noch es noch keine initialisierten Bind gibt, dann mach'n die initialisieren wir eben ein. Und pop'n dann aus der... einen Alltag auf der Liste. Wir wollen also zum Beispiel 30 bytes initialisieren. Es gibt noch keinen 30 byte-Bind, dann initialisieren wir einen neuen. Wenn wir eine... Wir pop'n einfach von der Freelist. Wir bekommen zum Beispiel einen Pointer und wollen ihn zurück in den Pool befreien und schauen, aus welchem Chunk der kommt. Wir lesen den Chunk Descripten, um zu sehen, aus welcher Freelist er kommt und schieben ihn zurück in die Freelist angenommen. Wir wollen den ersten Slot dieses Binds befreien. Dann sehen wir, kommt die nette dritte Seite. Die dritte Seite ist Bind 32. Und wir gehen zu der Freelist und schieben ihn zurück. Über die Allocator sollt ihr... euch merken, dass... Über den Allocator sollt ihr merken, dass er sehr freisagbar ist, was wichtig ist. Es ist nicht möglich, einfach irgendwelche Pointer zu befreien. Das wurde früher ausgenutzt, aber das geht heute nicht mehr. Denn wir können Speicher nicht mehr so manipulieren, dass er richtig aussieht, damit die Analyse funktioniert. Und wenn wir die Freelist ändern können und dann freie Slots allokieren können, dann können wir auf den Ort allokieren, den wir haben wollen, aber das erkläre ich euch später. Jetzt haben wir also Vulnerabilities und wir wissen, wie der Allocator funktioniert. Jetzt müssen wir anfangen, ein Export zu schreiben. Jeder Export hat mehrere Schritte. Der erste ist ein League. Das heißt, wir wollen ein bisschen Speicherinformationen durchsignal lassen. Anschließend wollen wir Speicher diesen, damit wir Daten lesen können. Wir würden auch gerne schreiben können, zum Beispiel Code oder andere Sachen, und wir würden gerne Code ausführen können. Dafür sind wir hier. Der schwierigste Teil zuerst ist der League. Dafür werden wir den Allocator ausnutzen. Er basiert ungefähr auf der vorherigen Technik und wir werden befreite Objekte serialisieren. So haben wir angefangen. Wenn wir irgendwas anzuerrealisieren, dann wurde es wahrscheinlich vorher geserialisiert. Das heißt, wir haben irgendein Mechanismus, das wir etwas serialisieren, dann wieder anzuerrealisieren und so weiter. Der Allocator, wenn ihr euch erinnert, ist eine Freelist. Das heißt, der Allocator wird freie Slots überschreiben und zum Schluss können wir Daten lesen, die auch befreit wurden. So wird es also funktionieren. Der Allocator ist eine Freelist und der erste ist ein Pointer auf dem nächsten Slot. Das erste Feld hier ist ein Pointer. Wenn wir befreite Objekte lesen, dann können wir manchmal über diesen Pointer lesen. Wir haben den Pointer befreit und können den nächsten Pointer lesen. Hier ist meine absolute Lieblingsklasse in PHP. Das ist die DateInterval-Klasse. So wird das Speicher implementiert und das erste Feld ist ein Pointer. So ein Glück, das zeigt auf dieses Struct und dieses Struct ist ein sehr einfach Struct. Das hat viele Fäder, aber alle davon sind Integer. Fast alle. Einer ist Sainte-Long-Long. Wenn wir diese Klasse lesen, dann bekommen wir also den Tag, das Jahr und so weiter. Wie bekommen wir also etwas dazu durchzusickeln? Als erstes werden wir das Objekt allokieren und anschließend werden und ein weiteres Objekt mit einem String und anschließend werden wir beide befreien. Und der Allocator wird, es überschreibt, mit einem String. Wenn wir dieses DateInterval serialisieren, dann kommen wir zu etwas. Aber zuerst hier ein Hexdom. Hier allokieren wir ein DateInterval und wie ihr sehen könnt, zeigt es auf ein Struct. Und wir allokieren auch, oder anzerialisieren auch ein String, nach dem anderen. Und jetzt befreien wir beide. Und wie ihr sehen könnt, zeigt der... nun auf den befreiten String. Und wenn wir das serialisieren, dann bekommen wir tatsächlich die Werte in diesem String. Also wir bekommen diese Pointer als Integer, was sehr nett ist. Wie können wir den Speicher lesen? Wir haben schon dieses sehr nette Struct, wenn wir das, also komplett kontrollieren können. Und könnten wir es einfach, können wir den Pointer auf alles Liebige ändern. Das heißt, wenn wir es auf ein DateInterval ändern, dann können wir jeden Speicher lesen, den wir haben wollen. Wenn wir den Sieber nicht kontrollieren, was auch der Fall sein kann, dann gibt es einen etwas komplizierteren Weg, den ich hier nicht diskutieren möchte. Aber wir können ein anderes Objekt verwenden, das DatePeriod-Objekt, das in erstes Fall ein Pointer ist, das auf ein anderes Struct zeigt und das kontrolliert einen anderen Pointer. Wir können also Speicher mit SPL-Copy lesen und ihr könnt alle Details in dem Paper lesen, das ich ja früher in diesem Jahr veröffentlicht habe. Wie können wir Speicher lesen? Wir können Speicher schreiben, das ist deutlich komplizierter. Wir werden ein paar Strings befreien und hier diese Strings können Pointer einhalten. Anschließend werden wir die Freelist ausnutzen. Wir werden die inkrementieren oder die dekumentieren und wenn wir sie irgendwann weit genug inkrementiert haben, dann werden sie auch den Speicher zeigen, den wir schreiben möchten. Dann gibt uns der Allocator die Adresse, auf die wir schreiben möchten. Das ist das, was wir haben wollen. Wie können wir diese Strings befreien? Jeden Wert, den wir an Strings pausen, der bekommt eine Referenz. Während der Ansehrelesierung ist nicht befreit. Es gibt nur eine Ausnahme. In der Hashtable können wir den gleichen Key zweimal benutzen. Darum werden keine Referenzen behalten. Wenn wir an der Hashtable ein Strings verwenden, dann sagt der Hashtable und befreit ihn. Wie können wir es in der Freelist-Pointer ausnutzen? Der Grund dafür, dass das möglich ist und sehr häufig verwendet wird, ist Type Confusion. Wir haben die Freelist-Pointer. Wir haben die Freelist-Pointer. Wir haben die Freelist-Pointer. Wir haben auch den Referenzsillausgleich. Auf dem Hip hat ein Referenzcount und der ist immer das erste Feld. Das ist das, was wir es nehmen. Wir haben das erste Felddesign. Das ist das, was wir haben. wenn ein Objekt befreit wurde und wir es immer noch benutzen können, dann wird tatsächlich ein Pointer inkrementiert oder dekommentiert, dass es Teil des Exploits, den ich für einen Backgeschrieben habe. Und hier seht ihr, dass wir schon eine Stringsprick zum Allocator befreit haben. Und jetzt werden wir die Vulnerability auslösen. Die liegt in dem ArrayObjekt, in der ArrayObjektChesson. Und wenn wir es pausen, dann inkrementiert es den Pointer. Der Pointer der Freelist ist immer noch im Allocator, aber wir haben noch eine Referenz auf ihn. Es war der elfte Wert, den wir gepasst haben, für Referenzen hinzufügen. Dann inkrementieren wir diesen Pointer jedes Mal um zwei. Und irgendwann kommen wir zu dem Wert, den wir gerade befreit haben. Wenn wir jetzt zweimal aus dem Bin allokieren, dann allokieren wir jetzt beim ersten Mal, das CODExecution ist relativ einfach. Wenn wir die Siva kontrollieren können, dann können wir einfach ein Objekt kontrollieren und beschließen, welche Callbacks es hat. Wenn wir das nicht machen können, dann können wir aber primitiven schreiben und wir können den Funktionen Pointer schreiben und das ist alles. Was nehmen wir von diesem exploit mit? Der Allocator ist euer Freund, benutzt ihn, aber benutzt ihn weise. Und diese Primitiven sind wiederverwendbar. Wenn wir all diese Primitiven kombinieren, dann kommen wir rumored CODExecution. Selbst wenn wir, wenn ja euer Code in einem Code in einem Code ist, dann habt ihr trotzdem low-level Probleme. Das neue Design von PHP ist für Effizienz. Es gibt immer noch Vulnerabilities. Ich glaube nicht, dass es sicherer oder weniger sicher ist, sansläufig. Der Allocator ist freundlich zu Leuten, die ihn ausnutzen wollen und nie, nie, nie benutzt an serialize. Und das ist das, was wir jetzt machen. Der Allocator ist freundlich zu Leuten, die ihn ausnutzen wollen und nie, nie, nie benutzt an serialize. Diese Funktion ist eigentlich einfach nur remote CODExecution. Jedes Mal mit dem Code auftaucht, wurde sie ausgenutzt. Mehr Informationen findet ihr im Checkpoint-Blog und in dem Paper, das ich gerade veröffentlicht habe. Und das wird beide eine weitere Veröffentlichung geben über die Verbundbarkeiten, die ich gefunden habe und mehr Informationen. Und die dritte Verbundbarkeit, die ich jeden Titel geführt habe, PHP-Bug-System ist der zweite Link. Da findet ihr jeden Bug, der jeder gefunden hat und nicht andere davon haben, CVEs. Und das dritte ist Nikita Popova. Blog, er ist einer der Hauptcontributors zu PHP. Wenn ihr mich kontaktieren wollt, habt ihr meine Geschäftsadresse, mein Twitter. Und ihr werdet mich auch auf verschiedenen anderen Plattformen, Twitter, Gmail, Couchsurfing. Ja, das war's. Dann gibt es Fragen. Jetzt sind die Fragen gegen deine Frage von hier oder vom Internet. Ich werde mit einer Frage anfangen. Erwarten wir das, so wirklich zu sehen, im produktiven Kurs? PHP 7 ist relativ neu, aber sobald die Plattformen wechseln zu PHP 7, werden wir das sehen. Wir können warten, dass wir mehr in nächster Zeit sehen. Das Internet hat eine Frage. Ist es irgendeine beliebte Produkte, die von diesem exploit betroffen sind? Nicht, was ich weiß, weil PHP 7 bis jetzt nicht in großer Verwendung ist.