Welcome Guest, Not a member yet? Register   Sign In
how to be secure with file uploads...
#1

[eluser]tomdelonge[/eluser]
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

[eluser]richthegeek[/eluser]
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):
Code:
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

[eluser]tomdelonge[/eluser]
So what precautions do I need to take? Just setting folder permissions?
#4

[eluser]charlie spider[/eluser]
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:

Code:
$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:

Code:
<img src="image/thm/image_name.jpg"  alt="blah blah" title="image" />

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:

Code:
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

[eluser]jedd[/eluser]
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

[eluser]Unknown[/eluser]
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

[eluser]Wuushu[/eluser]
[quote author="shawnhenry" date="1249335072"]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.[/quote]

What tutorial.. ?
#8

[eluser]devbro[/eluser]
[quote author="Wuushu" date="1249335948"][quote author="shawnhenry" date="1249335072"]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.[/quote]

What tutorial.. ?[/quote]

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

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.




Theme © iAndrew 2016 - Forum software by © MyBB