OrchardCMS / Orchard

Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
https://orchardproject.net
BSD 3-Clause "New" or "Revised" License
2.38k stars 1.12k forks source link

Authorized media file access #3871

Open orchardbot opened 11 years ago

orchardbot commented 11 years ago

@Piedone created: https://orchard.codeplex.com/workitem/20043

Similarly to MediaUrl we could have an AuthorizedMediaUrl on MediaPart. This would point to an url that routes the file access through a controller action where content item permissions are checked for the media item. (This is only applicable to media items that have a corresponding local file naturally.)

This would need the followings to work:

The url of the real file behind the media item shouldn't be published, but this is up to the user.

To mask the relative path to the real file the arguments the action gets to locate the media item's file shouldn't include the real file path. The arguments need to include the (or an) Id of the item to locate it but this can't be the numerical ID alone, since we only want certain files to be accessible through the action (being able to fetch any media through a controller would cause a possible exploit for a DoS attack).

So this is what I propose: Media items should have a unique but not guessable ID associated to them (e.g. a GUID). Their corresponding files, if existing, can be fetched through a controller action that only needs this ID. With the help of the ID it fetches the media item, enforces corresponding permissions and returns the file named as the ID.

This is quite simple and would work with any media item without any further configuration and is developer friendly (because e.g. a media item shouldn't be set as "secret" by the user explicitly). However if the real path of the media is published or is guessable (i.e. the user doesn't know exactly how this all works) it can be circumvented.

To overcome this (but this is just thinking aloud) there could be further services built on top of this feature, e.g. a part that hides the real URL everywhere and swaps it with the authorized one together with storing the file under a random file name....

orchardbot commented 11 years ago

@bleroy commented:

We've been very careful to always maintain direct serving of media files by IIS. I will strongly oppose any effort to change that. The only way I can see this being acceptable is by having it be a new type of media (leave the default alone and universally served via IIS) that has its storage in a folder that is not served by IIS, and to then serve those files through a new route and controller action, using one of the stream file APIs in ASP.NET, that are not quite as fast as IIS alone but still pretty fast. This can of course be done as a separate module (one that would certainly have a significant audience), so there is no need to do this in core, at least for now.

orchardbot commented 11 years ago

@bleroy commented:

Also, security by obscurity? Tss.

orchardbot commented 11 years ago

@Piedone commented:

No need to oppose anything as my idea is about creating an alternative, optional way of serving certain files in an authorized manner.

What do you find security by obscurity here? The idea behind having real files under an unpublished route and thus enforcing their access through another authorized way is a standard practice employed by e.g. Google Drive or YouTube, where the password to an item is its URL (because it's not listed anywhere but if you know the URL, you can view the item). Nevertheless I don't find this ideal either, because as I've written, making this path like a password is something the user has to think about. To overcome this and have a separate folder that's content can't be accessed directly is much better.

I opened this issue also to gauge whether there would be a need for authorized media access, because if there is really significant audience, as you say, I don't see why this feature couldn't be built into the default media management (what has many features already).

orchardbot commented 11 years ago

@bleroy commented:

Security by obscurity: "Media items should have a unique but not guessable ID associated to them", "if the real path of the media is published or is guessable (i.e. the user doesn't know exactly how this all works) it can be circumvented", "storing the file under a random file name", and you added a new layer with "a standard practice employed by e.g. Google Drive or YouTube, where the password to an item is its URL (because it's not listed anywhere but if you know the URL, you can view the item)"

Trying to put permissions in front of media files is one thing, having "unlisted" media is another, very different thing. Google is not telling you that the unlisted videos are not accessible to unauthorized people, they are telling you that it won't appear in search results. The "unlisted" feature is not a security feature at all.

There are definitely quite a few people who would like to have media with permissions, and I encourage you to build it. It is not, however, a feature that almost all Orchard users would use, so it shouldn't go into core. I base this assertion on how often the question has been asked on forums since the creation of Orchard. From what I've seen, there are enough interested people for this to be a successful module, but not nearly enough to make it core. Also, lots of super-useful things started as modules (cache, taxonomies, etc.), so I don't see why this would be any different.

Cheers to building this as a module, with the reservations I formulated on implementation (i.e. the files must really not be accessible to unauthorized users). Don't interpret my reservations as gratuitous criticism, I'm really trying to help ;)

orchardbot commented 11 years ago

@Piedone commented:

No way I'm offended or something, thank you for your input!

As written having truly inaccessible media files would be much better, but I'm unsure how to approach it in a generic way: though the default IStorageProvider implementation uses local files where a Web.config would help to restrict access to a folder this won't work with all implementations. I'm not sure this is possible without changing the interface to have a way to explicitly store non-served files.

orchardbot commented 11 years ago

@bleroy commented:

Right, you would definitely not use IStorageProvider. Maybe a first version of your module would only support the file system, or maybe it stores media in the database (I don't like that but it may be an acceptable first implementation). But some duplication seems necessary as IStorageProvider was made for publicly accessible files, as far as I understand. Maybe extending that core feature would make sense, I don't know.

orchardbot commented 11 years ago

@Piedone commented:

Hmm, I'd have to think about this more.

orchardbot commented 10 years ago

@jeffolmstead commented:

Just throwing out a comment that I have some modules in place accomplishing this topic that I am planning on open sourcing soon. Contact me directly if you want a demo / to use the source code prior to release. My goal is to release these modules so others can improve them; would be great to have it work with the new Azure Media Services (doesn't yet). Currently it works on Blob storage though I had it also working using web.config on local file system.

orchardbot commented 10 years ago

@StanleyGoldman commented:

If you check this branch.

https://orchard.codeplex.com/SourceControl/network/forks/StanleyGoldman/UserMediaLibrary?branch=Submission_UserMediaLibrary

I have a custom module, called UserMediaLibrary, that by permission, limits users of the Media Library and the Media Library Picker to a folder named /Users/[username]. Not exactly what you are looking for. But maybe you can use/customize it.