PHP uploader and htaccess password problems - php

I've got a rather baffling question/problem, let me lay it out for you.
I have two directories -- gallery and uploader
The uploader directory is htaccess password protected. This is where several PHP pages and the PHP file uploader reside. I enter my credentials when I access the index PHP file when I load a the index within the directory.
The problem is that the uploader is uploading the files and then moving it to the gallery directory (not password protected). It then runs other scripts to copy that image, resize it, then delete the original. This process works beautifully until I put the htaccess password on the uploader directory. So for some reason the PHP uploader in a protected directory can't move/work on the uploaded image and then copy it to the un-protected directory.
Any ideas of what I need to do? I'm not sure if the issue is the PHP uploader calling other scripts in the protected directory or if it's having troubles when moving it to the un-protected directory.
EDIT:
Here is some sample code and as you can see URLs aren't being used (nor are they in the resizeMyImageTN method).
//WHERE THE SAVE HAPPENS!
move_uploaded_file($_FILES['Filedata']['tmp_name'], '../../uploads/'.$folder.'/'.$new_index.'-' . $_FILES['Filedata']['name']);
//Call function to resize images pass in path
resizeMyImageTN($_FILES['Filedata']['name'],$folder, $new_index);
unlink('../../uploads/'.$folder.'/'.$new_index.'-' . $_FILES['Filedata']['name']);

.htaccess protection works at the webserver level. But, UNLESS you're using URLs in your various file-manipulation calls, the PHP script works at the filesystem level and would never see the .htaccess protection.
move_uploaded_file($_FILES['uploaded']['tmp_name'], '/some/dir/that/is/protected/newname.txt');
would not involve the HTTP layer, which means no protection. But if you were try
move_uploaded_file($_FILES['uploaded']['tmp_name'], 'http://myserver.com/newname.txt');
that would involve a new HTTP request, re-upload the file, and be subject to any URl restrictions in place on the server.
Without seeing some code, we most likely can't answer your question.

I forgot to answer this (my bad). In the end I could only get it to work by not having the upload directory .htaccess protected. Which wasn't ideal but I couldn't seem to figure anything else out. Since I asked this I have converted the site to Django and that has fixed all my problems.

Related

Redirect a user trying to download a .zip file to download.php?file=fileName in IIS

I need to prevent people from downloading .zip files in my server unless they are logged in. For this purpose and since I'm also using MediaWiki and I would like to have to modify the least this as I'm not familiar with it I was thinking about doing the following:
When a user wants to download a .zip file, it will be redirected by the server (with a web.config rule) to something like download.php?file=fileName and inside the PHP, I can do my programming to see if he's logged in and then use readFile() to give him the file.
However I'm not familiar with IIS (not much more with Apache either) and I'm totally clueless as how to write this rule. Could someone please help me out on this?
I'm also open to other suggestions. Putting the upload folder in a place not accessible to the public (but to the server) may do the trick but images are also uploaded then and then they wouldn't download. I could, again modify the behavior of the upload system myself but as it's done by MediaWiki I would prefer not to.
I have found this code (by using a .htaccess to web.config online translator) but it's not working. Maybe it's easier for you to just fix this code:
http://pastebin.com/waMJnFyK
The uploads are in subdirectories within /images like for example /images/a/ae/file.zip and I would like that when you try to open that you get redirected to a php file where as a GET input I have the file location.
Solution I took: http://pastebin.com/7skGT9uN
It redirects everything that ends in .zip within /images to download.php?fileName=whatever where the /images part is not passed.

Codeigniter captcha image cannot be written into captcha directory

I have created a login form with captcha image. It works well on my windows operating system. When I uploaded it to the server captcha image is not displayed. CI creates the image but cannot write it into captcha directory (CHMOD = 755) bacuse of permission settings. When I set CHMOD value of the directory to 777 (which I should not) it works well.
Here there is a question similar to mine but proposed and accepted answer is not secure, I guess.
How can I say CI to write the file that it created into the directory using ftp credentials on the fly or is there another way?
I am afraid of encountering further problems like file upload operations (like profile picture change, attachments to the announcements) by the users.
I got around the permission problem by not writing a file at all.
I modified the library in system/plugins/captcha_pi.php to return the image data for inline inclusion. The other return values are the same (timestamp and captcha phrase).
So instead of writing to a file, it returns the inline image content instead.

.htaccess for images only upload

I'm developing a very simple PHP upload feature in my site to permit users to upload JUST images. Apart from checking the mime-type through php I wanted a .htaccess file to rule what can be uploaded and what can't.
I want to insert the .htaccess in my root folder and from there writing the rules for all the folders I need to be ruled.
It's the first time I work with .htaccess and from the internet I was able to find this:
http://pastebin.com/0KNHEbw0
But it doesn't work. I'm testing it locally with my xampp on win7 and I see that I can upload any type of files in the "oggetti" folder.
What's that is wrong?
And then, to rule other folders should I write something like this?
http://pastebin.com/dFMUu1g0
Thank you in advance!
You can't control what files are uploaded through a .htaccess file: Apache, the web server parsing those commands, deals with serving the files only.
You will need to do these checks in the PHP script that handles the upload process. Note that checking the MIME type sent with the file is not a reliable method to determine a file's type! The value sent can be manipulated by an attacker. To ensure a file is an image file, you could e.g. use getimagesize().
This cannot be accomplished using .htaccess. I'm guessing what you're trying to do is prevent malicious scripts from accidentally being executed on the server. The way I normally handle file uploads like this is:
Insert filename, mime-type, etc., into a database with an auto_increment ID.
Use the ID as the file name - no extension, and place the file in a directory outside of your webroot. This way you're certain nobody can execute the file.
When a file is requested, query the database for filename mime-type and id, and send the file to the user with readfile() (follow the link for an example).

