Open PupLukey opened 9 months ago
@PupLukey lack of protection around static assets is a concern and I agree.
However, can you document and prove specifically the following:
Which allows the enumeration of media file urls even easier and ultimately results in all your data being stolen by some filthy guy like me.
Without logging into the user's account, there is no way to enumerate media urls, especially if they are marked private.
You will see the following when making a request to the /media?author=
{
"count": 0,
"next": null,
"previous": null,
"results": []
}
Thanks for your reply and support on this topic, @tobocop2
I assume we both mean user provided assets like the actual video or other media files when you say "static assets"?
It is true and well known to me that you cannot query information about media with a state of private
. The query returns something like
{ detail: "This media is private." }
And it is also true that media with such state aren't listed when trying to obtain a list of media. Nevertheless the actual files of this private media are still unprotected even though you cannot enummerate them directly from the api. A more sophisticated guy than me may come up with an effective way to find those files just from the web. (Not even sure if web directory listing is deactivated in the nginx configuration)
Furthermore there is no point with this application to mark something as private since there is no such feature to share private media with selected users. \
My (and probably common) use case is a private media sharing platform to share media with a closed set of people known to me. This is supposed to be achieved by setting LOGIN_REQUIRED_GLOBALLY
to true in local_settings.py.
Conclusion: It doesn't matter that private media info isn't queryable.
However, can you document and prove specifically the following:
Which allows the enumeration of media file urls even easier and ultimately results in all your data being stolen by some filthy guy like me.
Sure, here are my queries. Curl doesn't do anything if not told so. This means that there can be no authentication happening on the server side since no such information is provided. For the sake of brevity I will ommit the verbose flag. You can look up an example with verbose information in my original post.
The general approach is to get a list of api urls to every media and then using that list to get the specific file url to the encoded media file.
Additionally I have written a little bash script for you that utilizes this approach to download every file.
This returns a list of meta informations for every video/media. \
This meta informations contains a json key api_url
which can be used in a second query to obtain the url to the target.
@PupLukey thanks, this makes sense. I just would suggest updating the title / description to factor in the fact that private media associated to a different author is not enumerable. This would be an even more massive security flaw so I just wanted to ensure that other folks are aware of the distinction.
I've been experimenting with the following strategies personally:
store all static content in s3 behind cloudfront and serve the data with cloudfront signed urls.
serve mediacms in a closed network and provide access to it via a VPN. This is fine if it is to be used internally only.
To be frank here, I don't exactly like your suggestions about what one can do to secure access since they all rely on external systems being integrated with the mediacms system for a functionality so essential that it should be implemented by the app itself. \ Furthermore securing this application with a VPN would undermine a key reason to use the software. I think MediaCMS is about easily sharing Media with others. Requiring normal people without technical knowledge to use a VPN Client sounds counter productive to me. If I was in need of an application to upload files and access them anywhere I would have stayed with any cloud solution.
I would really like to see that MediaCMS overhaul it's authentication and authorization in a way that allows more options for privacy. That includes the basic functionality as opt-in to put media files and the api for meta information about these media files/objects behind authorization but may also include:
And actually I have already suggested a solution in my first post which integrates well with the current way of providing files and doesn't require huge changes. Using different urls now might be a little annoying. I would do it myself and open a PR but I really dislike Python and can't develop with it.
If there is something missing with my proposal I will be glad to discuss that. :)
I suggest adding the bug or enhancement label to clarify that this issue is not about requesting help to setup MediaCMS. Would be great to hear some feedback from the guys who need to approve changes. :)
Just now I have seen that #905 relates to this issue. \ But as I explained above it's not only the search bar or a frontend thing. The whole problem here is bigger.
This is not meant to be a complaint. Great work and love the concept and project, together with clearly your hard work. I thought it was most relevant, best to comment here, rather than add a new topic but I've just found more exposure that I didn't expect. When not logged in and with the configuration setup for private access, any tagged media becomes listed (thumbnails) and available from the "Tags" side menu, the same with "Categories" and "Members" are all listed in full?
On a side note, it would be really great is your could reset the "Views" count or perhaps not increment this number when logged in as an admin and setting things up.
I really hope an update fixes this at some point otherwise, very regrettably this won't be useful.
In case that this behavior is actually intended by the devs, this issue becomes a feature request.
Description
In violation with the major benefit that this application claims to provide, control over your data, there are two entities being exposed:
The visibilty state
private
of a media object which can be set after uploading or by a default setting in the settings.py does only prevent the enumeration of urls (answer). And is also undesirable since you would probably want to share it with registered users. \ It does however not prevent anyone from downloading the files.This will be the case no matter if GLOBAL_LOGIN_REQUIRED is true or false. \ Also overriding the LOGIN_REQUIRED_IGNORE_PATHS as opposed to #418 doesn't seem to deny access for anonymous users. @masavini mentioned in the aforementioned issue that the api uses a different authentication system. I would be glad if anyone could elaborate on this.
It seems that the backend is intended to let the nginx webserver do the heavy lifting of transferring media files to keep resources free for new requests. That is probably why the default site configuration of the nginx points urls beginning with
/media
andmedia/original
to directories on the filesystem.default config excerpt
``` location /media/original { alias /home/mediacms.io/mediacms/media_files/original; } location /media { alias /home/mediacms.io/mediacms/media_files ; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; } ```While this seems to be a known practise I recommend implementing some form of authorization to at least protect files from anonymous users but better to perform actual checks if this specific user is allowed to access the requested media. \ (This is also feature I am missing: Grant permission to watch a private video on a user+video basis.) \
One possibility mentioned by other online sources like the nginx documentation would be to use the
X-Accel
headers more commonly known as X-Sendfile feature. \ Then the resource request of the media file would need to be run against the REST API and the api returns a status code of either 200 or 403 to indicate if permission is granted and append theX-Accel-Redirect
header with the media file path to the response. The API does not need to return the file itself (empty body). Nginx (or any other supporting webserver) intercepts responses with this header and either returns the file or an http error code depending on the status of the original response given by the REST API.I think my proposal is quite reasonable since this application relies on nginx anyways and it would need only medium size changes to be useful for private use. \ I suppose changes may include:
X-Accel-Redirect
internal
directive to media locationsTo Reproduce
Steps to reproduce the issue:
Expected behavior
A non logged in user should not be able to get information from the api or access media files from the webserver if the GLOBAL_LOGIN_REQUIRED flag is true.
Screenshots
No Screenshots provided
Environment / Setup
Additional context
curl /api/v1/media no auth
``` curl -v -X GET https://Final Words
I like your efforts to provide the world with software fundamental to the web. \ I would like to continue using your software if this issue was addressed. \ I have not spent nearly enough time in this repo to see every context or understand it entirely. It may be that I made assumptions on how things are intended or how they could be implemented which are just wrong. Feel free to correct me or clarify things to help improve this software.