LAB_03 / FILES Intermediate

An extension is not enough. Test actual file validation.

Experiment hint

First, try ordinary input. Then use an example from the lesson and compare the result in the vulnerable and protected variants. The code panels highlight the boundaries relevant to the attack or defense.

File Upload

01 / THEORY · ⚠ VULNERABLE CODE

Vulnerable variant

File uploads are a critical application boundary. Insufficient validation can lead to resource exhaustion and, in some applications, compromise of the server.

In the vulnerable variant, file properties such as type and size are not reliably checked. The following code illustrates an insufficient restriction.

<input type="file" name="fileToUpload" id="fileToUpload" accept="image/*">

The “accept” attribute attempts to restrict file types in the browser. A user can remove it in DevTools and upload a file that is not an image. The vulnerable variant also lacks a file size limit, allowing uploads that consume server resources.

The form below relies only on a client-side HTML attribute.

02 / EXPLOIT · TEST THE INPUT

03 / DEFENSE · ✓ PROTECTED CODE

Protected variant

Security checks must run on the server, where a user cannot remove them using browser developer tools. The following examples demonstrate server-side validation.

First, check the uploaded file type. The following example checks whether the file contains an image.

                        
$correct = 0;
@$check_error = getimagesize($_FILES["fileToUpload"]["tmp_name"]);

// Checking if an actual image
if( $check_error!== false) {
// Image
    $correct = 1;
} else {
// Not an image
    $correct = 0;
}

// Check the extension
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
$uploaded_type = $_FILES[ 'fileToUpload' ][ 'type' ];

if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
        && $imageFileType != "gif") {
//Wrong extension
        $correct = 0;
}
                

The getimagesize() function reads image information and returns false if the file cannot be recognized as an image. The pathinfo() function extracts the extension so it can be compared with allowed image extensions.

An image can also be re-encoded using imagecreatefromjpeg() or imagecreatefrompng() and the corresponding image output function to remove metadata. The following code illustrates this approach.

                        
if( $uploaded_type == 'image/jpeg' ) {
	$img = imagecreatefromjpeg( $uploaded_tmp );
    imagejpeg( $img, $temp_file, 100);
}
else {
	$img = imagecreatefrompng( $uploaded_tmp );
	imagepng( $img, $temp_file, 9);
}
imagedestroy( $img );

Next, check that the file size is within the allowed range and is greater than zero. A system that accepts unlimited empty files can still exhaust resources: file names and other filesystem metadata take up space even when the file content is empty.


// Check the size
if ($_FILES["fileToUpload"]["size"] > 100000  or $_FILES["fileToUpload"]["size"] == 0 ) {
    //Too large
$correct = 0;
}

Use the protected form below to compare the result of server-side checks with the vulnerable variant. Inspect the actual validation code alongside the examples.