I have uploaded some files on server. The link provided to me is pretty simple i-e; no signs/ symbols etc. If I provide the same link to the user for downloading the data, it might result in hacking of my server or loss of data. Now my question is how to encrypt this kind
www.hello.com/myApp/myFile.mp3
of url and provide the encrypted url to the user which the browser can understand.
Regards
Correct me if I misunderstand, but are you trying to prevent someone from downloading the file unless you tell them it's ok to download it?
Then the threat is that someone may find the file linked on a search engine or be able to guess it.
There are a few ways to make that threat less likely.
Make the url very long and unguessable. Simply rename the file to some random value could work. From the command line (linux)
echo http://example.com/file.mpe $(date) | md5sum
d8a5e8d341135379b8ad38f1d06970be
Or even easier, choose a random password from http://tooln.net/pw/ and rename the file to one of the passwords without symbols. Either is difficult to guess.
If you know the person, you could easily share a password and set a password on the directory. You can turn on passwords per directory through apache.
Turn off indexing of the site through robots.txt.
A URL can be encrypted, but if a browser can understand it, decrypting it would be a trivial process for a hacker. I'm assuming what you want to do is to prevent too many people from accessing your URL. To do this, you will have to have either some sort of user login system or an IP based limitation. Both of these would have to be backed by a database.
Instead of linking directly to the file, you would link to something like download.php?fileid=$some_file_id and in your database, you just insert the user ID (or IP address) and file ID every time the file is download. Then to display the file back to the user, you would check how many downloads of that file have been made by the user and if it is less than your threshold, e.g.:
SELECT COUNT(*) FROM downloads WHERE user = :user AND file_id = :id
Then get PHP to echo the contents of the file to the browser.
Add other clauses such as limiting it to X downloads in the past 24 hours, etc. or however you would like to work it.
Other things you could do would be storing the files outside the document root (or protecting direct access with .htaccess or similar), and including a hash of the file name in the link, so someone couldn't just do download.php?fileid=1 and guess the next one is download.php?fileid=2.
Related
i build a security script (not upload viruses s.e.) to upload images. I have now a question due to security of output the images on website.
Why this is not a security way to output the image:
<img src="/pathdir/imagerealname.jpg">
Why its better to make a script like photo.php and load original image as other name?
The URL that you use for your image isn't a problem. You can use whatever you want. The issue comes when you allow users to store files on disk that they name.
While it is possible to allow a user to upload a file directly to something like /users/username.jpg, you must take extra caution to ensure that they don't set up their naming in such a way that the file lands in the wrong place, or becomes executable.
For example, maybe someone's username is ../../../etc/init.d/somethingevil. You wouldn't want them putting scripts there. Or, maybe someone's username becomes evil.php, and then they can just call /users/evil.php and execute code on your servers.
Again, it is possible to set the file name to something the user provided, but then you have to do a bunch of checking to ensure it's fine.
There are also issues of usernames changing. You would need to protect against someone changing to a username that someone else previously had.
Now, back to your PHP script. What you could do is always write files to the hash of the username. For example, on disk you might have /var/www/images/users/B858CB282617FB0956D960215C8E84D1CCF909C6.jpg. And, you might have a rewrite rule that sets up all requests for /images/users/(.*) to go to /user-image.php. /user-image.php then hashes this username and actually outputs the contents of the image on disk. This also enables you to do things in your PHP script like resize that user image on-demand, via libvips or similar.
I need to deliver a file
example.com/realpathofthe/file.zip
to customers but I don't want to communicate the same URL to all customers (they could easily share URL to non-customers, and it would be difficult to track if the product is delivered or not). Instead, I'm generating a random string in PHP and want to share such URL:
example.com/download/djbf6xu83/file.zip
which will be different for each customer.
Question: should I generate symlinks for each customer to link the random string path to the path of the actual file on server?
Or use a RewriteRule in .htaccess for this? But then if done this way (ie rewrite /download/*/file.zip to the actual file), all random strings would link to the same file. This is not good because a non customer could generate a download link himself.
How to handle this correctly?
Note: I'd like to avoid if possible that PHP has to process the gigabytes of files data (through file_get_contents()) before delivering it. I thought (please correct me if I'm wrong) that it would be lighter for the server to let Apache distribute the file.
There can be many ways to approach this problem. Here's what I suggest.
Make a file, say /download.php and pass in a download code as an HTTP GET variable. So it'd say something like /download.php?code=abcdef, meanwhile generate and store codes for each customer in a database, and check if the code exists when someone opens download.php. Easy to track, and not creating a complex directory structure.
Hello everyone I was wondering if there's a way to have a random text generated and replaces my file names (and of course still have the link work) ?
I've noticed how people like to have files (mostly video) have very random characters as file names instead of a relevant file names. Are they generated as each user view the page? Or is it really a file with a name of random characters? I cannot imagine this can be efficient if you have large amounts of files.
I'm currently using the script from http://css-tricks.com/snippets/php/generate-expiring-amazon-s3-link/
This allows me to not share my files publicly but the users cannot access the file directly. I hope that makes sense, let me know what you think.
Thank you
As of today, you could probably use S3 Website Redirects to accomplish this.
Simply create a random new file with the correct HTTP header set, and have it redirect back to the real file. This uses an HTTP 301 redirect, so loading it in a web browser or requesting it with cURL or wget will end up resolving the real location.
I want to allow registered users of a website (PHP) to upload files (documents), which are going to be publicly available for download.
In this context, is the fact that I keep the file's original name a vulnerability ?
If it is one, I would like to know why, and how to get rid of it.
While this is an old question, it's surprisingly high on the list of search results when looking for 'security file names', so I'd like to expand on the existing answers:
Yes, it's almost surely a vulnerability.
There are several possible problems you might encounter if you try to store a file using its original filename:
the filename could be a reserved or special file name. What happens if a user uploads a file called .htaccess that tells the webserver to parse all .gif files as PHP, then uploads a .gif file with a GIF comment of <?php /* ... */ ?>?
the filename could contain ../. What happens if a user uploads a file with the 'name' ../../../../../etc/cron.d/foo? (This particular example should be caught by system permissions, but do you know all locations that your system reads configuration files from?)
if the user the web server runs as (let's call it www-data) is misconfigured and has a shell, how about ../../../../../home/www-data/.ssh/authorized_keys? (Again, this particular example should be guarded against by SSH itself (and possibly the folder not existing), since the authorized_keys file needs very particular file permissions; but if your system is set up to give restrictive file permissions by default (tricky!), then that won't be the problem.)
the filename could contain the x00 byte, or control characters. System programs may not respond to these as expected - e.g. a simple ls -al | cat (not that I know why you'd want to execute that, but a more complex script might contain a sequence that ultimately boils down to this) might execute commands.
the filename could end in .php and be executed once someone tries to download the file. (Don't try blacklisting extensions.)
The way to handle this is to roll the filenames yourself (e.g. md5() on the file contents or the original filename). If you absolutely must allow the original filename to best of your ability, whitelist the file extension, mime-type check the file, and whitelist what characters can be used in the filename.
Alternatively, you can roll the filename yourself when you store the file and for use in the URL that people use to download the file (although if this is a file-serving script, you should avoid letting people specify filenames here, anyway, so no one downloads your ../../../../../etc/passwd or other files of interest), but keep the original filename stored in the database for display somewhere. In this case, you only have SQL injection and XSS to worry about, which is ground that the other answers have already covered.
That depends where you store the filename. If you store the name in a database, in strictly typed variable, then HTML encode before you display it on a web page, there won't be any issues.
The name of the files could reveal potentially sensitive information. Some companies/people use different naming conventions for documents, so you might end up with :
Author name ( court-order-john.smith.doc )
Company name ( sensitive-information-enterprisename.doc )
File creation date ( letter.2012-03-29.pdf )
I think you get the point, you can probably think of some other information people use in their filenames.
Depending on what your site is about this could become an issue (consider if wikileaks published leaked documents that had the original source somewhere inside the filename).
If you decide to hide the filename, you must consider the problem of somebody submitting an executable as a document, and how you make sure people know what they are downloading.
I have a topic/question concerning your upload filename standards, if any, that you are using. Imagine you have an application that allows many types of documents to be uploaded to your server and placed into a directory. Perhaps the same document could even be uploaded twice. Usually, you have to make some kind of unique filename adjustment when saving the document. Assume it is saved in a directory, not saved directly into a database. Of course, the Meta Data would probably need to be saved into the database. Perhaps the typical PHP upload methods could be the application used; simple enough to do.
Possible Filenaming Standard:
1.) Append the document filename with a unique id: image.png changed to image_20110924_ahd74vdjd3.png
2.) Perhaps use a UUID/GUID and store the actual file type (meta) in a database: 2dea72e0-a341-11e0-bdc3-721d3cd780fb
3.) Perhaps a combination: image_2dea72e0-a341-11e0-bdc3-721d3cd780fb.png
Can you recommend a good standard approach?
Thanks, Jeff
I always just hash the file using md5() or sha1() and use that as a filename.
E.g.
3059e384f1edbacc3a66e35d8a4b88e5.ext
And I would save the original filename in the database may I ever need it.
This will make the filename unique AND it makes sure you don't have the same file multiple times on your server (since they would have the same hash).
EDIT
As you can see I had some discussion with zerkms about my solution and he raised some valid points.
I would always serve the file through PHP instead of letting user download them directly.
This has some advantages:
I would add records into the database if users upload a file. This would contain the user who uploaded the file, the original filename and tha hash of the file.
If a user wants to delete a file you just delete the record of the user with that file.
If no more users has the file after delete you can delete the file itself (or keep it anyway).
You should not keep the files somewhere in the document root, but rather somewhere else where it isn't accessible by the public and serve the file using PHP to the user.
A disadvantage as zerkms has pointed out is that serving files through PHP is more resource consuming, although I find the advantages to be worth the extra resources.
Another thing zerkms has pointed out is that the extension isn't really needed when saving the file as hash (since it already is in the database), but I always like to know what kind of files are in the directory by simply doing a ls -la for example. However again it isn't really necessarily.