Check File Upload extension (PHP/Jquery/Javascript) - php

As title which of them is better and why? Any weaknesses from doing it?
I been hearing that Jquery/Javascript checking is bad and adviced to use PHP but somehow don't know why....
Need some recommend from any of you. Thanks in advance.
Anyone see if this is good or bad:
<input type="file" name="task_doc" class="task_doc" onChange="checkext();"/>
function checkext(){
var permittedFileType = ['pdf', 'doc', 'docx', 'xls', 'xlsx'];
var fext = $(".task_doc").val().split('.').pop().toLowerCase();
var resultFile = validate_filetype(fext, permittedFileType);
if(resultFile === false){
$(".task_doc").replaceWith("<input type='file' name='task_doc' class='task_doc' onChange='checkext();'>");
alert("Invalid Extension");
}
else{
alert("Success");
}
}
function validate_filetype(fext, ftype)
{
for(var num in ftype)
{
if(fext == ftype[num])
return true;
}
return false;
}

If you use only javascript to check for data-validity, advanced users will have the possibility of uploading any data they want.
On the other hand using javascript might be a convenient way for the user to get fast feedback, if his entered data (files in this case) is invalid.
So I suggest using both client side and server side scripts.

You have to assume that any outside data is tainted and could be malicious. A user could disable JavaScript and send any file they want. Or a user could send a file to the server and change the MIME type and/or extension to bypass checks on the server as well.
Your best bet is to make sure your server is set up to correctly handle the various MIME types and not by default parse unknown file types as PHP. In other words, don't set Apache to handle anything but .php files as PHP and block .php files from being uploaded at all. Handling file uploads is a sticky situation at best, security-wise. I would highly recommend saving uploads outside of your document root directory, renaming them to a random string that only you know (i.e. on upload store the random name in a database), then send the file via PHP to the browser.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($filename));
header('Content-Transfer-Encoding: binary');
readfile($filename);
I recommend doing this because storing them outside the document root prevents access, using a unique filename stops somebody from directly accessing it, and forcing a download (should) prevent any auto execution of a malicious file so hopefully the user's anti-virus could find it....

Related

How to download a file without an extension in PHP

I have a file with no extension on it, but I know it's a tiff. I want to be able to download this file via PHP.
I created a page with a link to another php page, which has the following content:
<?php
$imgPath = 'http://server/23700-b074137f-eb5c-45d6-87c2-13c96812345b';
header("Content-disposition: attachment; filename=invoice.tiff");
header("Content-type: image/tiff");
readfile($imgPath);
?>
When I click the link, I get a prompt to download invoice.tiff, but it's 0 bytes.
However, if I rename the file on the server to 23700-b074137f-eb5c-45d6-87c2-13c96812345b.tiff (and change the $imgPath), it works.
How do I accomplish this without renaming the file to include the extension?
It's possible the 'tiff' extension is registered as a known file type on the server, so when you rename and request the tiff it's permissions will allow you to open it. However, with no extension, the security is probably stopping you from reading it, as mentioned by 'Mike B' above. To check this try just entering the file name in your browser address bar and see if it opens, both with and without the 'tiff' extension. There is no workaround for getting past the security issue, short of changing the severs security which would be very bad.
You are retrieving the file from a URL, therefore activating the 'fopen wrappers' in readfile. In general, you should not do this, especially when working locally since it invokes a lot of unnecessary overhead and (in this case) unwanted 'magic' behaviour.
Just use readfile on the local path to the file, and it'll be fine, or use die(file_get_contents($imgPath)) instead of the last line to circumvent PHP's native behaviour.
It works for me:
$imgPath = 'http://server/23700-b074137f-eb5c-45d6-87c2-13c96812345b';
$f = fopen($imgPath, "r");
header("Content-disposition: attachment; filename=invoice.tiff");
header("Content-type: image/tiff");
fpassthru($f);
You should also add the content-length header like so:
// untested code
header('Content-Length: '.strlen(stream_get_contents($imgPath)));

Link to a PDF in html, the file has no extension, but I know it is pdf how to make it open appropriately

First post. I'm working on a project for a client where they have pdf files uploaded to a file structure (LAMP Stack) but the files have no extensions on them. Under the assumption that those files have to be PDF how would I get the browsers to understand that, and open them accordingly? Obviously with adding the file extensions this would suddenly work but I can't change the way their system works, it would result in too many changes and they are on a tight deadline. As for saving a temporary copy somewhere, I could do that, but I was hoping for a better solution. Is there a way to suggest to the browsers that they open a file a certain way?
Any thoughts guys/gals?
You just set the application type and file name in the headers, like so:
// This points to the file in question, note that it doesn't
// care whether it has an extension on the name or not.
$filePathOnDisk = '/path/to/your/pdffile';
// You can make this whatever you like, it doesn't have to
// be the same as the file name on the disk! This is the name of the file your end
// user will see when they are asked if they want to save. open, etc in the browser.
$fileName = 'file.pdf';
$data = file_get_contents($filePathOnDisk);
header("Content-type: application/pdf");
header("Content-disposition: attachment;filename=$fileName");
echo $data;
See PHP: stream remote pdf to client browser and Proper MIME media type for PDF files for reference as well.
Tested
You can use the following which will prompt the user to save the (PDF) file on their computer.
Notice the different file names.
One is the file that will be uploaded/prompted to the user download_example.pdf, while the other is the file without an extension as set in readfile('example');
<?php
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="download_example.pdf"');
readfile('example');
?>

PHP file uploading security

