Samuel Manechez | File upload - Type MIME | M2i2020 | --- | ---| --- |
Avec Shell
Analyse du site
- Galerie d'upload
- Fichier uniquement en GIF, JPEG or PNG
- "Wrong file" losque ce n'est pas un fichier autorisé
Analyse des requête HTTP
On observer une ligne application/w-php lorsqu'on essaie d'ajouter un fichier php.

Compromission
Création d'un fichier PHP cmd.php:
Modification de le requête en image/png.

Ouverture de la réponse, le fichier php est bien uploader. Accédons à ce dernier et ajoutons ?cmd=pwd dans l'URL pour avoir le dossier racine de l'applications.

Plus qu'à récupérer le flag à la racine :
URL : view-source:http://challenge01.root-me.org/web-serveur/ch21/galerie/upload/24c1fc3201ec15cf5713e6a1e1b30497//test5.php?cmd=cat%20../.passwd

Flag
Le flag a7n4nizpgQgnPERy89uanf6T4.
Sans Shell (Affichage de l'index avec coloration)
Création d'un script Shell
Upload
Envoyer le fichier via la page upload en modifier la requête HTTP POST :application/w-php  en image/png.
Exploitation

Code source
<?php
// File upload : MIME type
session_start();
$galerie_dir = 'galerie';
$www_dir     = './galerie/upload/' . session_id() . '/';
$upload_dir  = getcwd() . '/' .$www_dir;
$aff= '<html><head><style>body { background: black; color: white; }</style></head><body><h1>Photo gallery v 0.03</h1><span id=menu/>';
if (isset($_GET["galerie"]) &&
        preg_match("/^[a-z]+$/", $_GET["galerie"]) &&
        file_exists($galerie_dir."/".$_GET["galerie"]))
    $galerie = $_GET["galerie"];
else
    $galerie = "pirate";
if (file_exists($galerie_dir)) {
    $d = opendir($galerie_dir);
    while ($file = readdir($d)) {
      if ($file[0] == ".") { }
      else {
          $aff .= " | <span><a href='?galerie=$file'>";
          if ($file == $galerie)
              $aff .= "<b>$file</b>";
          else
              $aff .= "$file";
          $aff .= "</a></span>";
      }
    }
    $aff .= "<br><hr>";
    closedir($d);
}
if (isset($_GET["action"]))
    $action = $_GET["action"];
else
    $action = "view";
if ($action == "view") {
    if (isset($galerie)) {
        if ($galerie == "upload") {
            $path = $www_dir;
        } else {
            $path = $galerie_dir . '/' . $galerie;
        }
        if (file_exists($path)) {
            $aff .= '<table id="content"><tr>';
            $d = opendir($path);
            $i = 0;
            while ($file = readdir($d)) {
              if ($file[0] == ".") { }
              else {
                  $aff .= "<td><a href='$path/$file'><img width=64px height=64px src='$path/$file?preview' alt='$file'></a></td>";
                  $i = $i+1;
              }
              if ($i%4 == 0)
                  $aff .= "</tr><tr>";
            }
            $aff .= '</tr></table>';
        }
        if ($galerie == "upload") {
            $aff .= '<br><p><a href="?action=upload">Upload</a> your photo !</p>';
        }
    }
} else if ($action == "upload") {
    if (isset($_FILES["file"])) {
        $allowedExts = array("jpg", "jpeg", "gif", "png");
        $allowedType = array("image/gif", "image/jpeg", "image/png");
        $extension = end(explode(".", $_FILES["file"]["name"]));
        if (($_FILES["file"]["size"] < 100000)) {
          if (in_array($_FILES["file"]["type"], $allowedType)) {
            $aff .= "File information :<br><ul>";
            if ($_FILES["file"]["error"] > 0)  {
                $aff .= "<ul>";
                $aff .= "<li>Error: " . $_FILES["file"]["error"] . "</li>";
            } else {
                $aff .= "<li>Upload: " . $_FILES["file"]["name"] . "</li>";
                $aff .= "<li>Type: " . $_FILES["file"]["type"] . "</li>";
                $aff .= "<li>Size: " . ($_FILES["file"]["size"] / 1024) . " kB</li>";
                $aff .= "<li>Stored in: " . $WWW_DIR . "/". $_FILES["file"]["name"]."</li>";
            }
            $aff .= "</ul>";
            if (! file_exists($upload_dir)) {
                mkdir($upload_dir, 0750);
            }
            if (move_uploaded_file($_FILES["file"]["tmp_name"], $upload_dir."/".$_FILES["file"]["name"])) {
                $aff .= "<b>File uploaded</b>.";
            } else {
                $aff .= "<p style='color: red'>Error during upload</p>";
            }
          } else {
              $aff .= "<p style='color: red'>Wrong file type !</p>";
          }
        } else {
            $aff .= "<p style='color: red'>File size too big !</p>";
        }
    } else {
        $aff .= "<p><b>Upload your photo</b></p>";
        $aff .= "<form method=post enctype='multipart/form-data'>";
        $aff .= "<input type=file name=file />";
        $aff .= "<input type=submit value=upload />";
        $aff .= "</form>";
        $aff .= "<br><br><i>NB : only GIF, JPEG or PNG are accepted</i>";
    }
}
$aff .= "</body></html>";
echo $aff;
?>
Flag
De même pour récuprérer le flag :
Modifier la requête HTTP POST : application/w-php  en image/png.
Affichage du flag :

Correction
Modification du code originale
Modification de la ligne 83 :
- Avant :
Après :
La modification de la requête ne fonctionne plus. Dans tous les cas nous avons "Wrong file type".

Restriction .htaccess v1
Ajout d'une restriction .htaccess. Avant tout il faut modifier la configuration apache pour activer la prise en charge du fihcier .htaccess.
Répérer la ligne Directory, correspondant au dossier ou se trouve votre index.

Remplacer AllowOverride None par  AllowOverride All.
Redémarrer le service :
Créer un fichier .htaccess sous /var/www/html/galerie/upload/ avec ce contenu à l'intrérieur :
# 07/11/2019 10:37:03
# https://httpd.apache.org/docs/2.4/handler.html
# default-handler: envoie le fichier en utilisant le default_handler(), qui est>
# Vilain Hacker : .php. => contenu statique.
# Le PHP n'est que pour les honnêtes gens !
<FilesMatch "\.php$">
    SetHandler default-handler
</FilesMatch>
AddDescription "Le contenu du .htaccess" htaccess
Le $ à la fin permet de selectionner que les fichier avec extension .php.
L'éxécution de fichier .php n'est plus fonctionnelle.

Restriction .htaccess v2
Une autre méthode est d'interdire l'ensemble des fichier .php excepté ceux autorisés. 
Ajout d'une restriction .htaccess. Avant tout il faut modifier la configuration apache pour activer la prise en charge du fihcier .htaccess.
Répérer la ligne Directory, correspondant au dossier ou se trouve votre index.

Remplacer AllowOverride None par  AllowOverride All.
Redémarrer le service :
Créer un fichier .htaccess sous /var/www/html/  (à  la racine de l'application) avec ce contenu à l'intrérieur :
