PHP file uploading security - php

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

Related

using PHP to remove the extension from a file and then downloading it

I recently had a asked a question very similar to this one, however after evaluating that I did not explain it in the best way I have come back once again explaining it in a greater manner.
So, I am creating a system that will gather data from a MySQL database and use a unique id to download a file, however depending on the value of a column within that database called type, this file could be anything from a png file to an xml file. What I am currently doing is trying to download these files WITHOUT any extension.
As an example to maybe make this easier to understand, a file named image.png would be converted to just image and then downloaded.
With this you could rename the file to image.png again on the local machine and view the image.
This may seem very inefficient to most reading this but for my current situation it's all that will work.
How could I remove a files extension and then download it? (in php)
Thank you in advance.
Just use headers to specify response type.
$filepath = '/wherever/the/file/is.png';
$filename = 'new-cool-name';
header('Content-Type: whatever/content-type-is');
header("Content-disposition: attachment;filename=$filename");
readfile($filepath);
This basically sends a response with specified content-type as an attachment and the body of the attachment contains the file contents. If you never sure what's the content type is, then just use application/octet-stream
Usually when you set out to push a file for downloading from a serverside script, you do so by utilizing http headers like https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
The filename of the downloadable file is specified in that header
Okay so to remove an extention from a file you could do is
$withoutExtion = preg_replace('/\\.[^.\\s]{3,4}$/', '', $youfilename);
...followed by your file download code

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');
?>

Restriction so only the relevant uploader can download their files

im building a small website that allows users to upload and download their personal files from a server. Codeigniter is being used for the project and im using the file uploading class to upload the files.
the problem that is arrised is how do i make sure that only the person who has uploaded the file can download it. currently all the files are uploaded to localhost/curious/uploads. although the files are visible only for the person who uploads, if they share the upload link anyone can download the file.
so if Steve uploads a file called secure_rom.doc and the path is localhost/curious/uploads/secure_rom.doc that file can be downloaded by anyone who has that link.
how is it possible make sure only the uploader can download from the download area and not anyone else?
You can use a download script (try to adapt with codeigniter)
1) Check if the user is logged
2) Set the header with the file name and the content type
3) Read the file and send it to the client !
Controller :
if($userConnected) {
header('Content-disposition: attachment; filename=' . $file_name);
header('Content-type: ' . $file_mime);
$file_content = file_get_contents($file_location);
echo $file_content;
}
else
echo 'No permission !';
Mime content function
Easy Way
-just store the 'id' of the user when he/she uploaded something.
- hide the URL if 'user_id' is different.
- adding random character will have in securing.

Check File Upload extension (PHP/Jquery/Javascript)

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....

How to force a file to download in PHP

I have list of images and I want a "Download" link along with every image so that user can download the image.
so can someone guide me How to Provide Download link for any file in php?
EDIT
I want a download panel to be displayed on clicking the download link I dont want to navigate to image to be displayed on the browser
If you want to force a download, you can use something like the following:
<?php
// Fetch the file info.
$filePath = '/path/to/file/on/disk.jpg';
if(file_exists($filePath)) {
$fileName = basename($filePath);
$fileSize = filesize($filePath);
// Output headers.
header("Cache-Control: private");
header("Content-Type: application/stream");
header("Content-Length: ".$fileSize);
header("Content-Disposition: attachment; filename=".$fileName);
// Output file.
readfile ($filePath);
exit();
}
else {
die('The provided file path is not valid.');
}
?>
If you simply link to this script using a normal link the file will be downloaded.
Incidentally, the code snippet above needs to be executed at the start of a page (before any headers or HTML output had occurred.) Also take care if you decide to create a function based around this for downloading arbitrary files - you'll need to ensure that you prevent directory traversal (realpath is handy), only permit downloads from within a defined area, etc. if you're accepting input from a $_GET or $_POST.
In HTML5 download attribute of <a> tag can be used:
echo '<a href="path/to/file" download>Download</a>';
This attribute is only used if the href attribute is set.
There are no restrictions on allowed values, and the browser will
automatically detect the correct file extension and add it to the file
(.img, .pdf, .txt, .html, etc.).
Read more here.
The solution is easier that you think ;) Simple use:
header('Content-Disposition: attachment');
And that's all. Facebook for example does the same.
You can do this in .htaccess and specify for different file extensions. It's sometimes easier to do this than hard-coding into the application.
<FilesMatch "\.(?i:pdf)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
By the way, you might need to clear browser cache before it works correctly.

Categories