ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

how to be secure with file uploads...

July 31, 2009 9:12pm

Subscribe [6]
  • #1 / Jul 31, 2009 9:12pm

    tomdelonge

    60 posts

    So, the administrator of the website will upload an image associated with a product. Where should those images go? Just in an images folder, right below the webroot, I’d guess.

    One thing I don’t understand at all is folder permissions. How do I make it so no one can mess with the folder, but I can upload to it?

    Some suggestions?

  • #2 / Jul 31, 2009 10:42pm

    richthegeek

    242 posts

    re file permissions, these permissions only affect actual users on the server - these can be connected by FTP or telnet/SSH, or actually on the machine physically (ie a techmonkey at your host). They do *not* apply to general web browsers, nor can I do an fwrite/touch to a file on your server.

    Typically Apache creates files with the username www-data, so if you want to be slightly more secure issue these two commands using SSH (or possibly FTP depending on your setup):

    chown -R www-data .
    chmod -R 755 .

    That will set the owner of the current folder and all its files to be www-data, and the file permissions to 755 (so only www-data has “write” access)

  • #3 / Jul 31, 2009 11:36pm

    tomdelonge

    60 posts

    So what precautions do I need to take? Just setting folder permissions?

  • #4 / Aug 01, 2009 2:12am

    charlie spider

    125 posts

    this has nothing to do with folder permissions, but for security purposes i hide the uploaded file by creating a directory with a randomized name, then store the randomized folder name in the db with the other file details.

    here’s a stripped down example:

    $config['upload_path'] = '../file_uploads/';  // below root - or is that above root ??? i can never remember :\
    $config['encrypt_name'] = TRUE; // this will actually become the folder name
    
    $this->load->library('upload', $config);
    
    if ( $this->upload->do_upload() )
    {
    
        $upload_data = $this->upload->data();
        foreach( $upload_data as $item => $value ) { $filedata[$item] = $value; }
    
        $keys_n_values = array
        ( 
            'file_ID' => 0,
            'local_path' => $filedata['file_path'],
            'orig_filename' => $filedata['orig_name'],
            'md5_dir' => $filedata['raw_name'] . '/',
            'ext' => $filedata['file_ext'],
            'size' => $filedata['file_size'],
        );
        $table = 'file_upload';
    
        $this->File_model->insert($keys_n_values, $table) )    //  inserts the array of details into their respective fields in the db.  
    
        $new_path = $filedata['file_path'] . $filedata['raw_name']; // the upload path + the random encrypted name that CI generates
        
        if( mkdir($new_path) )
                rename( $filedata['full_path'], $new_path . '/' . $filedata['orig_name']); // copies the uploaded file into the new folder and deletes the original uploaded file

    then to access the file you just grab the record from the db and use the mdr dir as part of the path. I usually md5 the filename too.

    i do the same thing for images, but to recall them i feed the image details to a script that gets the md5 filename and path from the db then streams the image to the browser, for example:

    to display an image i will use this in the view file:

    image/thm/image_name.jpg

    where:
    - image/ is a controller
    - thm/ stands for thumbnail (other sizes i use might be, erg for regular or full for, you guessed it, full sized images)
    - image_name.jpg is the original filename

    then the image controller looks something like this:

    class Image extends Controller 
    {
        function Image()
        {
            parent::Controller();  
        $this->load->database();
        }
    
        function _remap()
        {
            if ( $pic_size = '_' . $this->uri->segment(2) )
            {
                $orig_file = $this->uri->segment(3);
                
                $orig_file = substr($orig_file, 0, strlen($orig_file)-4);
            
                $this->db->select('md5_filename, ext');
                $this->db->from('asset');
                $this->db->where('orig_file', $orig_file);
                $query = $this->db->get();
                if ($query->num_rows() > 0)
                {
                    foreach ($query->result() as $row)
                    {
                        $filename = $row -> md5_filename;
                        $ext = strtolower($row -> ext);
                    }
                    
                    $path_to_root = FCPATH;
                    $path_to_root = substr($path_to_root, 0, strlen($path_to_root)-10);
                     
                    $image = $path_to_root . '/assets/images/' . $filename . $pic_size . $ext;
                    
                    header('Content-Type: image/jpeg');
                    echo(file_get_contents($image));
                }
            }
        }
    }

    works pretty good
    would keep a hacker confused for a few minutes at least

  • #5 / Aug 01, 2009 7:25am

    jedd

    2089 posts

    On a *nix system, change permissions to 770 for the directory, and 660 for all files therein (assuming owner and group are sensible).

    I’d use UUID as the filename, and have a mapping in my files table back to the original filename.  This means you can have a single directory containing all files (if you have a broken file system you can easily map that down to first four chars of the UUID, say, as sub-directories).  md5sum is slightly more expensive than UUID, but my bigger concern there is it breaks if you offer your users the option to replace extant files.  With UUID they keep the same identifier, with MD5 they will change.  Of course, you may in fact prefer the latter approach.

    For security I’d just put my file store outside of the web root - this seems a lot easier than wrapping lumps of code around the problem.  If you want it in the web root (and really, that’s what I end up doing just for portability’s sake) stick an empty index.html in that directory and you’re pretty much set.  The only filenames they can pick (using the UUID method above) are ones that they’ve already been exposed to, and presumably you don’t mind users accessing files that they’ve previously been allowed to access.

  • #6 / Aug 03, 2009 1:31pm

    shawnhenry

    1 posts

    PHP makes uploading files easy. You can upload any type of file to your Web server. But with ease comes danger and you should be careful when allowing file uploads.

    In spite of security issues that should be addressed before enabling file uploads, the actual mechanisms to allow this are straight forward. In this tutorial we will consider how to upload files to some directory on your Web server. We will also discuss security issues concerned with the file uploading.

  • #7 / Aug 03, 2009 1:45pm

    Wuushu

    103 posts

    PHP makes uploading files easy. You can upload any type of file to your Web server. But with ease comes danger and you should be careful when allowing file uploads.

    In spite of security issues that should be addressed before enabling file uploads, the actual mechanisms to allow this are straight forward. In this tutorial we will consider how to upload files to some directory on your Web server. We will also discuss security issues concerned with the file uploading.

    What tutorial.. ?

  • #8 / Aug 03, 2009 10:12pm

    devbro

    81 posts

    PHP makes uploading files easy. You can upload any type of file to your Web server. But with ease comes danger and you should be careful when allowing file uploads.

    In spite of security issues that should be addressed before enabling file uploads, the actual mechanisms to allow this are straight forward. In this tutorial we will consider how to upload files to some directory on your Web server. We will also discuss security issues concerned with the file uploading.

    What tutorial.. ?

    there are a lot of tutorial for file upload. just check the upload class for one 😊.

    I also have one more suggestion that can be useful. if you have access to .htaccess disable all types of executions in your upload folder, so if a php file is in your upload folder it would spit out the code.same for .pl .cgi and other stuff.

    this way even if they manage to upload something dangerous to your server it will no be executed at all.

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases