PHP Upload Security Tutorial

PHP Upload Security Tutorial

PHP Upload Security Tutorial

Perhaps our PHP Upload Primer Tutorial shows us a little “green around the gills” regarding “uploading”. Let’s face it, there is quite a bit more malicious activity going on with the net that means the discussion back then did not address “security” issues enough. That makes …

  • upload … and …
  • security

… be common bedfellows in many an online issue discussion these days? Well, think about it, what activities can involve content generation you may not be supervising directly, yourself, as content generators, online? Programmatical uploads, we’d say, using serverside languages, which in our case here at RJM Programming, primarily involves PHP.

The intention here is not to scare content generators, but parroting and trusting mime types will not stop a simple rename operation by a malicious uploader. You, as the programmer responsible for the uploading software need to be able to say (statements like) …

This nominally called JPEG image file contains JPEG formatted data

… before going on to any size checks or other checks you want to apply to the uploaded data as it arrives at your web server, before accepting it, which happens with PHP statements such as …

<?php

move_uploaded_file($tmp_name,$dir . $iprealbit);

?>

Take a look at our PHP “if” statements ahead of allowing that statement above to take effect, and place a file onto your web server …

Image files …
<?php

$types = array("image/jpg","image/jpeg","image/png","image/gif","image/bmp");

//$mime_type = mime_content_type($_FILES['upload']['tmp_name']); // thanks to https://github.com/Studio-42/elFinder/issues/815 and https://stackoverflow.com/questions/59986082/php-how-to-properly-check-mime-type-of-a-file
//if (getimagesize($_FILES['upload']['tmp_name']) !== false && in_array($mime_type, $types) && in_array($_FILES['upload']['type'], $types) && file_exists($dir) && filesize($tmp_name) <= floor($_POST['MAX_FILE_SIZE'])){ if (getimagesize($_FILES['upload']['tmp_name']) !== false && in_array($_FILES['upload']['type'], $types) && file_exists($dir) && filesize($tmp_name) <= floor($_POST['MAX_FILE_SIZE'])){ move_uploaded_file($tmp_name,$dir . $iprealbit);
}

?>
Audio or video files …
<?php

$types = array("audio/wav","audio/x-wav","audio/x-pn-realaudio","audio/x-mpegurl","audio/x-aiff","audio/mpeg","audio/mid",
"audio/basic","audio/ogg","video/x-sgi-movie","video/x-msvideo","video/quicktime","audio/mp3","video/mp4","video/mpeg",
"video/x-la-asf","video/ogg","video/webm","audio/mp4");

$mime_type='';
if (!function_exists('finfo_open')) { // thanks to https://stackoverflow.com/questions/5398488/alternative-to-finfo-for-php-5-3
$mime_type = exec("file -iL " . escapeshellcmd($_FILES['upload']['tmp_name']) . " 2>/dev/null");
$mime_type = trim(strtok(substr(strrchr($mime_type, ":"), 1), ";"));
} else {
// check REAL MIME type via https://stackoverflow.com/questions/52899276/detect-if-a-file-is-an-audio-file-in-php-without-mime-type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $_FILES['upload']['tmp_name'] );
finfo_close($finfo);
}

if (in_array($mime_type, $types) && in_array($_FILES['upload']['type'], $types) && file_exists($dir) && filesize($tmp_name) <= floor($_POST['MAX_FILE_SIZE'])) { move_uploaded_file($tmp_name,$dir . $iprealbit);
}

?>

If “goodwill” is guaranteed (and even if not), though, back at the file browsing aspects to your HTML form these attributes can help …

Image files …
<?php

<form style="background-color: #E4E4E4;" action="upload.php" method="post" enctype="multipart/form-data">

