views:

55

answers:

2

Hey there.

I'm currently working on a file uploading sript in PHP, but i'm kind of stuck. Users are allowed to upload files such as PHP and JS, but i don't want the scripts to run when a user is trying to download them. Is it possible to block that somehow using htaccess or something?

Thanks in advance.

A: 

You can change the file extension of the uploads, like

my-file.php.txt
my-file.js.txt

Assuming that .txt files don´t get processed by php on your server...

jeroen
Aaaah, good idea. Is there any smart way to check if a file contains plain text? Like a .php or a .js file? Cause i wont need to rename all exstensions such as .txt or .jpg..
Nike
I don´t know if there's a real reliable way, but you can easily see what extensions your web-server will process as php, so these extensions and for example .js should be enough.
jeroen
Well that's not a good idea either, cause there are other scripts than PHP that can be run. So if a user uploads a JS script it will run. Another way would be to grab the uploaded file exstention and then compare it to a list of scriptfile-exstentions and if it match, add ".txt" to the filename? I am however having problems finding a list.
Nike
No, it doesn´t matter what scripts can be run: What matters is what scripts your server will process before sending the output to the browser. For example a .js file will display in Firefox and trigger a download dialog in IE, just enter any url to a .js file on your server.
jeroen
+1  A: 

You can write a wrapper php file that sends the file content to the browser. But first you have to make sure that your uploaded files are stored outside the web root so that no one can access them via browser, unintentionally or otherwise.

The wrapper php script can go something along these lines:

<?php
    $f = $_GET[ "f" ];
    if ( filename_is_ok( $f ) && is_file( "../some_folder_outside_www/$f" ) )
    {
        header( "Content-Type: text/plain" );
        header( "Content-Disposition: attachment; filename=$f" );
        header( "Content-Length: " . filesize( "../some_folder_outside_www/$f" ) );
        readfile( "../some_folder_outside_www/$f" );
    }
    else
    {
        header("HTTP/1.0 404 Not Found");             
        echo "File not found (or you're not supposed to view this file)";
    }
    function filename_is_ok( $f )
    {
        // You'll have to implement it yourself
        return false;
    }
    // example calls:
    // http://website.com/download.php?f=test.php
    // http://website.com/download.php?f=test.js
?>
Salman A
Perfect!! I'll give it a shot.
Nike
Why was this downvoted? It seems like a good idea to me!
Josh
-1 because the script provided will allow any visitor to download any source file of your site by providing a simple URL (ie. f=../your_webroot_folder/index.php). You have to sanitize the input first (to prevent visitors from escaping out of the folder you specified). The idea behind the solution is ok, the implementation is insecure as hell...
wimvds
What happens if a user uploads an image for example? Will that be viewed in plain text?
Nike
Nvm the last comment. It works great!
Nike
wimvds has a point though. God it feels like i'm spamming now!
Nike
I'd solve the insecurity by creating a table that will contain at least an ID and the filename (either a full path or just the filename, depending on how you want to store the uploads). And pass the ID to the download script, that's about as safe as can be. You check first if the ID exists, if it does check if the file is still there and do a readfile, if the ID doesn't exist or the file is no longer there display an error message. But never ever put the script above online as-is!
wimvds
I already implemented that. Works great, thanks! :)
Nike
Why the downvote when I said "something along these lines"? The OP is supposed to add sensitization and permission checking.
Salman A