I use file extension for validate uploading file like word excel pdf etc.?
But if user change their file extension then they can upload any file they want.
I want to function that check type of file if user change their file extension after that they should not be able to upload file.
Can any one help
You should also check the mimetypes, for example:
$allowedMimes = array('image/gif', 'image/jpeg', 'image/jpg', 'image/png', 'image/bmp', 'image/wbmp');
//getting the mime type (it can be different from the extension) Be careful!
$imgInfo = getimagesize(imagePath);
$type = strtolower($imgInfo['mime']);
//hey dude!! This is a fake image!!
if(!in_array($type, $allowedMimes)){
//We delete it!!
unlink(imagePath);
}else{
//do whatever with the image...
}
You can find more info about mime types here.
To be safe
Move all the files regardless of type out of the webroot.
Dont allow direct access to the file, use a loader to send the file
to the user if you have a download feature.
Force the download
Have a script, download.php or whatever, get the file's ID, verify who is logged in, and if everything checks out, fetch the file, read it out to the browser, and send the appropriate download headers.
header('Content-type: application/octet-stream');
header('Content-disposition: attachment; filename=file.ext');
header("Content-Length: " . filesize('../not_in_web_root/file.ext'));
header("Content-Transfer-Encoding: binary");
readfile('../not_in_web_root/file.ext');
exit;
Only accept files you want to accept by checking the extension and mimetype where possible. Its
even ok to even accept php as long as you dont allow it to execute or give user direct access to it.
If your only allowing images then use a function like getimagesize(), if it has a size its an image, but still dont allow direct access to it as PHP maybe embedded into it.
If you offer a filesystem feature to your users, make it a virtual one, based on values within a database not access to the real files.
You could possibly look at the mime type of the file? http://us2.php.net/manual/en/fileinfo.constants.php

PHP Download not working with path coming from DB

I have a simple form that, when posted back, calls a function to initiate a download. The path and file name are pulled from the database then I'm using headers to start the download. My code for the download is:
//START DOWNLOAD
header('Content-type: "application/octet-stream"');
header('Content-Disposition: attachment; filename="'.$FILE_PATH.$FILE_NAME.'"');
header("Content-Transfer-Encoding: binary");
header("Connection: close")
In the example above, the $FILE_PATH variable is /downloads/software/ and the $FILE_NAME variable is client-installer.exe. So, what I would expect is a file called client-installer.exe (approximately 70MB) to be downloaded to the client. Instead, I get a file called _downloads_software_client-installer.exe and approximately 10KB.
I thought maybe I needed to urlencode the file path/name but that didn't fix the issue either. So I'm left thinking perhaps I have something wrong with the header but can't seem to find it.
Thank you!
The filename header just denotes what the file should be called. It must contain only a filename, not a path. The internal path on the server's hard disk is irrelevant and of no interest to the client. Your server will have to output the actual file data in the response, the client can't take it from the server given the path.
See readfile.

Is directly linking to an image okay for images uploaded to the server with a custom PHP script?

For an image file (JPEG) that has been uploaded to the server via a PHP script (to a directory such as http://www.somedomain.com/images, is it a good idea to allow the client to get the image's direct address (such as http://www.somedomain.com/images/someimage.jpg and paste it into a WYWSIWYG text editor (such as TinyMCE)?
I am wondering if there is a preferable method where the direct address is encrypted?
Please, if I should just link directly to the image, just say so.
Thanks!
Note: I have modified this question from my original. Please see revisions if you are curious, but I think I was asking the question incorrectly. My apologies to the people who already answered.
As long as you check correctly WHAT is being uploaded, it shouldn't be a problem. So please at least use getimagesize or a similar function to make sure it's an image that's being uploaded, AND make sure the extension on the file is correct so that it will never be run through the PHP interpreter - to prevent someone from uploading an image with a PHP script attached.
BTW Here's a nice whitepaper on uploads and security : http://www.scanit.be/uploads/php-file-upload.pdf
Depending on the CPU Constraints of your web-hosting service you can write a service to 'serve' the images to your users.
Here is some very BASIC code, it needs spiffing up and cleaning up for XSS/etc...
<?php
$basePath = "/path/to/my/image/store/not/web/accessible/";
$file = NULL;
if (isset($_GET['file']))
$file = $_GET['file'];
if ($file != NULL)
{
$path = $basePath . $file;
// $file needs to be checked for people
// trying to hack you, but for the sake of simplicity
// i've left it out
$mime = mime_content_type($path);
$size = filesize($path);
header("Content-Length: " . $size);
header("Content-Type: " . $mime);
header('Expires: 0');
readfile($path); // Outputs the file to the output buffer
}
?>
Obviously you can put whatever security checks in here you want. But this way your files are below the web dir, and you can apply logic to thier accesibility. This is typically used more for FILE vs. Images, but you can do the same thing here.
Images Accessed like this
http://www.mysite.com/image.php?file=hello.jpg
And you can use mod_rewrite to rewrite urls like this:
`http://www.mysite.com/images/hello.jpg
Into the first url.
I Cannot stress enough the need for further security checking in the above example, it was intended to show you how to serve a file to the user using PHP. Please don't copy & use this verbatim.
Wordpress uses direct links for images. The permalink function simply puts the image on a page along with metadata for comments, but the images' SRC attributes still link directly to the image.
why are you concerned about revealing your image location. Hotlinking?
if so you can prevent hotlinking with htaccess
http://altlab.com/htaccess_tutorial.html
Didn't you get your answer already?
Every site reveals image location to the browser. It's just the way web works.
Got any reason to "encrypt" original location?

Categories