<fieldset>
<legend>Upload "Upload File - RJM Programming" jpg photo file(s) (<= 1,000,000 bytes) - Everybody Welcome!</legend>
<input type="hidden" name="MAX_FILE_SIZE" value="1000000">
<input style="background-color: yellow;" size="100" background-color:="" yellow;"="" type="file" name="upload" accept="image/*" data-capture="">
</fieldset>
<input style="color: green;" type="submit" name="submit" value="Upload Files">
<input style="color: red;" type="submit" name="home" value="Reload Home Page...">
</form>

?>
Audio or video files …
<?php

<form style="font-size:34px;background-color: #E4E4E4;" action="upload_audio.php?random=1618371584" method="post" enctype="multipart/form-data">
<fieldset>
<legend>Upload Audio/Video "RJM Programming" file(s) (<= 3,000,000 bytes) - Everybody Welcome ... but keep it fairly short!</legend>
<input type="hidden" name="MAX_FILE_SIZE" value="3000000">
<input onclick=" if (tois != '' && sofar.indexOf(':@') == -1 && sofar.indexOf('@?') == -1 && sofar.indexOf(':?') == -1) { if (1 == 2) { document.getElementById('myspan').style.display='block'; } document.getElementById('emailsubmit').style.display='block'; } document.getElementById('submit').style.display='inline'; document.getElementById('dmodes').style.display='inline'; " style="font-size:26px;height:60px;background-color: yellow;" type="file" id="files" name="upload" accept="video/*,audio/*" data-capture="">
</fieldset>
<span id="myspan" style="display:none;" class="readBytesButtons">
<button style="display:none;" data-startbyte="0" data-endbyte="4">1-5</button>
<button style="display:none;" data-startbyte="5" data-endbyte="14">6-15</button>
<button style="display:none;" data-startbyte="6" data-endbyte="7">7-8</button>
<button style="background-color:pink;">Email this Audio/Video</button>
</span>
<div style="display:none;" id="byte_range"></div>
<div style="display:none;" id="byte_content"></div>
<p>Fill out all fields below to email your content, before clicking above to create Audio/Video:</p>
<input name="mode" type="hidden" value="y">
<input id="jmydurl" name="mydurl" type="hidden" value="">
To: <input onblur="fix_jmymobile(this.value,'?',':');" name="to" type="email" value="" style="width:300px;"><br>
Subject: <input onblur="fix_jmymobile(encodeURIComponent(this.value),'&body=','?subject=');" name="subject" type="text" value="My Audio/Video Share ... which you may need to download ..." style="width:300px;"><br>
<input name="mymobile" id="jmymobile" type="hidden" value="mailto:@?subject=My%20Audio%2FVideo%20Share%20...%20which%20you%20may%20need%20to%20download%20...&body="><br>
<input id="submit" style="font-size:36px;color: green;display:none;" type="submit" name="submit" value="Upload Audio/Video Files"> <div style="display:none;" id="dmodes"> Links: <input type="checkbox" name="dlinks" id="dlinks" checked=""> Audio/Video Controls: <input type="checkbox" name="dvideoaudios" id="dvideoaudios" checked=""> Downloads: <input type="checkbox" name="ddownloads" id="ddownloads" checked=""> Iframe: <input type="checkbox" name="diframes" id="diframes" checked=""></div>
<input onclick="if (1 == 2) { document.getElementById('fclick').click(); } " name="emailsubmit" id="emailsubmit" style="font-size:36px;color: green;display:none;" type="submit" value="Email Audio/Video Files">
<!--input style="color: red;" type="submit" name="home" value="Reload Home Page..." /-->
</form>

?>

… and would be “sort of great” just on their own if it wasn’t for …

  1. that “All Files” ways the list can be manipulated down the bottom of the browsing dialog box …
  2. way somebody with malicious intent can come in with an improperly named file

You can insist on administrative moderation too, which is good to do especially as the content and size could be okay but the content offensive, if you want to save to a web server non-visible folder in the meantime, perhaps. Again, we’re sorry if this scares, but if we are talking “security” these matters are important.


Previous relevant PHP Upload Primer Tutorial is shown below.

PHP Upload Primer Tutorial

PHP Upload Primer Tutorial

Most of us are into downloading, as we thirst for information, and as most of us are the ones lacking the information, we go and download the information, except if we are on an escalator while downloading, when there is a 50/50 chance of “up” to the downloading. Do you catch my drift, or do you want me to explain the rules of cricket? … it’s your choice?! Thought so … so let’s talk about uploading. Uploading is the process that web managers and content managers do a lot, whereby the information is taken to the repository (or website (database)) where the data is stored ready for somebody to download (or if they are on an escalator (well, you know what I mean)), or just to be part of the website content.

Because uploading requires file manipulation you will not be able to do it with purely clientside code like Javascript, so you will need a serverside language like PHP (spelt PHP backwards, if that is any help). And please don’t start sentences with “because”, and could you leave out starting them with “and” too, if you wouldn’t mind.

As you can see, am trying to wean myself off Wikipedia, and it is a bit hard to bulk things out, so my apologies for this, and would like to reiterate that apology here then now.

So, on with the show tutorial here where we show you an Upload scenario where people can contribute their own photos to a website presenting a stream of photos as the One Image Page Site notion at this blogsite. You will notice how PHP code can be used to test things about the file ahead of accepting it, and in this case we restrict people’s jpg files to 1000000 bytes or less (and did you know that 1mb is not 1000000 bytes, so have a read here). To have success you should restrict a lot or monitor a lot, to have a secure website environment. These are all concerns of CMS systems, and how those CMS systems are set up to function by website administrators and Bugs Bunny … down dog!

Here is a link to some downloadable PHP programming source code which you might like to rename to myjpgupload.php

Please think of this as a starting point for your further study of uploading and here is a good link for further study … PHP File Upload.

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

This entry was posted in eLearning, Event-Driven Programming, Operating System, Tutorials and tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *