{"id":64214,"date":"2024-07-15T03:01:00","date_gmt":"2024-07-14T17:01:00","guid":{"rendered":"https:\/\/65.254.95.247\/ITblog\/?p=64214"},"modified":"2024-07-17T12:59:27","modified_gmt":"2024-07-17T02:59:27","slug":"php-upload-security-tutorial","status":"publish","type":"post","link":"https:\/\/www.rjmprogramming.com.au\/ITblog\/php-upload-security-tutorial\/","title":{"rendered":"PHP Upload Security Tutorial"},"content":{"rendered":"<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Upload\/\" rel=\"noopener\"><img decoding=\"async\" style=\"border: 15px solid pink;\" alt=\"PHP Upload Security Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/upload_better.jpg\" title=\"PHP Upload Security Tutorial\"  style=\"float:left;\" \/><\/a><p class=\"wp-caption-text\">PHP Upload Security Tutorial<\/p><\/div>\n<p>Perhaps our <a title='PHP Upload Primer Tutorial' href='#phpupt'>PHP Upload Primer Tutorial<\/a> shows us a little &#8220;green around the gills&#8221; regarding &#8220;uploading&#8221;.  Let&#8217;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 &#8220;security&#8221; issues enough.  That makes &#8230;<\/p>\n<ul>\n<li>upload &#8230; and &#8230;<\/li>\n<li>security<\/li>\n<\/ul>\n<p> &#8230; 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&#8217;d say, using serverside languages, which in our case here at RJM Programming, primarily involves PHP.<\/p>\n<p>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) &#8230;<\/p>\n<blockquote><p>\nThis nominally called JPEG image file contains JPEG formatted data\n<\/p><\/blockquote>\n<p> &#8230; 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 &#8230;<\/p>\n<p>&lt;?php<br \/>\n<code><br \/>\n <a target=\"_blank\" title='move_uploaded_file information from home of PHP' href='https:\/\/www.php.net\/manual\/en\/function.move-uploaded-file.php' rel=\"noopener\">move_uploaded_file<\/a>($tmp_name,$dir . $iprealbit);<br \/>\n<\/code><br \/>\n?&gt; <\/p>\n<p>Take a look at our PHP &#8220;if&#8221; statements ahead of allowing that statement above to take effect, and place a file onto your web server &#8230;<\/p>\n<table>\n<tr>\n<th>Image files &#8230;<\/th>\n<\/tr>\n<tr>\n<td>\n&lt;?php<br \/>\n<code style=font-size:8px;><br \/>\n      $types = array(\"image\/jpg\",\"image\/jpeg\",\"image\/png\",\"image\/gif\",\"image\/bmp\");<br \/>\n<br \/>\n    \/\/$mime_type = mime_content_type($_FILES['upload']['tmp_name']); \/\/ thanks to <a target=\"_blank\" title='https:\/\/github.com\/Studio-42\/elFinder\/issues\/815' href='https:\/\/github.com\/Studio-42\/elFinder\/issues\/815' rel=\"noopener\">https:\/\/github.com\/Studio-42\/elFinder\/issues\/815<\/a> and https:\/\/stackoverflow.com\/questions\/59986082\/php-how-to-properly-check-mime-type-of-a-file<br \/>\n    \/\/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'])){  \n    if (<a target=\"_blank\" title='PHP getimagesize' href='https:\/\/www.php.net\/manual\/en\/function.getimagesize.php' rel=\"noopener\">getimagesize<\/a>($_FILES['upload']['tmp_name']) !== false && in_array($_FILES['upload']['type'], $types) && file_exists($dir) && filesize($tmp_name) <= floor($_POST['MAX_FILE_SIZE'])){  \n     <a target=\"_blank\" title='move_uploaded_file information from home of PHP' href='https:\/\/www.php.net\/manual\/en\/function.move-uploaded-file.php' rel=\"noopener\">move_uploaded_file<\/a>($tmp_name,$dir . $iprealbit);<br \/>\n    }<br \/>\n<\/code><br \/>\n?&gt;\n<\/td>\n<\/tr>\n<tr>\n<th>Audio or video files &#8230;<\/th>\n<\/tr>\n<tr>\n<td>\n&lt;?php<br \/>\n<code style=font-size:8px;><br \/>\n$types = array(\"audio\/wav\",\"audio\/x-wav\",\"audio\/x-pn-realaudio\",\"audio\/x-mpegurl\",\"audio\/x-aiff\",\"audio\/mpeg\",\"audio\/mid\",<br \/>\n      \"audio\/basic\",\"audio\/ogg\",\"video\/x-sgi-movie\",\"video\/x-msvideo\",\"video\/quicktime\",\"audio\/mp3\",\"video\/mp4\",\"video\/mpeg\",<br \/>\n      \"video\/x-la-asf\",\"video\/ogg\",\"video\/webm\",\"audio\/mp4\");<br \/>\n<br \/>\n    $mime_type='';<br \/>\n    if (!function_exists('finfo_open')) { \/\/ thanks to <a target=\"_blank\" title='https:\/\/stackoverflow.com\/questions\/5398488\/alternative-to-finfo-for-php-5-3' href='https:\/\/stackoverflow.com\/questions\/5398488\/alternative-to-finfo-for-php-5-3' rel=\"noopener\">https:\/\/stackoverflow.com\/questions\/5398488\/alternative-to-finfo-for-php-5-3<\/a><br \/>\n    $mime_type = <a target=\"_blank\" title='PHP exec() method information' href='http:\/\/php.net\/manual\/en\/function.exec.php' rel=\"noopener\">exec<\/a>(\"file -iL \" . escapeshellcmd($_FILES['upload']['tmp_name']) . \" 2>\/dev\/null\");<br \/>\n    $mime_type = trim(strtok(substr(strrchr($mime_type, \":\"), 1), \";\"));<br \/>\n    } else {<br \/>\n    \/\/ check REAL MIME type via <a target=\"_blank\" title='https:\/\/stackoverflow.com\/questions\/52899276\/detect-if-a-file-is-an-audio-file-in-php-without-mime-type' href='https:\/\/stackoverflow.com\/questions\/52899276\/detect-if-a-file-is-an-audio-file-in-php-without-mime-type' rel=\"noopener\">https:\/\/stackoverflow.com\/questions\/52899276\/detect-if-a-file-is-an-audio-file-in-php-without-mime-type<\/a><br \/>\n    $finfo = finfo_open(FILEINFO_MIME_TYPE);<br \/>\n    $mime_type = <a target=\"_blank\" title='finfo_file information from home of PHP' href='https:\/\/www.php.net\/manual\/en\/function.finfo-file.php' rel=\"noopener\">finfo_file<\/a>($finfo, $_FILES['upload']['tmp_name'] );<br \/>\n    finfo_close($finfo);<br \/>\n    }<br \/>\n<br \/>\n    if (in_array($mime_type, $types) && in_array($_FILES['upload']['type'], $types) && file_exists($dir) && filesize($tmp_name) <= floor($_POST['MAX_FILE_SIZE'])) {  \n     <a target=\"_blank\" title='move_uploaded_file information from home of PHP' href='https:\/\/www.php.net\/manual\/en\/function.move-uploaded-file.php' rel=\"noopener\">move_uploaded_file<\/a>($tmp_name,$dir . $iprealbit);<br \/>\n    }<br \/>\n<\/code><br \/>\n?&gt;\n<\/td>\n<\/tr>\n<\/table>\n<p>If &#8220;goodwill&#8221; is guaranteed <font size=1>(and even if not)<\/font>, though, back at the file browsing aspects to your HTML form <font color=blue>these attributes<\/font> can help &#8230;<\/p>\n<table>\n<tr>\n<th>Image files &#8230;<\/th>\n<\/tr>\n<tr>\n<td>\n&lt;?php<br \/>\n<code style=font-size:8px;><br \/>\n&lt;form style=\"background-color: #E4E4E4;\" action=\"upload.php\" method=\"post\" enctype=\"multipart\/form-data\"&gt;<br \/>\n        <br \/>\n      &lt;fieldset&gt;<br \/>\n           &lt;legend&gt;Upload \"Upload File - RJM Programming\" jpg photo file(s) (&lt;= 1,000,000 bytes) - Everybody Welcome!&lt;\/legend&gt;<br \/>\n           &lt;input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"1000000\"&gt;<br \/>\n           &lt;input style=\"background-color: yellow;\" size=\"100\" background-color:=\"\" yellow;\"=\"\" type=\"file\" name=\"upload\" <font color=blue>accept=\"image\/*\"<\/font> data-capture=\"\"&gt;<br \/>\n      &lt;\/fieldset&gt;<br \/>\n      &lt;input style=\"color: green;\" type=\"submit\" name=\"submit\" value=\"Upload Files\"&gt;<br \/>\n      &lt;input style=\"color: red;\" type=\"submit\" name=\"home\" value=\"Reload Home Page...\"&gt;<br \/>\n&lt;\/form&gt;<br \/>\n<\/code><br \/>\n?&gt;\n<\/td>\n<\/tr>\n<tr>\n<th>Audio or video files &#8230;<\/th>\n<\/tr>\n<tr>\n<td>\n&lt;?php<br \/>\n<code style=font-size:8px;><br \/>\n&lt;form style=\"font-size:34px;background-color: #E4E4E4;\" action=\"upload_audio.php?random=1618371584\" method=\"post\" enctype=\"multipart\/form-data\"&gt;<br \/>\n      &lt;fieldset&gt;<br \/>\n           &lt;legend&gt;Upload Audio\/Video \"RJM Programming\" file(s) (&lt;= 3,000,000 bytes) - Everybody Welcome ... but keep it fairly short!&lt;\/legend&gt;<br \/>\n           &lt;input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"3000000\"&gt;<br \/>\n           &lt;input onclick=\" if (tois != '' &amp;&amp; sofar.indexOf(':@') == -1 &amp;&amp; sofar.indexOf('@?') == -1 &amp;&amp; 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\" <font color=blue>accept=\"video\/*,audio\/*\"<\/font> data-capture=\"\"&gt;<br \/>\n      &lt;\/fieldset&gt;<br \/>\n&lt;span id=\"myspan\" style=\"display:none;\" class=\"readBytesButtons\"&gt;<br \/>\n  &lt;button style=\"display:none;\" data-startbyte=\"0\" data-endbyte=\"4\"&gt;1-5&lt;\/button&gt;<br \/>\n  &lt;button style=\"display:none;\" data-startbyte=\"5\" data-endbyte=\"14\"&gt;6-15&lt;\/button&gt;<br \/>\n  &lt;button style=\"display:none;\" data-startbyte=\"6\" data-endbyte=\"7\"&gt;7-8&lt;\/button&gt;<br \/>\n  &lt;button style=\"background-color:pink;\"&gt;Email this Audio\/Video&lt;\/button&gt;<br \/>\n&lt;\/span&gt;<br \/>\n&lt;div style=\"display:none;\" id=\"byte_range\"&gt;&lt;\/div&gt;<br \/>\n&lt;div style=\"display:none;\" id=\"byte_content\"&gt;&lt;\/div&gt;<br \/>\n      &lt;p&gt;Fill out all fields below to email your content, before clicking above to create Audio\/Video:&lt;\/p&gt;<br \/>\n      &lt;input name=\"mode\" type=\"hidden\" value=\"y\"&gt;<br \/>\n      &lt;input id=\"jmydurl\" name=\"mydurl\" type=\"hidden\" value=\"\"&gt;<br \/>\n      To: &lt;input onblur=\"fix_jmymobile(this.value,'?',':');\" name=\"to\" type=\"email\" value=\"\" style=\"width:300px;\"&gt;&lt;br&gt;<br \/>\n      Subject: &lt;input onblur=\"fix_jmymobile(encodeURIComponent(this.value),'&amp;body=','?subject=');\" name=\"subject\" type=\"text\" value=\"My Audio\/Video Share ... which you may need to download ...\" style=\"width:300px;\"&gt;&lt;br&gt;<br \/>\n      &lt;input name=\"mymobile\" id=\"jmymobile\" type=\"hidden\" value=\"mailto:@?subject=My%20Audio%2FVideo%20Share%20...%20which%20you%20may%20need%20to%20download%20...&amp;body=\"&gt;&lt;br&gt;<br \/>\n      &lt;input id=\"submit\" style=\"font-size:36px;color: green;display:none;\" type=\"submit\" name=\"submit\" value=\"Upload Audio\/Video Files\"&gt; &lt;div style=\"display:none;\" id=\"dmodes\"&gt; Links: &lt;input type=\"checkbox\" name=\"dlinks\" id=\"dlinks\" checked=\"\"&gt; Audio\/Video Controls: &lt;input type=\"checkbox\" name=\"dvideoaudios\" id=\"dvideoaudios\" checked=\"\"&gt; Downloads: &lt;input type=\"checkbox\" name=\"ddownloads\" id=\"ddownloads\" checked=\"\"&gt; Iframe: &lt;input type=\"checkbox\" name=\"diframes\" id=\"diframes\" checked=\"\"&gt;&lt;\/div&gt;<br \/>\n      &lt;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\"&gt;<br \/>\n      &lt;!--input style=\"color: red;\" type=\"submit\" name=\"home\" value=\"Reload Home Page...\" \/--&gt;<br \/>\n&lt;\/form&gt;<br \/>\n<\/code><br \/>\n?&gt;\n<\/td>\n<\/tr>\n<\/table>\n<p> &#8230; and would be &#8220;sort of great&#8221; just on their own if it wasn&#8217;t for &#8230;<\/p>\n<ol>\n<li>that &#8220;All Files&#8221; ways the list can be manipulated down the bottom of the browsing dialog box &#8230;<\/li>\n<li>way somebody with malicious intent can come in with an improperly named file<\/li>\n<\/ol>\n<p>You can insist on administrative <a target=\"_blank\" title='Moderation information from Wikipedia ... thanks' href='https:\/\/en.wikipedia.org\/wiki\/Moderation_system' rel=\"noopener\">moderation<\/a> 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&#8217;re sorry if this scares, but if we are talking &#8220;security&#8221; these matters are important.<\/p>\n<p><!--p>You can also see this play out at WordPress 4.1.1's <a target=\"_blank\" href='\/\/www.rjmprogramming.com.au\/ITblog\/new-php-upload-primer-tutorial\/' rel=\"noopener\">New PHP Upload Primer Tutorial<\/a>.<\/p-->\n<hr>\n<p id='phpupt'>Previous relevant <a target=\"_blank\" title='PHP Upload Primer Tutorial' href='\/\/www.rjmprogramming.com.au\/ITblog\/php-upload-primer-tutorial\/' rel=\"noopener\">PHP Upload Primer Tutorial<\/a> is shown below.<\/p>\n<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Upload\/\" rel=\"noopener\"><img decoding=\"async\" style=\"border: 15px solid pink;\" alt=\"PHP Upload Primer Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Upload\/PHP_Upload_Primer-53of.jpg\" title=\"PHP Upload Primer Tutorial\"  style=\"float:left;\" \/><\/a><p class=\"wp-caption-text\">PHP Upload Primer Tutorial<\/p><\/div>\n<p>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 &#8220;up&#8221; to the downloading.   Do you catch my drift, or do you want me to explain the rules of cricket? &#8230; it&#8217;s your choice?!   Thought so &#8230; so let&#8217;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.<\/p>\n<p>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&#8217;t start sentences with &#8220;because&#8221;, and could you leave out starting them with &#8220;and&#8221; too, if you wouldn&#8217;t mind.<\/p>\n<p>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.<\/p>\n<p>So, on with the <strike>show<\/strike> tutorial <a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Upload\/\" rel=\"noopener\">here<\/a> 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&#8217;s jpg files to 1000000 bytes or less (and did you know that 1mb is not 1000000 bytes, so have a read <a title='1mb' href='http:\/\/www.answerbag.com\/q_view\/730178'>here<\/a>).   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 <a target=\"_blank\" href='http:\/\/www.youtube.com\/watch?v=eUKADwTqkBQ' title='My apologies' rel=\"noopener\"><strike>Bugs Bunny<\/strike><\/a> &#8230; down dog!<\/p>\n<p>Here is a link to some downloadable PHP programming source code which you might like to rename to <a target=\"_blank\" title='myjpgupload.php' href='http:\/\/www.rjmprogramming.com.au\/PHP\/Upload\/myjpgupload.php_GETME' rel=\"noopener\">myjpgupload.php<\/a><\/p>\n<p>Please think of this as a starting point for your further study of uploading and here is a good link for further study &#8230; <a target=\"_blank\" title='PHP File Upload advice from w3schools' href='http:\/\/www.w3schools.com\/php\/php_file_upload.asp' rel=\"noopener\">PHP File Upload<\/a>.<\/p>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d3937' onclick='var dv=document.getElementById(\"d3937\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"http:\/\/www.rjmprogramming.com.au\/wordpress\/?cat=64#content\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d3937' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n<hr>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d64226' onclick='var dv=document.getElementById(\"d64226\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/upload\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d64226' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Perhaps our PHP Upload Primer Tutorial shows us a little &#8220;green around the gills&#8221; regarding &#8220;uploading&#8221;. Let&#8217;s face it, there is quite a bit more malicious activity going on with the net that means the discussion back then did not &hellip; <a href=\"https:\/\/www.rjmprogramming.com.au\/ITblog\/php-upload-security-tutorial\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,14,29,37],"tags":[4832,113,1993,3531,2150,257,4833,3574,405,1797,418,421,2655,425,4834,4835,452,4836,590,4837,2239,760,1668,2122,932,997,1872,4838,1114,3716,1319,1343,4839,1369,1411],"class_list":["post-64214","post","type-post","status-publish","format-standard","hentry","category-elearning","category-event-driven-programming","category-operating-system","category-tutorials","tag-accept","tag-audio","tag-browse","tag-browsing","tag-capture","tag-content","tag-content-generator","tag-dialog-box","tag-exec","tag-extension","tag-file","tag-file-browsing","tag-file-extension","tag-file-size","tag-finfo_file","tag-finfo_open","tag-form","tag-getimagesize","tag-image","tag-malicious","tag-malware","tag-media","tag-mime-type","tag-moderation","tag-php","tag-programming","tag-rename","tag-renaming","tag-security","tag-serverside","tag-tutorial","tag-upload","tag-uploader","tag-video","tag-web-server"],"_links":{"self":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/64214"}],"collection":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/comments?post=64214"}],"version-history":[{"count":1,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/64214\/revisions"}],"predecessor-version":[{"id":64215,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/64214\/revisions\/64215"}],"wp:attachment":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/media?parent=64214"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/categories?post=64214"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/tags?post=64214"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}