Ekoparty CTF 2015 - Writeups

Am Abend nach dem Hacklu CTF hatte Sebastian den Drang erneut ein paar Challenges zu lösen. Auf Ctftime.org wurde der ekoparty CTF 2015 als erster Eintrag angezeigt und es war noch ein Tag Zeit um mitzuspielen. In diesem Blogpost wird Sebastian seine Lösungen für die folgenden Challenges beschreiben:

  • Slogans ( Trv 50)
  • SSL Attack (Trv 90)
  • Blocking truck (Trv 100)
  • Pass Check (Web 50)
  • XOR Crypter (Cry 200)
  • Press it (Misc 100)

Außerdem noch ein paar Notizen zu anderen Challenges, die er sich angeschaut hat.

Ich wünschte ich hätte mehr Zeit für diesen CTF gehabt. Einige Challenges sahen sehr viel versprechend aus und es hat mal wieder viel Spaß gemacht:

Slogans

Die Aufagbe bestand darin, die Slogans der Ekopartys 2008 & 2009 herauszufinden.

Da der jeweilige Slogan sehr prominent auf der Webseite angezeigt wird, war meine erste Idee die wayback machine zu nutzen, um die Webseiten in der Vergangenheit zu betrachten. Allerdings gab es keine Einträge für das Jahr 2008, sodass ich mich entschied, das allwissende Google zu fragen. Ich nutzte folgende Suchanfrage:

1
intext:ekoparty intext:2008 intext:slogan

Sceenshot of google dork

Der erste Treffer war ein Blogpost, welcher die gesuchten Informationen enthielt:

Sceenshot of ekoparty slogans 2008 and 2009

Die akzeptierte Flagge war: EKO{Vi root y entre_What if r00t was one of us?}

SSL Attack

Bei dieser Challenge sollte man den Namen eines auf einer Ekoparty vorgestellten SSL-Angriffes finden.

Auch diesmal half uns etwas Google-Zauberei (intext:ekoparty intext:ssl), denn dies listete einige Webseiten mit den bekannten Angriffen BREACH, CRIME und BEAST. Die letzte Abkürzung war die korrekte Flagge:

BEAST SSL attack presented auf ekoparty

Flagge: EKO{BEAST}

Blocking truck

Die Beschreibung gab an, dass vor dem Eingang ein blauer Truck stehen würde. Die korrekte Flagge sei die URL auf diesem.

Zunächst dachte ich, dass ich diese Challenge nicht lösen könnte, da ich nicht vor Ort bei der Veranstaltung war, sondern vor meinem Laptop in Berlin saß. Allerdings bezweifelte ich, dass es eine Challenge geben würde, die nur von anwesenden Teams gelöst werden könnte. Ich probierte also mein Glück mit Google Maps und siehe da: Mit Hilfe von Streetview konnte ich mir den Truck anschauen und die URL ablesen.

Streetview of blue truck at ekoparty

Die Domain war ein wenig unscharf, aber das Eintippen von desimonehnos.com.ar führte zur korrekten Webseite. In der ersten Version der Aufgabe wurde von url to contact gesprochen, sodass ich einige Versuche benötigte, um herauszufinden, dass die Landing-Page genügte.

Flagge: EKO{http://www.desimonehnos.com.ar} oder EKO{www.desimonehnos.com.ar} (Kann mich nicht mehr genau daran erinnern…)

Pass check

Das war die erste Web-Challenge. Sie sah nicht nur toll aus, sondern machte auch noch schöne Geräusche beim Eintippen eines Passworts ;)

Screenshof of pass check input box

Die Geräusche und das Geblinke waren schön, hatten allerdings nicht mit der Lösung zu tun. Ich startete BurpSuite und schaute mir den AJAX-Request an. Nach ein paar einfachen Versuchen ersetzte ich password=test mit password[]=test und daraufhin war die Applikation so nett mir die Flagge zu nennen.

Screenshof of pass check input box

Flagge: EKO{strcmp_not_s0_s4fe}

Die Funktion strcmp ist nicht für Vergleiche von Objekten, die keine Strings sind, geeignet. Eine interessante Auflistung kann auf php.net gefunden werden.

XOR Crypter

Gegeben war der folgende String CjBPewYGc2gdD3RpMRNfdDcQX3UGGmhpBxZhYhFlfQA= und Python Quellcode.

Der String ist offensichtlich base64 kodiert, aber eine Dekodierung führte zu einem wenig sinnvollen Ergebnis: 0O{sh1_t7_uhiabe}. Also musste ich doch auf den Quelltext gucken. Der Kodierungsalgorithmus verlängert die Daten auf eine durch 4 teilbare Länge. Danach werden die Daten in Stücke von 4 Byte geteilt. Jeder Block wird mit der nach 16 nach rechts geshifteten Version seiner selbst gexored. In Python kommt die Operation >> vor ^. Die letzte Operation besteht darin, jeden Block zu packen und das Ergebnis mit base64 zu kodieren.

Das Hauptproblem hier ist die Nutzung von XOR in Kombination mit dem rechts-shift. Hier ist eine Handsimulation des Vorganges:

1
2
3
4
5
6
# 1001 >> 2 (9 shifted by 2 adds zeros to the beginning and the result is 0010 = 2)
# 0010 ^ 1001 (2 xored 9 is 1011 = 11; This is the result of our encryption.)

# 1011 >> 2 (11 shifted by 2 is 0010 = 2)
# 0010 ^ 1011 (11 xored with 2 is 1001 = 9)
# 1001

