summaryrefslogtreecommitdiffstats
path: root/system/libraries
diff options
context:
space:
mode:
authorAndrey Andreev <narf@bofh.bg>2011-09-24 13:25:33 +0200
committerPhil Sturgeon <email@philsturgeon.co.uk>2011-10-27 00:33:17 +0200
commit6700b93c4d7a16e7288e4e2cd3223093926666ea (patch)
treea4af90e0186e845783d846d5ae3787068041711a /system/libraries
parent67bffa2237188d2cf1a84e8e540e352f458c5c66 (diff)
Added _file_mime_type() method to system/libraries/Upload.php in order to fix a possible MIME-type injection (issue #60)
Diffstat (limited to 'system/libraries')
-rw-r--r--system/libraries/Upload.php68
1 files changed, 66 insertions, 2 deletions
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 3177424c4..93f763ed9 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -196,7 +196,8 @@ class CI_Upload {
// Set the uploaded data as class variables
$this->file_temp = $_FILES[$field]['tmp_name'];
$this->file_size = $_FILES[$field]['size'];
- $this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$field]['type']);
+ $this->_file_mime_type($_FILES[$field]);
+ $this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $this->file_type);
$this->file_type = strtolower(trim(stripslashes($this->file_type), '"'));
$this->file_name = $this->_prep_filename($_FILES[$field]['name']);
$this->file_ext = $this->get_extension($this->file_name);
@@ -1006,8 +1007,71 @@ class CI_Upload {
// --------------------------------------------------------------------
+ /**
+ * File MIME type
+ *
+ * Detects the (actual) MIME type of the uploaded file, if possible.
+ * The input array is expected to be $_FILES[$field]
+ *
+ * @param array
+ * @return void
+ */
+ protected function _file_mime_type($file)
+ {
+ $file_type = '';
+
+ // Use if the Fileinfo extension, if available (only versions above 5.3 support the FILEINFO_MIME_TYPE flag)
+ if ( (float) substr(phpversion(), 0, 3) >= 5.3 && function_exists('finfo_file'))
+ {
+ $finfo = new finfo(FILEINFO_MIME_TYPE);
+ if ($finfo !== FALSE) // This is possible, if there is no magic MIME database file found on the system
+ {
+ $file_type = $finfo->file($file['tmp_name']);
+
+ /* According to the comments section of the PHP manual page,
+ * it is possible that this function returns an empty string
+ * for some files (e.g. if they don't exist in the magic MIME database.
+ */
+ if (strlen($file_type) > 1)
+ {
+ $this->file_type = $file_info;
+ return;
+ }
+ }
+ }
+
+ // Fall back to the deprecated mime_content_type(), if available
+ if (function_exists('mime_content_type'))
+ {
+ $this->file_type = @mime_content_type($file['tmp_name']);
+ return;
+ }
+
+ /* This is an ugly hack, but UNIX-type systems provide a native way to detect the file type,
+ * which is still more secure than depending on the value of $_FILES[$field]['type'].
+ *
+ * Notes:
+ * - a 'W' in the substr() expression bellow, would mean that we're using Windows
+ * - many system admins would disable the exec() function due to security concerns, hence the function_exists() check
+ */
+ if (substr(PHP_OS, 0, 1) !== 'W' && function_exists('exec'))
+ {
+ $output = array();
+ @exec('file --brief --mime-type ' . escapeshellarg($file['tmp_path']), $output, $return_code);
+ if ($return_code === 0 && strlen($output[0]) > 0) // A return status code != 0 would mean failed execution
+ {
+ $this->file_type = rtrim($output[0]);
+ return;
+ }
+ }
+
+ $this->file_type = $file['type'];
+ }
+
+ // --------------------------------------------------------------------
+
}
// END Upload Class
/* End of file Upload.php */
-/* Location: ./system/libraries/Upload.php */ \ No newline at end of file
+/* Location: ./system/libraries/Upload.php */