Secure image upload in php -
i making image upload function can re-use in code, has 100% secure. please tell me if can spot , security wholes in initial code;
function upload($file) { list($width,$height,$type,$attr) = getimagesize($file); $mime = image_type_to_mime_type($type); if(($mime != "image/jpeg") && ($mime != "image/pjpeg") && ($mime != "image/png")) { return 'error3: upload file type un-recognized. .jpg or .png images allowed'; }else{ $newname = md5('sillysalt'.time()); if (move_uploaded_file($file, 'images/'.$newname.$type)) { return 'uploaded!'; }else{ return 'server error!'; } } }
thanks!
update; how far i've gotten , research, please tell me think. don't mind speed, me it's being 100% secure, or close to.
function upload($file) { list($width,$height,$type,$attr) = getimagesize($file); $mime = image_type_to_mime_type($type); $folder = 'images/'; // mime checks add layer of security keeps out less sophisticated attackers if(($mime != "image/jpeg") && ($mime != "image/pjpeg") && ($mime != "image/png")) { return 'error3: upload file type un-recognized. .jpg or .png images allowed'; }else{ // if file has no width not valid image if(!$width) { $newname = md5('sillysalt'.time()); $finfo = finfo_open(fileinfo_mime_type); $mime2 = finfo_file($finfo, $folder.$newname); // should remove second mime check? since info comes form same spoofable source in image if(($mime != "image/jpeg") && ($mime != "image/pjpeg") && ($mime != "image/png")) { $filetype = exif_imagetype($file); $allowed = array(imagetype_jpeg, imagetype_png); if(!in_array($filetype, $allowed)) { // don't overwrite existing file $i = 0; $parts = pathinfo($file); while(file_exists($folder . $name)) { $i++; $name = $newname."-".$i.".".$parts["extension"]; } if(move_uploaded_file($file, $folder.$name)) { // set permissions file chmod($name, 0644); return 'uploaded!'; }else{ return 'server error!'; } } } } } }
thanks again!
as long don't use fileinfo
(http://www.php.net/manual/en/ref.fileinfo.php) extensions php check mime type, function not secure @ (think later you'll want upload pdf's, excels, etc).
also, md5 on md5 nothing increasing collision chances.
l.e: something simple following should it:
function getextensiontomimetypemapping() { return array( 'ai'=>'application/postscript', 'aif'=>'audio/x-aiff', 'aifc'=>'audio/x-aiff', 'aiff'=>'audio/x-aiff', 'anx'=>'application/annodex', 'asc'=>'text/plain', 'au'=>'audio/basic', 'avi'=>'video/x-msvideo', 'axa'=>'audio/annodex', 'axv'=>'video/annodex', 'bcpio'=>'application/x-bcpio', 'bin'=>'application/octet-stream', 'bmp'=>'image/bmp', 'c'=>'text/plain', 'cc'=>'text/plain', 'ccad'=>'application/clariscad', 'cdf'=>'application/x-netcdf', 'class'=>'application/octet-stream', 'cpio'=>'application/x-cpio', 'cpt'=>'application/mac-compactpro', 'csh'=>'application/x-csh', 'css'=>'text/css', 'csv'=>'text/csv', 'dcr'=>'application/x-director', 'dir'=>'application/x-director', 'dms'=>'application/octet-stream', 'doc'=>'application/msword', 'drw'=>'application/drafting', 'dvi'=>'application/x-dvi', 'dwg'=>'application/acad', 'dxf'=>'application/dxf', 'dxr'=>'application/x-director', 'eps'=>'application/postscript', 'etx'=>'text/x-setext', 'exe'=>'application/octet-stream', 'ez'=>'application/andrew-inset', 'f'=>'text/plain', 'f90'=>'text/plain', 'flac'=>'audio/flac', 'fli'=>'video/x-fli', 'flv'=>'video/x-flv', 'gif'=>'image/gif', 'gtar'=>'application/x-gtar', 'gz'=>'application/x-gzip', 'h'=>'text/plain', 'hdf'=>'application/x-hdf', 'hh'=>'text/plain', 'hqx'=>'application/mac-binhex40', 'htm'=>'text/html', 'html'=>'text/html', 'ice'=>'x-conference/x-cooltalk', 'ief'=>'image/ief', 'iges'=>'model/iges', 'igs'=>'model/iges', 'ips'=>'application/x-ipscript', 'ipx'=>'application/x-ipix', 'jpe'=>'image/jpeg', 'jpeg'=>'image/jpeg', 'jpg'=>'image/jpeg', 'js'=>'application/x-javascript', 'kar'=>'audio/midi', 'latex'=>'application/x-latex', 'lha'=>'application/octet-stream', 'lsp'=>'application/x-lisp', 'lzh'=>'application/octet-stream', 'm'=>'text/plain', 'man'=>'application/x-troff-man', 'me'=>'application/x-troff-me', 'mesh'=>'model/mesh', 'mid'=>'audio/midi', 'midi'=>'audio/midi', 'mif'=>'application/vnd.mif', 'mime'=>'www/mime', 'mov'=>'video/quicktime', 'movie'=>'video/x-sgi-movie', 'mp2'=>'audio/mpeg', 'mp3'=>'audio/mpeg', 'mpe'=>'video/mpeg', 'mpeg'=>'video/mpeg', 'mpg'=>'video/mpeg', 'mpga'=>'audio/mpeg', 'ms'=>'application/x-troff-ms', 'msh'=>'model/mesh', 'nc'=>'application/x-netcdf', 'oga'=>'audio/ogg', 'ogg'=>'audio/ogg', 'ogv'=>'video/ogg', 'ogx'=>'application/ogg', 'oda'=>'application/oda', 'pbm'=>'image/x-portable-bitmap', 'pdb'=>'chemical/x-pdb', 'pdf'=>'application/pdf', 'pgm'=>'image/x-portable-graymap', 'pgn'=>'application/x-chess-pgn', 'png'=>'image/png', 'pnm'=>'image/x-portable-anymap', 'pot'=>'application/mspowerpoint', 'ppm'=>'image/x-portable-pixmap', 'pps'=>'application/mspowerpoint', 'ppt'=>'application/mspowerpoint', 'ppz'=>'application/mspowerpoint', 'pre'=>'application/x-freelance', 'prt'=>'application/pro_eng', 'ps'=>'application/postscript', 'qt'=>'video/quicktime', 'ra'=>'audio/x-realaudio', 'ram'=>'audio/x-pn-realaudio', 'ras'=>'image/cmu-raster', 'rgb'=>'image/x-rgb', 'rm'=>'audio/x-pn-realaudio', 'roff'=>'application/x-troff', 'rpm'=>'audio/x-pn-realaudio-plugin', 'rtf'=>'text/rtf', 'rtx'=>'text/richtext', 'scm'=>'application/x-lotusscreencam', 'set'=>'application/set', 'sgm'=>'text/sgml', 'sgml'=>'text/sgml', 'sh'=>'application/x-sh', 'shar'=>'application/x-shar', 'silo'=>'model/mesh', 'sit'=>'application/x-stuffit', 'skd'=>'application/x-koan', 'skm'=>'application/x-koan', 'skp'=>'application/x-koan', 'skt'=>'application/x-koan', 'smi'=>'application/smil', 'smil'=>'application/smil', 'snd'=>'audio/basic', 'sol'=>'application/solids', 'spl'=>'application/x-futuresplash', 'spx'=>'audio/ogg', 'src'=>'application/x-wais-source', 'step'=>'application/step', 'stl'=>'application/sla', 'stp'=>'application/step', 'sv4cpio'=>'application/x-sv4cpio', 'sv4crc'=>'application/x-sv4crc', 'swf'=>'application/x-shockwave-flash', 't'=>'application/x-troff', 'tar'=>'application/x-tar', 'tcl'=>'application/x-tcl', 'tex'=>'application/x-tex', 'texi'=>'application/x-texinfo', 'texinfo'=>'application/x-texinfo', 'tif'=>'image/tiff', 'tiff'=>'image/tiff', 'tr'=>'application/x-troff', 'tsi'=>'audio/tsp-audio', 'tsp'=>'application/dsptype', 'tsv'=>'text/tab-separated-values', 'txt'=>'text/plain', 'unv'=>'application/i-deas', 'ustar'=>'application/x-ustar', 'vcd'=>'application/x-cdlink', 'vda'=>'application/vda', 'viv'=>'video/vnd.vivo', 'vivo'=>'video/vnd.vivo', 'vrml'=>'model/vrml', 'wav'=>'audio/x-wav', 'wrl'=>'model/vrml', 'xbm'=>'image/x-xbitmap', 'xlc'=>'application/vnd.ms-excel', 'xll'=>'application/vnd.ms-excel', 'xlm'=>'application/vnd.ms-excel', 'xls'=>'application/vnd.ms-excel', 'xlw'=>'application/vnd.ms-excel', 'xml'=>'application/xml', 'xpm'=>'image/x-xpixmap', 'xspf'=>'application/xspf+xml', 'xwd'=>'image/x-xwindowdump', 'xyz'=>'chemical/x-pdb', 'zip'=>'application/zip', ); } function getmimetype($filepath) { if (!is_file($filepath)) { return false; } $finfo = finfo_open(fileinfo_mime_type); $mime = finfo_file($finfo, $filepath); finfo_close($finfo); return $mime; } function upload($filepath, $destinationdir = 'images', array $allowedmimes = array()) { if (!is_file($filepath) || !is_dir($destinationdir)) { return false; } if (!($mime = getmimetype($filepath))) { return false; } if (!in_array($mime, $allowedmimes)) { return false; } $ext = null; $extmapping = getextensiontomimetypemapping(); foreach ($extmapping $extension => $mimetype) { if ($mimetype == $mime) { $ext = $extension; break; } } if (empty($ext)) { $ext = pathinfo($filepath, pathinfo_extension); } if (empty($ext)) { return false; } $filename = md5(uniqid(rand(0, time()), true)) . '.' . $ext; $newfilepath = $destinationdir.'/'.$filename; if(!rename($filepath, $newfilepath)) { return false; } return $filename; } // use if (isset($_files['something']['tmp_name'])) { $file = $_files['something']['tmp_name']; $storagepath = 'images'; // relative script, better use absolute path. $allowedmimes = array('image/png', 'image/jpg', 'image/gif', 'image/pjpeg'); $filename = upload($file, $storagepath, $allowedmimes); if (!$filename) { exit ('your file type not allowed.'); } else { // check if file image, optional, in case allow multiple types of files. // $imageinfo = @getimagesize($storagepath.'/'.$filename); exit ("your uploaded file {$filename} , can found @ {$storagepath}/{$filename}"); } }
Comments
Post a Comment