mercredi 27 juillet 2016

L'attaque baptisée SHELLSHOCK

Description :

Il s'agit d'une vulnérabilité logicielle présente dans le shell Unix bash. Ce logiciel est responsable de l’exécution de programmes, que ce soit des programmes lancés par des utilisateurs que d’autres programmes, et est souvent utilisé par les serveurs web pour lancer des sous-programmes responsables de la génération des pages. Cette faille touche l’environnement, un ensemble de données transmises de programme en programme, qui contient des informations utiles pour l’exécution de ces derniers. Dans le cas d’un serveur web, il est utilisé pour transmettre toutes les informations sur une requête (quelle page demande l’utilisateur, quel navigateur il utilise, de quelle page il vient, …) au programme suivant. Le problème est une fonctionnalité ajoutée à bash il y a longtemps (en 1989) qui permet d’utiliser l’environnement pour passer des fonctions, des morceaux de code qui peuvent être utilisées par le shell pour exécuter certaines tâches. Cette fonctionnalité peut se révéler utile et n’est pas vraiment le problème: dans le cas d’un serveur web, bash se contenterait de passer le code de la fonction au programme de génération de la page et ne jamais les utiliser. Mais voici le problème: si la fonction est écrite correctement, elle peut forcer bash à exécuter du code à son lancement, ce qui n’est pas souhaitable. Cela veut dire qu’une personne peut simplement demander une page et introduire un en-tête HTTP spécialement préparé, et lorsque bash va lire l’environnement contenant les données malicieuses, il va tenter de les exécuter. Et cela permet d’exécuter toutes sortes d’attaques.

Exploitation (POC)

Démo d'une attaque Shellshock par injection d'entête HTTP :

Le test démontré consiste à envoyer à un serveur web[1], disponible sur le réseau,  un paquet HTTP forgé avec des entêtes HTTP contenant une injection de commande. Le serveur, étant vulnérable contre ShellShock, va passer les valeurs des entêtes HTTP sous forme de variables Bash et par conséquent les commandes incluses seront exécutées de manière illicite.

Schéma global du réseau
Le réseau virtuel privé mis en place tourne sous Virtualbox selon l’architecture suivante :


Les adresses IP des deux machines ont été affectées par le serveur DHCP, propre à l'adaptateur ethernet #2 avec le pool d’adresse 192.168.220.220-100/24.

Machine d'attaque :


Récolte d’informations :

En réalisant un mapping du réseau avec Nmap sur l’adresse 192.168.220.100/24 nous avons découvert l’adresse 192.168.220.103 sur laquelle nous avons effectué un scan plus approfondi.



Nous pouvons constater les différents ports ouverts et les différentes versions de services  en vigueurs sur ces ports. On constate également le déploiement d’interfaces de connexions administratives via SSH d'une part, et un serveur Web qui tourne sur le port 80 d'autre part.

En tentant d'y accéder au site web à travers un navigateur, on tombe sur la page suivante :


Si on s'attarde sur le contenu de la page web, on verra bien qu'elle inclut des informations sur le système (le serveur web en question). En parcourant le code source de cette page, on s'aperçoit de la fonction appelé par un script pour générer une telle sortie. Il s'agit de la fonction status() qui est définit ainsi :


En fait, cette fonction fait appel à un script CGI dont on a pu clairement obtenir le chemin.
En indiquant le chemin du script dans la barre d'adresse, on retrouve bien les informations précédentes  sur le système ainsi :


A présent, nous allons actualiser la page tout en interceptant la requête de chargement de la page avec le proxy Burp afin  d'y injecter notre code malicieux dans l'en-tête HTTP. Plus précisément, nous allons modifier la valeur du champ 'User Agent' de l'en-tête HTTP comme suit :


On modifie cette valeur par le code suivant afin de tester si le serveur est vulnérable contre ShellShock :


A priori, il s'agit d'un code plus ou moins bénin qui va afficher la chaine de caractère précisée,  dans la page retournée, ainsi :


En effet, notre code a été interprété par Bash et a été correctement exécuté, ce qui affirme l'existence de la faille ShellShock dans le serveur web en question.
Encore plus critique, nous allons tenter de charger le fichier /etc/passwd depuis le serveur :


Le résultat est le suivant :



Désormais, la gravité de la faille commence à prendre de l'ampleur étant donné qu'on a pu charger le fichier des mots de passes des utilisateurs depuis le serveur.
Pour finir, nous allons tenter de maintenir un reverse shell sur le serveur en ouvrant un port sur notre machine et en tenant de s'y connecter depuis le serveur afin qu'on puisse obtenir un shell dessus.
A titre d'exemple, on ouvre le port 31337 sur notre machine comme suit :


