OK, pls dont flame me if this is really dumb, but I dont think it is, I maybe just havent articulated it that well...

How to do secure file uploads with php? Or, more correctly, how to upload to a secured dir? Many apps and posts I have seen on the web advise that the target dir must be writable. Now, this is ok if I am the owner of the dir, but what about if I want my users to be able to e.g. upload an image? Unless I authenticate them as an ftp user on the system, with access to the folder, the folder must be chmod 777, which is highly insecure. If I am using a shared host, which many of us are, it is not feasible for me to create an ftp login for all my users. I use session based security, and require sessions for all uploads, but if the folder is 777, anyone can just come along and browse it, and more importantly, bypass the session and write to it.
htaccess is not really suitable in my situation either, as it will use the browser popup for auth, rather than my login system and this is not consistent with the rest of the site. Once someone has logged into my site (i.e. authenticated against my db, and got a session/cookie), they should be logged in to all the areas they require access too. And how to maintain password resets etc between the db AND the htpasswd file?
Is there a way for me to use something like ftp_connect, or cURL to open a connection, possibly as a ftp user who only has access to this folder, and do some stuff like fopen(); fwrite(): or imagejpeg(); whilst the connection is open, and then close that connection?

thanks in advance!
ben

    If your site is hosted https then whatever a user POSTs to your site will be encrypted. This would require that you buy a cert for your site. Or you could generate one yourself using openssl but visitors to the securely hosted pages would get warnings in their browser about the certificate not being validated. In either case, the data would be encrypted in transit from browser to server.

    The trick to preventing users from going directly to a particular file that has been uploaded is to feed it to users through a php page that
    1) checks the session to make sure a user has permission
    2) acts as a proxy to deliver the file using something like [man]readfile[/man]

    the files would ideally be stored outside of the web root so there's absolutely no way for users to get at the file by typing in some url. it has to be fed to them through PHP or cgi or something.

    that php file might look something like this:

    define('SECRET_IMAGE_LOCATION', '/var/www/secretImageFolder'; // ideally this is outside your web root so it's not available through apache
    $imageName = $_GET["imageName"];
    if(empty($imageName)) {
      die('empty image name'); // given that people don't directly visit this page (it's displayed in an <IMG> tag) you might want to output an error image instead;
    }
    
    if (!file_exists(SECRET_IMAGE_LOCATION.$imageName)) {
      die('file does not exist'); // see prev comment
    }
    
    if (notPermitted()) {
      die('you are not allowed!'); error image here?
    }
    $output = imagecreatefromjpeg(SECRET_IMAGE_LOCATION.$imageName);
    imagejpeg($output, "", 100);
    imagedestroy($output);
    

    something to keep in mind is that if apache is going to read and write the file, then it's going to have all the permissions needed to read and write the file. 777 or 770 or whatever is kind of irrelevant.

    also, you might want to send a header indicating a mime type or something.

    EDIT: fixed some syntax errors involving quotes and changed the comment

      The files when uploaded with PHP have the user and group set to what the webserver is running under (www-data, etc), so if you do a chmod 750 after the upload, only apache/PHP will be able to read the file from the system shell, I assume this is what you are referring to?

        Remember that the "world writeable" bit in Unix filesystem permissions only applies to users who have the means to write to the file in the first place.

        Arbitrary users can't write to it. They can't even read it if it's outside the web root or the web server denies access.

        If you're on shared hosting, all security bets are off. Anyone can do anything by simply compromising the box from one of the other dodgy web apps you share hosting with - or at a push, and attacker can simply sign up for their own account with the hosting provider, get a shared account, then using a dodgy web app gain access to your service. There is nothing much you can do about this - get dedicated hosting if you care (at all) about security.

        Mark

          thank you all for your illuminating comments!! thanks for sharing yr knowledge!! really helpful for my current issue.

            Write a Reply...