Man beachte, dass bei einem Rechtsshift um N bits, die ersten N bits des Ergebnisses dieselben sind wie die Eingabe. Die Umkehrbarkeit von XOR ((Y ^ U) ^ U = Y) hilft uns bei der Wiederherstellung des verbleibenden Blockanteils. Die anderen Operationen (base64-Kodierung, Ein-/Auspacken) müssen einfach in verkehrter Reihenfolge ausgeführt werden. Hier ist der Link zu meinem kleinen Python Script [Ich habe ein paar print/debug Ausdrücke hinzugefügt]

Screenshof of XOR crypter output

Flagge: EKO{unshifting_the_unshiftable}

Press it

Meiner Meinung nach war dies die interessanteste Challenge. Man sollte die Flagge aus der folgenden Datei extrahieren: 05gXbV9/+Bpg=).

Zunächst dachte ich, dass es sich um zufällige Hexzahlen handelt, aber dann erinnerte ich mich an das Format/layout. Ich sah es als ich /usr/bin/showkey ausführte, um die dr.bob hacklu 2015 challenge zu lösen. Ich öffnete tty2 auf meiner Maschine und startete showkey -s und es gab ähnliche Hexzahlen aus als ich Tasten drückte.

Ich googelte nach einem Programm oder einem Tool, welches den Dump automatisch wieder umkehren und mir die gedrückten Tasten ausgeben würde. Leider ohne Erfolg, also musste man selbst Hand anlegen.

Ich las mich durch die Showkey Manpage und lernte, dass diese Codes Scancodes genannt werden und diese pro Taste/Zeichen eindeutig sind. Pro Taste gibt es zwei Codes: Einen, wenn die Taste gedrückt wird, und einen wenn diese wieder losgelassen wird.

Der letzte Fakt ist entscheidend, denn ich versuchte erst jedes Zeichen einzeln zu behandeln und dies führte zu einem komischen Ergebnis. Alle ? oder leere Codes sind wahrscheinlich Loslass-Codes. Zusätzlich musste ich auf die harte Tour lernen, dass auch Kombinationen von Codes möglich sind. Zum Beispiel 0xe0 0x38 steht für die linke Alt-Taste. Microsoft hat eine gute Übersicht mit Scancode-Zuweisungen

Nachdem ich alle Scancodes ein zweites Mal durchgearbeitet habe, stand folgendes Ergebnis in meinen Notizen: This is it. EKO{ibm_model_m}

Flagge: EKO{ibm_model_m}

Weitere Challenges/Notizen

Wie immer habe ich auch einen Blick auf andere Challenges geworfen, diese probiert zu lösen, aber bin dann irgendwie irgendwo stecken geblieben und kam nicht weiter. Ich bin ein wenig enttäuscht, dass ich Mr Anderson (Ich kenne den Film nicht, aber die Lösung sollte nicht so schwer sein?), Custom ACL (Ich habe hier viel Zeit verwendet - wahrscheinlich fehlt nur eine winziger Schritt) nicht lösen konnte.

Mr Anderson (Trv 80)

  • Mr Anderson und last serie deuten auf Mr.Robot
  • Ich verstehe den favority music artist Hinweis nicht. Ich probierte ein paar Soundtracks der letzten Episode. Kein Erfolg
  • Nicht genügend Motivation um alle möglichen Künstler zu brute-forcen.

Custom ACL (Web 100)

  • Entdeckung des Sources für admin.php unter admin.phps (Pastebin)
  • Versuch die REMOTE_ADDR mit X-Forwarded-For & co zu spoofen bis man lernt, dass dies wirklich nur die IP der TCP-Verbindung ist.
  • Nmap gegen die IP-Range 67.222.139.223-230 gestartet und Ergebnis ist ein Host mit ein paar interessanten Posts (Pastebin)
  • Versuche diesen als Proxy zu nutzen schlägt mit dem Fehler 501 method "GET/POST/Whatever" not supported fehl
  • Bermeken den Server: pve-api-daemon/3.0-Header, aber finden nicht heraus, wie man diesen (mis)brauchen kann.
  • Nicht genügend Zeit, um weiter darüber nachzudenken.

Crazy JSON (Web 300)

  • evaluator.js fehlt auf dem Server
  • HTTP Response enthält interessantes JSON (Pastebin)
  • new Ajsone() Aufruf. Google führt zu einem github repository mit einem Demo/Test-Bereich .
  • Xor (^) ist nicht implementiert. Implementiere es.
  • Passwort muss 32 Zeichen lang sein, aber weitere Evaluirungen führen zu einem error inf loop?.
  • Auch hier wird die Zeit knapp. Nichtdestotrotz interessant.

SVG Viewer (Web 400)

  • Hochladen von SVG mit XXE testvector -> Entity declaration detected Fehler
  • Versuch, eigene, externe DTD zu nutzen, um diesen Check zu umgehen. Funktioniert nicht wirklich wie gedacht. Wechsel zu einer anderen Aufgabe

Olive (Misc 50)

  • Pcap mit traffic
  • Viel VNC traffic / Http traffic möglicherweise uninteressant
  • Extrahieren VNC traffic in eine Datei. Sie nach einem RFB (remote frame buffer) aus
  • Suchen eine Programm, um dies wiederzugeben. Weder rfbproxy noch vncreplay funktionieren mit den extrahierten Daten.
  • Keine Ideen mehr, wie man RFB anzeigen/wiedergeben kann.

Auch diesmal vielen Dank für diesen wunderbaren CTF :)

Sebastian