 um Feedback auf Twitter unter dem Hashtag C3T und ihr könnt auch an C3Translate tweeten oder uns e-mailen an hello at C3lingo.org. Ja jetzt sind wir von Omega Select Code Execution from Star using SQLite. Willkommen zu meinem Vortrag, wo wir Code Execution mit Swissfielding SQLite Datenbanken kriegen. Ich bin Umagul aus Tel Aviv, forsche an vulnerabilities. Ich habe die letzten drei Jahre Checkpoint Research betrieben und bin jetzt vor kurzem in Startup Hunters AI übergegangen. Unsere Agenda, ich rede über die Motivation und Hintergrund-Story, gebe eine kurze SQLite Intro. Wir werden über die Attackenobüfte hier einer boshaften Datenbank reden, über vorherige Arbeitreden und denken dann darüber nach, wie wir Memory Corruptions nutzen können mit reim SQL, sprechen dann über query orientiertes Programmieren, also Crop, ich demonstriere ein bisschen und werde schließen mit zukünftigen Arbeiten und einer Zusammenfassung. Die Motivation ist relativ offensichtlich. SQLite ist eine der meist deploiten Softwares in dieser Welt. Du seht dir in PHP 5, 7, Android, iOS, Windows 10, Firefox und Chrome. Und die Liste kann man unendlich lange fortführen. Und eine SQLite Datenbank befragen, es fühlt sich safe an, aber am Ende des Vortrages wisst ihr hoffentlich, ne, das nicht so. Das fing an damit, dass Menschen versucht haben, Passworte zu stehlen. Es gibt viele davon in der Welt, die Story ist immer ungefähr dieselbe. Ein Computer wird infiziert, irgendeine malware sammelt sich die gespeicherten Credentials von den verschiedenen Clients, irgendeine Clientssoftware speichert dieses Secrets in der SQLite Datenbank und die malware schickt das zu ihrem Commodate Control Server und der extrahiert die Geheimnisse heraus und speichert sie in seinem Loot. Omri und ich, ein Kollege von mir, haben uns dann die gelegten Quellen von solchen Passwortstehlein angesehen und diese Leute ernten einfach ein paar unserer Datenbanken und lesen sie aus in ihrem Backend. Und können wir diesen Load and Query von einer nicht vertrauenswürdigen Datenbank zu unserer Vorteil benutzen. Das könnte viel größere Implikationen in verschiedenen Szenarien haben, weil SQLite so beliebt ist. Und das hat uns die längste Capture the Flag Challenge meines Lebens bislang eingebracht. Die meisten anderen SQL Datenbanken haben eine kleinen Server-Architektur, bei SQLite ist das nicht so. SQLite schreibt und liest direkt Daten, Dateien. Eine vollständige Datenbank mit verschiedenen Tabellen, Indizes, Trigern, Views ist innerhalb von dieser einen Datei enthalten. Lassen Sie uns also auf die Angriffsoberfläche schauen. Diesen Schnipselcode aus einem sehr bekannten Passwortstealer. Da sehen wir erst mal SQLite oben, wo die potenzielle, böswürdige Datenbank geladen wird. Dann sehen wir den eigentlichen Query, das Select Statement. Wir haben keine Kontrolle über dieses Statement, es ist ja immerhin hartgecoded. Aber wir kontrollieren vielleicht den Inhalt, also wir können vielleicht sehen, was da geht. Der erste Punkt, das SQLite Open. Das ist viel Setup und Konfigurationscode und dann haben wir ziemlich grad lindiges Header-Parsing. Der Header ist etwa 100 bytes lang, also nicht so lang. Und das wurde schon ausgiebig befasst von dem Tool AFL, das ist also kein vielversprechender Zahl für uns. Der SQLite Query könnte schon viel interessanter sein, um es mit den Worten des SQLite Authors zu sagen. Das Select Statement ist das schwierigste Command in der Sprache SQL. Hinter SQLite sitzt eine Virtual Machine. Das heißt, jeder Query muss kompliziert werden in ByteCode. Das ist auch bekannt als der Vorbereitungsstep, Preparation Step. Das heißt, SQLite Prepare macht genau das, läuft und expandiert den Query. Zum Beispiel wird so ein Stern zu allen validen Spalten-Namen umgeschrieben. SQLite Locate Table verifiziert, dass alle relevanten Objekte tatsächlich existieren und sucht nach ihnen im Spracher. Jeder SQLite Datenbank hat einen SQLite Master Table, in dem das Schema für die Datenbank hinterlegt ist. Das ist die Struktur für so ein SQLite Master Table. Da haben wir halt den Type der Table, oder ob es ein View ist, der Name, und ganz unten seht ihr, ich spalte SQL. SQL ist dann die Data Definition Language, die dieses Objekt beschreibt. Ddl steht für Data Definition Language. Ddl-Commands sind ungefähr sowas wie header files in C. Sie definieren Struktur, Namen und Typen innerhalb der Datenbank und stehen im Klartext innerhalb der Datei. Wir sehen uns hier ein Beispiel an. Wir öffnen den SQLite Interpreter, erzeugen eine Tabelle, tun Werte rein, beenden den Editor und sehen uns einen Bytecode an und sehen unmittelbar das Create Table Statement, was Teil des SQLite Master Schemas ist und sehen auch die Werte. Lass uns also zurückgehen zu der Query Vorbereitung. SQLite Locate Table versucht die Struktur, die die Tabelle hat, die wir Queryn wollen zu finden. Also liest das Schema, was es in SQLite Master findet. Wenn es das zum ersten Mal tut, wird es eine Callback Funktion haben für jedes solche Ddl Statement. Dieser Callback validiert das Data Definition Language und baut die interne Datenstruktur dieses Objekts auf. Also haben wir darüber nachgedacht, Ddl-Patching zu betreiben. Was wenn wir den Query innerhalb der Data Definition Language verändern? Das hier ist der Callback von dem ich gerade geredet habe. Der wird erst verifiziert mit Create Space und nur dann wird präpariert. Das ist eine ziemliche Einschränkung. Es muss anfangen mit Create und der Strich. Aber es hinterlässt uns noch ein bisschen Raum für Flexibilität. Wenn wir uns die SQLite Dokumentationen aber ansehen, können wir Create, Index, Table, Trigger, View, Virtual Table machen. Etwas, was wir noch nicht wirklich verstehen. Dann haben wir also darüber nachgedacht über Create View. Das ist sozusagen ein vorverpacktes Select Statement. Views können genauso an Create werden wie Tabellen. Also ist Select Call A from my Table etwa dasselbe wie eine Sparte aus diesem View Selekt. Dann können wir über Query Highjacking nachdenken. Wir werden also die SQLite-Masse, Ddl mit Views statt mit Tables patchen. Und diese patched Views können jedes Select haben, was wir haben wollen. Und mit diesem Select Subquery können wir mit dem SQLite Interpreter interagieren. Das ist ein großer Schritt vorwärts. Also haben wir einen Verlierung kontrollierbaren Query zu etwas gemacht, wo wir jetzt Kontrolle ausüben können. Etwa hier ist Beispiel, da haben wir die originale Datenbank und die hat eine Tabelle mit zwei Spalten. Dummy, Call A und Call B. Und dann würde die Software, die wir targetten wollen, es vielleicht versuchen anzufragen mit Select Call A, Call B von Dummy. Und dieser View kann das Highjacking. Wir machen einen View, der den selben Namen hat wie diese Tabelle, auch mit den selben Tabellen. Aber dahinter kann hier stehen Select 2 Subquery Spalten. Hier wäre ein praktisches Beispiel dafür. Wir createn ein View mit Dummy, mit Call A und Call B. Wir benutzen die SQLite Version Function. Das ist so eine Build-Infunction von SQLite, die können wir benutzen. Und das zweite benutzt die SQLite eigene Implementation von Print F. Das ist eine der wirklich überraschenden Features und Fähigkeiten von SQLite. Wenn wir uns das jetzt von der Targetseite ansehen, dann versucht jemand aus Dummy zu query'n und selectet aber hiermit diese Funktionen, die wir dort initiiert haben. Das ist ein großer Schritt vorwärts. Wir haben etwas Kontrolle über diesen query bekommen. Was können wir jetzt mit dieser Kontrolle machen? Hat SQLite irgendwelche Systemkommandos? Können wir damit lesen und schreiben auf irgendwelche anderen Files? Das war ein guter Punkt, um auf vorangegangene Arbeiten zu sammeln. Wir waren offensichtlich nicht die ersten, die auf die Idee gekommen sind, SQLite so auszubeuten, mit dem hohen Potenzial. Denken wir bei SQL Injections nach, das Szenarios etwa dasselbe. Irgendjemand mit bosshafter Absicht hat Kontrolle über einen SQL query. Es gibt ein paar bekannte SQL Injection Tricks in SQLite. Wir erzeugen eine Tabelle und setzen ein paar Strings rein. Hier in der Datenbank ist einfach nur eine Datei. Das ist so etwas ähnliches wie ein beliebiger Datei zu schreiben. Wir können aber nicht anhängen, denn DDL muss anfangen mit Create. Ein anderer bekannter Trick ist die LotExension Funktion. In diesem Fall also etwa eine RemoteDLL und auch diese Funktionen, aber typischerweise deaktiviert per Default. Wie sieht es aus mit Memory Corruptions in SQLite? SQLite ist ziemlich kompliziert und geschrieben in C. Es gibt den schönen Blockpost Finding Bucks in SQLite Easyway, also Bucks finden in SQLite auf die einfache Art und Weise und finden 22 Bucks in 30 Minuten Fuzzing. Seit dem, also Version 3.18 in 2015, haben SQLite angefangen AFL als integralen Teil ihrer Testsuite zu benutzen. Und diese Memory Corruptions ließen sich wirklich nicht gut ausbeuten ohne eine bequeme Umgebung. Und die Security Research Umgebung fand das perfekte Ziel, nämlich WebSQL. WebSQL ist eine WebAPI, mit der man Daten in der Data-Datenbank gespeichern kann. Man kann es von JavaScript callen, es besitzt einen SQLite backend und hier und es ist vorhanden ein Chrome und Safari. Hier sehen wir ein ganz einfaches Beispiel, wo man eine Datenmark öffnet und eine Transaktion öffnet und WebSQL ausführt. Anders gesagt, was wir haben hier ist ein unvertrauten Zugriff auf eine SQL-Datenbank. Dieses erreichbar von jeder Webseite, insbesondere von ein paar sehr beliebten Browsern und diese Bucks können jetzt mit der sehr schönen Umgebung von JavaScript Interpretern ausgenutzt werden. Es gab sehr viele beeindruckende Forschungsergebnisse, die in der letzten Zeit gepublished wurden. Zum Beispiel sehr einfach Sachen wie das Ergebnis CVE 2014 7036, wo eine unverträuliche Pointer die Referenzierung ausgenutzt wurde und eine etwas kompliziertere von Blackhead in 2017, wo die FTS Optimizer Funktion ausgenutzt wurde und der Magellan hat Bucks gefunden, wo er Integer Overflows in Secrenaxt ausgenutzt hat. Und wenn ihr euch ein bisschen das ankommt, dann seht ihr ein sehr interessantes Pattern, denn alle diese Funktionen, die ausgenutzt wurden, starten mit FTS und da frage ich mich, FTS, was soll das bedeuten und ich habe ge-googelt und war noch mehr verwirrt. Nach ein bisschen Überlegen habe ich endlich festgestellt, dass FTS steht für Full Text Search, Full Text Suche steht. Und zwar gibt es virtuelle Tabellen und was es erlaubt, dass man Text Suchen auf Dokumenten macht oder wie die SQL-Authornes bezeichnen, ist wie Google auf Datenbanken. Das gibt ziemlich viele coole Funktionen, die man dafür beschwkommt, zum Beispiel Artree, das macht geografisches Indexing oder virtuelle Table CSV, die erst an einer möglichen Datenbank wie ein CSV-Dokument zu behandeln. Und diese virtuellen Tabellen werden genauso wie normale Tables gecarried, aber hinter dem Vorhang passieren sehr viele Magischittinge, zum Beispiel die Curries, die gekollt werden, arbeiten auf sogeilten Shadow Tables, Schattentabellen. Und stellen wir uns vor, ich würde jetzt so eine virtuelle Tabelle erzeugen mit Create Virtual Table. Und jetzt inserte ich in diese Tabelle ein String. Und jetzt für eine sehr effiziente Suche brauche ich etwas Metadaten, also Tokens oder Metadaten und das Allestext. Das heißt, diese eine virtuelle Tabelle funktioniert, wird verteilt auf drei Shadow Tables. Und zwar, die Metadaten kommen auf VD-Segments und der Content in 4D Content. Und diese Shadow Tables haben Interfaces zueinander, wo Daten in und her transportiert werden. Das heißt, es gibt Pointers in den einzelnen, die zwischen denen auch übertragen werden müssen. Und diese Interfaces sind sehr basierend darauf, dass man sehr viel Trust zwischen den einzelnen Tabellen hat. Das heißt, das ist natürlich ein gefundenes Fressen, um Fehler zu finden. Und ich möchte euch gerne zeigen, was ich in dem Artree Virtual Tabellemodul gefunden habe. Das ist ein Feature, was in MacOS und Windows 10 verfügbar ist, insbesondere auch in Windows 10. Es macht sehr smartes geografisches Index inizieren. Die DDL sieht wie folgend aus. Und jede virtuelle Tabelle muss mit ID anfangen. Und dann gibt es X und Y Koordinaten. Das heißt, jedes Artree Interface erwartet, dass ID ein Integer ist. Aber ich kann ja jetzt auch eine virtuelle Tabelle anlegen, die kein, die nicht ID in der ganzen String oder sowas bekommt, in dem ersten Fall. Und wenn wir das machen, dann bekommen wir einen Crash, nämlich einen Out of Bound Crash auf dem Heap. Und das ist ein Crash in diesem Beispiel, der auf Windows 10 passiert ist. Und das ist ziemlich gut. Denn jetzt haben wir festgestellt, okay, diese virtuelle Tabelle haben Bugs. Und wir können mit dieser Curry High Jacking Technik, können wir diese Bugs triggern auf unserem Ziel. Und das heißt, wir sorgen dafür, dass auf diesem Target ein Segmentation Fault, ein zu groß Fehler passiert. Und um das, aber jetzt um weiter arbeiten zu können, brauchen wir eine Form von Skripten. Aber wir haben kein JavaScript zum Beispiel. Das heißt, wir haben keine Logic Statements wie IF oder oder Schleifen, Loops. Aber wir haben doch schon mal irgendwie gehört, dass SQL Touring komplett ist oder Touring vollständig ist. Das heißt, wir haben ja eine kleine Wishliste zusammengestellt, die wir gerne haben möchten. Hier ist also die Liste von Primitiven, die wir gerne haben wollen. Um einen vollständigen Explorter zu schreiben, können wir mit diesen Memory Corruption Bugs, was brauchen wir dann? Das erste Mal, wir möchten Speicher leiden können. Ein Info-Leid. Und dann möchten wir halt auch den wirklich gewöhnlichen Task 64-Bits Zeiger zerlegen. Ja, doch, bearbeiten können. Zeiger Arithmetic betreiben können. Und dann suchen wir uns dann die Basis von Lib SQLite und nachlesen und manipulieren von Zeigern, wo wir sie natürlich auch wieder verpacken und dann mit denen beschreiben können. Und natürlich ist auch ein einzelner Zeiger nicht alles, was wir wollen. Wir wollen eigentlich auch gefakte Objekte im Speicher bauen können. Und wir möchten einen Heapspray betreiben können. Und kann all das getan werden nur mit SQL? Ja schon. Und stolz präsentiere ich euch Query orientiertes Programmieren. Und das zu Demenz sehen, schauen wir uns den nicht gefixten CVE 2015-7036 an. Da könntet ihr euch jetzt fragen, wie kann es sein, dass ein vier Jahre alter Bug immer noch nicht gefix ist? Das ist ein ziemlich guter Punkt für unser Argument. Der wurde nur als gefährlich im Kontext von nicht vertrauenswürdigen Web SQL. Also Gebläckliste zu lange nicht kompliziert wurde mit Enable FTS Token asa. Was wird damit compiled? Das sind PHP5, PHP7, iOS, MacOS und wahrscheinlich noch so viele andere Targets, für die wir einfach nur keine Zeit hatten, sie uns anzusehen. Schauen wir uns also diese Verwundbarkeit mal genauer an. Ein Token asa ist ein Satzregeln, um Terme aus einem Dokument oder aus einem Query rausziehen. Der grundlegende Token asa einfach zerlegt Strings einfach an den annualspaces. Aber man kann auch Custin Token asa schreiben. Etwa auch C Funktionen da reinpasen in den FTS3 Token asa im SQL Query. Man kann also einen Rundzeiger in eine C Funktion in einem SQL Query einpacken. Ich verstehe an diesem Punkt nach wie vor nicht, wie man das aussah für Exploits benutzen kann. FTS Token asa ist tatsächlich eine überladende Funktion. Wenn man es mit einem Argument nutzt, kriegt man die Adresse dieses Token asas, um das ein bisschen menschenlesbarer zu machen. Etwas menschenlesbarer. Benutzen wir den Hexty Coder und kriegen damit einen InfoLeak von LibEsculite. Wir müssen es noch umdrehen, aber gut, das ist schon ziemlich gut. Wenn man das jetzt mit zwei Argumenten called, das erste ein Name eines Token asas und das zweite ein Row Pointer, total verrückt, dann können wir jetzt die Adresse dieses Token asas lesen. Wenn jetzt jemand den Virtual Table mit FTS3 versucht zu erzeugen, erzeugen wir einen Segmentation Fault. Fassen wir das noch mal zusammen. Esculite ist also ein wundervoller Einschlussangriff für viele Ziele. In der komplexen Maschine geschrieben in C, mit Query hijacking, können wir diese Bugs auslösen und zielen darauf, volle Exploits zu implementieren mit allen notwendigen Primitiven, nur mit SQL Queries. Das heißt, unser Plan für Exportation ist ein paar Zeiger legen, dann ein paar Funktionsadressen finden, einen Fake Token Asa Objekt mit ein paar Zeigern aufs Zähn erzeugen, den Default Token Asa überschreiben, dabei dann unseren büßwilligen Token Asa auslösen, irgendwas passiert und zuletzt sollten wir irgendwie einen Profi daraus schlagen können, oder? Fangen wir an mit dem Speicherleck. Schon wird es also ein Lib SQLite League an. Da wissen wir schon, wie es geht. Wir haben den FTS Token Asa gesehen. Da gibt es noch das kleine Problem mit dem Little Indian Pointer, den wir umdrehen müssen. Sicherlich können wir auch SQLite Funktionen benutzen, um ihn zwei Items zur Zeit zu lesen und umzudrehen. Die Sündungszeit wäre so, jetzt haben wir den Pointer. Sehr gut. Was ist, wenn wir das jetzt auf den Heap tun wollen? Dafür müssen wir finden, wo der Heap ist. Dazu machen wir etwas Ähnliches wie mit dem Archie Bug, von dem wir geredet haben. Wir benutzen also dieses Virtual Table Interface, legen ein paar Werte darin ab. Jetzt werden wir das Match Interface verwirren. In Memory macht es dann tatsächlich einfach nur den Zeiger finden mit den Metadaten, die es hat. Statt es also zu einem anderen Virtual Table Interface zu geben, geben wir es einfach in den Hex-Decoder, den Raw Pointer und finden damit jetzt die Little Indian Adresse von dem Heap. Fertig, den Punkt in der Liste haben wir. Um diesen Pointer jetzt so entpacken, haben wir ein großes Problem. Ohne Browser Web SQL haben wir halt keine Variablen, keine Arrays. Wir brauchen komplexe Logik. Wir müssen die Funktionsadressen und Dinge irgendwie im Speich erhalten. Auf wie macht man das in SQLite? Naja, wir haben Insert Statements, aber wir können nur Create Table, View, Index oder Trigger. Also haben wir darüber nachgedacht, Views zusammen zu ketten, um sie als Pseudo-Variablen zu benutzen. Schauen wir uns ein Beispiel an. Wir erzeugen einen View Little Indian Leak. Wieder einmal mit dem FDS Tokenizer. Jetzt legen wir noch einen View da oben drüber und nennen ihn Leak und der flippt einfach wieder wie jetzt vorhin gesehen haben, aber mit Referenz auf den Little Indian Leak, was wir am Ende haben, ist eine Pseudo-Variable, die wir Leak nennen und wenn wir davon selekten, kriegen wir genau das erwartete Resultat. Jetzt können wir uns bewegen. Wir können komplizitere Dinge mit dieser Logik bauen und etwa 64 Bit Pointer entpacken. Lassen Sie uns also etwa versuchen, die Basis eines Images zu finden oder den Heap und müssen damit irgendwie unseren Pointer zu einem Integer umwandeln. Also müssen wir damit die Pointer lesen, ein Zeichen zur Zeit. Um in den Wert dieses Hex-Characters zu lesen, benutzen wir NSCR. Dann kriegen wir an den Wert von dem Hex-Character. Dann müssen wir ein bisschen schwarz-möbige Treiben schiften und hängen das alles wieder zusammen. Das Resultat ist dieser Monster-Curry, der ist dann am Ende, aber den Integer genau die entpackte Version dieses Initialen Leaks gibt. Jetzt haben wir ihn also entpackt und haben meinen Integer fertig. Wir können Pointer jetzt also zur Integer machen. Jetzt zur Zeiger-Retmetik. Wir haben die Adressen von ein paar Funktionen im Memory im Speicher. Mit Integern in der Hand wissen wir jetzt aber wie Zeiger-Retmetik geht. Das ist einfach. Wir schauen uns also an, wo das entpackte Leck ist und können jetzt einfach eine Konstante davon abziehen oder irgendeine Pseudo-Variable abziehen, um es dynamischer zu machen oder verlässt euch ja. Und finden dann die Flip-Esculite Base in Integer Form. Das wäre jetzt also eine gute Gelegenheit, diese Pointer auch wieder irgendwo hinzu an die Orte dieser Pointer was zu schreiben. Das funktioniert für relativ viele Werte gut, aber für größere Integers werden das 2-byte Compoints das für uns ein großes Hindernis. Nachdem wir uns sehr lange mit der Dokumentation gesetzt haben, haben wir auf einmal ein Großartigen Einfall gehabt. Ah, okay, aber halt mal, unser Explorer ist eigentlich eine Tatenbank. Aber wenn wir irgendeine Konvertierung machen wollen, können wir einfach vorher diesen Key-Value-Table anlegen. Und wenn wir einen Wert haben wollen, können wir einfach einen Query machen und unsere vorher erzeugte Key-Value-Table verwenden. Hier haben wir so eine, diese Funktion und die ist sehr einfach. Sie geht einfach über alle Values und insertet dann diese Conversion-Pare in die Tabelle ein. Lassen uns ein Beispiel angucken. Hier selekte ich den Value von Hexmap genau da, wo der Index genau, das ist ein bisschen, ein bisschen shifting und etwas dunkler Magie, bekommen wir genau. Und damit haben wir einen gepackten Little Indian Zeiger. Wie ich bereits erwähnt habe, nur einen einfachen Zeiger zu schreiben ist schon sinnvoll, aber noch nicht genug. Wir wollen weitergehen, wir wollen falsche Objekte schreiben und wir euch vielleicht auch erinnert, das müssen wir auch tun, denn die FTS 3 Tokenizer Funktionen braucht genau so eine, so eine Funktion. Das ist der Anfang dieser Funktionen. Da gibt es die i-Version, das ist eine neue Integer und da gibt es eine Funktion, die nicht interessant ist. Aber dann haben wir drei Funktionen, nämlich xCreate, der den Tokenizer erzeugt und xDustry, der den Tokenizer löscht. Und die dritte Funktion ist sehr interessant, denn das ist die Funktion, die den String tatsächlich tokenisiert. Das heißt, die Funktionen, der wir den String, den wir kontrollieren können, einfügen können. Das heißt, das ist die perfekte Funktion, die wir targetten könnten. So jetzt habe ich schon sehr viel von meinem SQL Knowledge verwendet, aber ich habe noch einen Trick, den ich noch nicht verwendet habe. Das sind Joint Queries. Wir werden jetzt einen Fake Tokenizer anlegen und dann werden wir eine Reihe von Ace konkatenieren und dann andere Sachen miteinander konkatenieren. Und jetzt lasst uns mal schauen, was im Debaker dabei rauskommt. Dann sehen wir, in ein paar Plätzen sieht man aaa und dann sieht man dieses simple create und das simple destroy. Und wir sind fast fertig, aber wir brauchen noch eine Zutat für diesen Nextploit. Wir haben jetzt bereits den fehlerhaften Tokenizer und wir wissen auch, wo der heap ist, aber wir wissen noch nicht, wo unser Tokenizer ist. Das ist ein guter Punkt, wo man heap Spraying machen kann. Das heißt, wir wollen unser Fake Object Primitive wiederholen. Das heißt, wir dachten, okay, wer es mit Repeat, aber leider ist das nicht in SQL Light implementiert, sondern um MySQL. Aber zum Glück gibt es Stack Overflow und das heißt, wir werden da die zero Blobfunktionen verwenden, die einen Blob zurückliefert mit N-Bytes und wir werden Replace verwenden, um Sachen dann sehr häufig zu ersetzen. Und hier sieht man jetzt im Debaker, auch wenn es vielleicht schwierig ist zu lesen. Hier haben wir sehr viel Konsistenzität. Das heißt, wir haben sehr viel, eine sehr gute heap Spraying Technik entwickelt. Und damit haben wir alle Sachen, die wir auf unser Lester haben, abgehakt und können zu unserem ursprünglichen Ziel zurückkehren. Noch einmal zur Wiederholung, das ist das Kurznippet von diesem Password Stealer. Und unten sieht man, das versucht, das ist das Secret zu extrahieren, indem es aus BodyRidge aus der Tabelle Notes extrahieren möchte. Und wir werden jetzt eine kleine Überraschung für diese SelectCurry vorbereiten. Wir erzeugen jetzt eine Notes, die hat drei Subcurries in den einzelnen Tabellen. Und jede dieser Subcurries ist auch eine Curry von sich selbst. Und wir werden in Overrides und Tokonase werden unseren Tokonase erzeugen. Und jetzt fragt ihr euch wahrscheinlich, was ist heap Spray? Und heap Spray ist diese Code Kette, die unsere heap Spray Technik, die wir entwickelt haben, benutzt. Und das ist eine Joint Query von ganz vielen Eis und dann eine ganz viele Pointer. Und das geht weiter, denn P64 SimpleCrate wurde abgeleitet von und das geht es immer weiter, down the rabbit hole. Wir benutzen ja also unsere Tagge Arithmetic-Mitgliedkeiten und machen weiter mit dem U64 League, dem FASC-NCR League und wir können das jetzt noch alles tun mit dem League, wie wir es ursprünglich aus der initialen Gewundbarkeit dem FT-S Tokoniser geholt haben. Das weiß es einer der drei Cobb Ketten. Und immer dann, weil ich diesen Exploit beschreibe, das ist das wahrscheinlich genau, wie ich für euch aussehe und irgendwie fühle ich mich auch so. Aber ihr müsst das Wettere aussehen, noch euch anfühlen, wie ich. Wir haben das mit Python realisiert in Cop.py und das könnt ihr jetzt bauen mit vier einfachen Zeilen Python. Damit könnt ihr jetzt also lustig spielen und nicht verrückt auf der Bühne aussehen. Wir können so jetzt also einen Passwortstealer-Backend angreifen. Hier sehen wir dann die ganzen interessierten Opfer dieses Passwortstealers. Jetzt schauen wir uns, ja wir kriegen 404 wenn wir auf die Web stellen wollen. Jetzt schauen wir uns den Computer der attackierenden Person an. Da fangen wir an mit Cop.py. Das generiert so eine das für die Datenbank, die ist erzeugt worden. Und jetzt werden wir eine Infektion simulieren und senden das an diesem Command and Control Server, der infiziert wurde von den Passwortstealen. Und weil das alle eine gewisse Zeit dauert, können wir uns währendessen die ganzen DDL Statements ansehen und sehen dann, dass die simpelste Web Shell an something PHP gepipet wird. Hoffentlich. So, ist fertig, schön. Jetzt gehen wir zurück auf diese Seite, kriegen jetzt ein 200er und jetzt lass uns immer versuchen damit Code auszuführen, WMI, WWData und dann versuchen wir mal ETC Password, offensichtlich. Ja, Erfolg. Was gerade passiert ist und was wir gezeigt haben, ist, wir können so einen Query zu einer Bus-Haffen-Datenbank bringen und damit Bus-Haffen-Code auslösen können. Und so beliebt wie SQLite ist, gibt es damit große Möglichkeiten für eine große Reichweite an Attacken. Lass uns also einen weiteren Nutzungsfall entsehen. Das ist Persistieren auf iOS. iOS benutzt SQLite ausgiebig. Und Persistenz ist hart zu erreichen auf iOS, denn alle ausführbaren Dateien müssen signiert sein. Aber SQLite-Hatenbanken sind nicht signiert, gibt dir keinen Grund dafür. iOS und MacOS werden beide kompelliert mit Enable-FTS-Tokenizer. Das ist genau dieser gefährliche Flagg. Wir wollen also Code ausführbarkeit nach dem Reboot wiederkriegen, indem wir eine beliebige SQLite-Datenbank ansehen. Wir nehmen hier das Adressbuch und ins Visier. Das ist eine Beschreibung in der originalen Datenbank, die haben keine besonders interessante Bedeutung. Und ich werde da eine Bus-Haffen-Datenbank ContactDB erzeugen. Womit ihr jetzt schon vertraut seid, wir fangen erst mal an mit den default-Tokenizer zu überschreiben. Das zweite DDL-Statement ist, installiert sie jetzt diesen Bus-Haffen-Trigger. Es wird immer dann crashen, wenn ihr das virtuelle Tabellenmodul auslöst. Was ich jetzt als nächstes mache, ist, jede Original-Tabelle ansehen mit diesem Curry-High-Jacking, was wir jetzt schon kennen. Also statt der Tabellen, statt der Spalten, die wir erwarten, leiten wir diese Statements ab in die Views, die wir hier gerade bauen, die ihr schon kennt. Wir rebooten und voila, wir haben damit den Secure Boot umgegangen. Das wirklich schön ist daran, der Crash ist gelassiert an 41, 49, 49, das ist genau das, was wir erwarten werden, was passiert, was passieren würde mit dem Offset 8 von der Version. Okay, gibt noch mehr. Die Datenbank wird aber von vielen Prozessen benutzt, von Contacts, FaceTime, Springboard, WhatsApp, Telegram, Excavacy Proxy und so fort. Viele dieser Prozesse sind viel privilegierter als andere und damit können wir code dann also auslösen in den Prozessen, die diese Datenbank befragen und damit können wir Privilegien eskalieren. Es gibt nicht spezielles an dieser Kontaktdatenbank. Jede dieser geteilten Datenbanken kann benutzt werden. Die müssen also einfach nur beschreibbar sein durch einen schwachen Nutzer und wir können uns so eskalieren zu einem stärkeren Nutzer. Bei diesen Bucks haben wir natürlich Reported an Apple, hier sind DCVs, um das abzuschließen. Wenn ihr irgendwas von diesem Talk mitnehmt, dann möchte ich nicht, dass ihr irgendwie verrückt der SQL-Kundinastik mitgenommen habt, sondern einerseits sollte ihr mitnehmen, eine Datenbank befragen, ist potenziell nicht sicher. Denn das ist möglicherweise nicht sicher wegen Query-High-Jacking. Mit Query-Oriented programmieren können wir halt insbesondere Memory Corruptions ausbauten mit nichts weiter als SQL. Kein JavaScript, kein Web-SQL. Wir sind uns ziemlich sicher, dass das nur die Spitze des Icebacks ist. SQLite total beliebt, aber es ist eigentlich immer nur durch die sehr schmale Linse Web-SQL angesehen worden. Es ist zwar total aufregend, Browser zu High-Jacken, aber es gibt so viel mehr Potenzial dafür. Wir haben viele Gedanken über zukünftige Arbeiten, die man darauf machen kann. Was Interessantes wäre halt die Prometive zu erweitern, zu absoluten Leseschreibzugriff. Meine Skizze von Exploits war nicht schön, weil da viel Art kommt, wenn man interne Funktionen von SQLite benutzt, wie SQLite Version, welche Compile-Options waren drin, dann kann man diese Cockchains dynamisch aufbauen und tatsächlich die spezifische Umgebung, in der man sich gerade befindet, exploiten. Und damit könnte man in so vielen Situationen Privilege-Eskalationen betreiben. Denn Entwicklerinnen hatten einfach ja auch nie im Gedanken, dass man eine Datenbank, die von Schwachen Nutzerinnen beschrieben und belesen werden kann, zur Privilegien-Eskalation nutzen werden könnte. Was sie außerdem wahrscheinlich gesehen hat, ist, dass von den Primitiven nichts Exklusives für SQLite. Also wäre es sehr interessant zu sehen, was diese Primitive in anderen Datenbankendits machen. Mit anderen Memory-Crafts und Bugs in anderen Datenbankendits. Vielen Dank. Das gibt uns sehr viel Zeit für Fragen. Wir haben hier drei Mikrofone, Nummer eins, Nummer zwei und Nummer drei. Wenn ihr Fragen habt, dann stellt euch bitte an. Haben wir ja schon Fragen aus dem Internet. Nein, noch nicht. Nummer zwei bitte. Ich habe eine Frage bezüglich des High-Jacking der Create-Funktionen. Du hast erwähnt, dass am Anfang des Researchs, du angenommen hast, dass create das erste Wort in diesem Check sein muss und dann ein Space. Und dann konntest du ganz viele andere Sachen erzeugen. Meine Frage ist, ob sich das geändert hat, nachdem das reported wurde. Es scheint ja ein Weg sein, um das zu exploiten. Wie mich interessiert hat, ob sich was wurde getan, um das zu verhindern? Die SQL-Light-Leute haben sich eher mit spezifischen Bugs als mit solchen Exploitation-Techniken beschäftigt. Also nein, diese Verreifikation ist nicht verändert worden. Und diese Validierung create space ist tatsächlich noch nicht lange drin. Vorher hätte jedes DDL-Statement drin sein können. Viel Glück in der Zukunft damit. Nummer eins bitte. Hast du eventuell aus Versehen ein Passwort angegriffen, der zum Steal benutzt wurde? Nein, das würde ich natürlich nicht tun. Da wäre ja kein Legitimer POC. Die Passwörter sind sicher bei den Stealer. Haben wir Fragen aus Internet? Keine Fragen.