Ensuite, on injecte le code malicieux suivant permettant le back connect :

On voie clairement notre adresse IP incluse dans le code injecté dans la figure précédente.

A présent, si on revient vers notre terminal (là où netcat écoute sur le port 31337),


On pourra suivre l'établissement de la connexion étant donné que le mode verbose (option -v) a bien été précisée.
Une fois connecté, on pourra exécuter des commandes à distance ainsi :


Ce qui reflète d'ailleurs toute la criticité de de cette vulnérabilité.
Sachez que l'exploitation de cette vulnérabilité pourrait se faire automatiquement de manière très rapide en utilisant le framwork Metasploit et l'exploit exploit/multi/http/apache_mod_cgi_bash_env_exec. Il suffira d'indiquer uniquement l'adresse IP du serveur web ainsi que le lien vers le script CGI. L'obtention d'un shell se fait aisément en utilisant la payload "linux/x86/meterpreter/reverse_tcp" de metasploit.

lundi 18 juillet 2016

wCTF3 Crypto 100 (RSA encryption)

weirdCTF3 crypto 100 (RSA encryption)
by Brahimi Zakaria


After downloading the compressed file (here) and having it extracted, we find two files named : 'public.key' (which contain the public key of the rsa keypair) and 'flag.crypted' (which contain the flag encrypted).

The task is clear, we have to recover the private key to get the flag.

Let's begin with exploring informations within the public key with openssl like this :

Input :
openssl rsa -noout -text -inform PEM -in public.key -pubin

Output :
openssl rsa -noout -text -inform PEM -in public.key -pubin
Modulus (565 bit):
    12:fb:b2:17:cc:d5:a2:a9:8c:73:67:77:7a:1d:e9:
    37:c7:7d:73:87:65:1e:20:84:b3:8f:4e:f9:3e:c4:
    96:8e:1b:be:9b:b2:30:23:45:05:33:7e:79:fc:fd:
    b7:78:37:7d:7a:c0:07:37:47:f2:27:5b:f9:c4:de:
    03:56:de:df:be:83:79:be:14:c6:75
Exponent: 65537 (0x10001)

It's an RSA public key with a non common size of 565 bits.

The public key only contains the modulus N and the exponent e. N could be factorized into 2 prime numbers p and q, so N = p x q.
Based on those 2 numbers we will be able to generate the private key.

As the modulus above is in a hexadecimal form, we have to convert it to a decimal form like this :

Input :
python -c "print int('12fbb217ccd5a2a98c7367777a1de937c77d7387651e2084b38f4ef93ec4968e1bbe9bb230234505337e79fcfdb778377d7ac0073747f2275bf9c4de0356dedfbe8379be14c675', 16)"

Output :
71641831546926719303369645296528546480083425905458247405279061196214424558100678947996271179659761521775290973790597533683668081173314940392098256721488468660504161994357


The modulus is made of 565 bits. Thus it couldn't be factorised easily.
Another possibility is fermat's factorisation.

By running a script (factorisation.py) which implement the Fermat's factorisation against this large prime number, we could spits out the two primes immediately.

Input :
python factorisation.py

Output :
p : = 8464149782874043593254414191179506861158311266932799636000173971661904149225893113387
q : = 8464149782874043593254414191179506861158311266932799636000173971661904149225893113311


Now we could regenerate the private key using another script called rsatool.py like this :

Input :

python rsatool.py -p 8464149782874043593254414191179506861158311266932799636000173971661904149225893113387 -q 8464149782874043593254414191179506861158311266932799636000173971661904149225893113311 -o private.pem

Output :

n = 12fbb217ccd5a2a98c7367777a1de937c77d7387651e2084b38f4ef93ec4968e1bbe9bb230234505337e79fcfdb778377d7ac0073747f2275bf9c4de0356dedfbe8379be14c675

e = 65537 (0x10001)

d = fdc0a8949cf7e4b8a94ebef6cadcaa7985a1e081319dd6f2098ed10dd38ded3b12848e2890cc75db5c9ed94e0b3f570bfdce9ef781e3db2e7d99069e78fe6425ec168752d64ed

p = 45b62603351c22f7148bcaa5cf013ad3c05dfcc054a146945d907c24d0f7053a461ae2b

q = 45b62603351c22f7148bcaa5cf013ad3c05dfcc054a146945d907c24d0f7053a461addf

Saving PEM as private.pem


We can now decrypt the base64 encoded cipher within the file 'flag.crypted' and decipher the content with the private key we had generated :

Input :

cat flag.crypted | base64 -d > flag
openssl rsautl -decrypt -in flag -inkey private.pem

Output :
wctf{RSA_c1n_b3_w3AK_b3_c4reFuL}


That's it.