PHP - Question about uploading & uploaded image file

I have read the following tutorial "Uploading Files To the Server Using PHP"
and have several questions related to the topics.
Q1> The tutorial mentions that
"Note that PHP must have write access
to $uploadDir or else the upload will
fail"
For me, I only allow the user to upload the file after the user has login to the website.
If we set that $uploadDir permission as 777, then everyone can have written permission to that folder. How to avoid this problems?
Also I am using WAMP as my testing bed, can I simulate the same case as a real web server?
Q2> In order to prevent Preventing direct access, the tutorial mentions:
"A better approach is to move the
upload directory away from your web
root. For example, the web root for
this site is:
/home/arman198/public_html/ to prevent
direct listing i can set the upload
directory to /home/arman198/upload/."
Now my problem is that how can I display the uploaded images on other website pages. Since, the upload is not accessible directly anymore? I need to display the uploaded image save personal headshot dynamically on other website page. Is it possible?
Thank you
It's a common problem.
All modern computers have a temporary files directory. On Linux/Unix it's /tmp, on Windows it's usually c:\temp. The OS install will have set permissions on that directory so that anyone can write files there but only privileged users can delete files that don't belong to them. This is where PHP will want to put an uploaded file; your application then has to move it elsewhere (this is the purpose of the move_uploaded_file() function). PHP under Windows may need upload_tmp_dir actually set in the php.ini file.
Once you have an uploaded file, you can shift it whereever you like, including to where the webserver can read it to serve it. The biggest problem with that it is awfully easy to put this directory inside your codebase. Don't do that. As soon as you do anything beyond editing the files inside the directory they are served from, it will be problematic. Trust me: I've dealt with a few times this in code I've inherited. It's easy to let your webserver load files from a location outside your codebase.
The other alternative is to produce a download script. That way the file need not be servable by the webserver at all. One disadvantage is that you don't get to leverage the web server's MIME translation, but then, that lets you control which types of image files are permitted.
For the second question, you can use a PHP script intead of direct access to the directory. Lets name it image.php. Lets assume that it can take a parameter id, like image.php?id=image_id. In that file you can get the id using superglobal array $_GET. Then you can search for images with that Id and just send it as response.
First one I'm not sure, but maybe play with .htaccess file.
And for the first question, try setting your permissions to 775. That should allow PHP to write the file to the directory without giving the general public write access.

Storing and reading images above public_html

I am trying to secure my PHP Image upload script and the last hurdle I have to jump is making it so that users cannot directly excecute the images, but the server can still serve them in web pages. I tried changing ownership and permissions of the folders to no avail, so I am trying to store the images above public_html and display them in pages that are stored in public_html.
My File Structure:
- userimages
image.jpg
image2.jpg
- public_html
filetoserveimage.html
I tried linking to an image in the userimages folder like this:
<img src="../userimages/image.jpg">
But it does not work. Is there something I am missing here? If you have any better suggestions please let me know. I am trying to keep public users from executing potentially dangerous files they may have uploaded. Just as an extra security measure. Thanks!
You want something that's basically impossible.
The way a browser loads a page (in a very basic sense) is this:
Step 1: Download the page.
Step 2: Parse the page.
Step 3: Download anything referenced in the content of the page (images, stylesheets, javascripts, etc)
Each "Download" event is atomic.
It seems like you want to only serve images to people who have just downloaded a page that references those images.
As PHP Jedi illustrated, you can pass the files through PHP. You could expand on his code, and check the HTTP_REFERER on the request to ensure that people aren't grabbing "just" the image.
Now, serving every image through a PHP passthru script is not efficient, but it could work.
The most common reason people want to do this is to avoid "hotlinking" -- when people create image tags on other sites that reference the image on your server. When they do that, you expend resources handling requests that get presented on someone else's page.
If that's what you're really trying to avoid, you can use mod_rewrite to check the referer.
A decent-looking discussion of hotlinking/anti-hotlinking can be found here
Use an image relay script!
To serve a imagefile that is outside the public_html folder you would have to do it by a php script. E.g make a image-relay.php that reads the image that is outside the public html...
<?php
header('Content-Type: image/jpeg');
$_file = 'myimage.jpg'; // or $_GET['img']
echo file_get_contents('/myimages/'.$_file);
?>
Now, $_file could be a $_GET parameter, but its absolutley important to validate the input parameter...
now you can make an <img src="image-relay.php?img=flower.jpg"> to access a flower.jpg image that is located in /myimage/flower.jpg ...
Well, a web browser will only be able to access files and folders inside public_html.
If the public_html directory is the root of the server for your users, Apache cannot serve anything that is not inside/below that dorectory.
If you want a file to be served by Apache directly, you'll have to put it in/below public_html.
I think your misunderstanding is in the fact that if you include an image in an <img> tag, your browser will send the exact same request to the webserver to fetch it, that will be sent to the webserver if you try to open the src url of the image in your browser directly.
Therefore, either both things work, or neither.
There are hacks around, involving a (php or other) script to make sure that an IP that has requested the image has also requested the html page within the last few seconds (which will not work if the user is behind a proxy that rotates outgoing IPs) or by checking the referer (which does not work with HTTPs and also not if the user has referer disabled).
If you want to make sure that only some users can see the image (both via <img> tag and directly), you can put the image outside public_html and have a (php or other) script that verifies the user's credentials before serving the image.
If you are using Apache or lighttpd you can use the X-Sendfile header to send files that are not in the web root(provided you haven't changed the configuration of mod_xsendfile).
To learn more about X-sendfile see this site.
This solution is giving you the best possible performance as PHP doesn't send the file but the server does and therefore PHP can be exited while the files are being served.
Hope that helps.

Categories