Yellow-Dog-Man / Resonite-Issues

Issue repository for Resonite.
https://resonite.com
139 stars 2 forks source link

assets.resonite.com contents can be loaded without gating #2763

Open jae1911 opened 2 months ago

jae1911 commented 2 months ago

Describe the bug?

When looking at assets.resonite.com, it is possible to load any media uploaded from it without authentication. While this is useful to export videos uploaded on Resonite to the outside, this also enables the use of the media repo as a CDN.

For instance, if a user were to upload a movie to Resonite, it is possible for that same user to hotlink it on a website or anywhere else, effectively sharing that movie. It would be the same if a user were to store arbitrary files (ISO, ZIP, EXE, etc).

While rightsholders can issue DMCAs and other requests to take down medias, it does not resolves the underlying issue of people being able to use Resonite as a CDN. Depending on providers, this could incur more storage and traffic costs, since with a little know-how, someone could automate account creation and media upload outside of the officially supported clients. In the worst case, this would also allow a threat actor to host malware on Resonite (example scenario: a program made to steal Discord tokens or browser passwords disguised under ResoniteInstaller.exe and hosted on assets.resonite.com to make it appear more legitimate).

To Reproduce

As a proof-of-concept, here are some files hosted on Resonite and accessible from the outside:

  1. The Blender Open Movie Big Buck Bunny: https://assets.resonite.com/45c8bafeb9a53df7f491198d2e71529701bcf1cd51805782089fac1d32869f9b
  2. Random STL file: https://assets.resonite.com/5ccb8b075968f3432748fc577f744596f02f63e988696705dedca1df98c3d8bb
  3. Random image: https://assets.resonite.com/e5a4a7bd9997a62357dfb1a04605fc2e457d5352d575c778bd27ee1ffc65998c

Steps to reproduce:

  1. Import media into Resonite
  2. Save it to the inventory
  3. Wait for it to fully sync
  4. Spawn the object in question
    • If a video, copy the media hash from the video player
    • If an arbitrary file, inspect the object, go to the root of it and get the media hash from the StaticBinary component
    • If an image, inspect the object, go to the root of it and get the media hash from the StaticTexture2D component
  5. While making sure you remove resdb:/// and the extension from the media hash, visit https://assets.resonite.com/<media hash> to access it outside of Resonite

Expected behavior

One way to mitigate that would be to require some kind of authentication to access medias (see Additional Context for more information about this).

The media repo could just ask the client for a specific token or just be behind regular authentication.

Screenshots

No response

Resonite Version Number

Unknown, API

What Platforms does this occur on?

Windows, Linux

What headset if any do you use?

No response

Log Files

Not applicable (API).

Additional Context

The Matrix protocol is plagued with that very specific issue. Because of the design of most media repos, users are able to upload any file then access it without any gating from outside of clients (for instance, my profile picture on my own server https://matrix.777.tf/_matrix/media/v3/download/matrix.777.tf/64251a83834d736e28efecf8bac80217ef998e231807419471262908416). This results in users uploading files, then using servers as a CDN, causing increased storage and bandwidth cost for server owners.

The proposed solution was to implement authentication for media access, MSC3916 (https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3916-authentication-for-media.md). While Resonite is fundamentally different from Matrix and does not exhibits the same behaviours (like being able to load medias from other instances without being authenticated), it does share a similarity, notably:

  • The only protection for media is the obscurity of the URL, and URLs are easily leaked (eg accidental sharing, access logs).

Reporters

U-j4 | j4.lc (Discord)

Frooxius commented 2 months ago

This isn't really a bug, it's just how the CDN works.

I don't really see how would you actually combat this in the first place - the clients need to be able to download the assets.

Even if we were to add some kind of authentication token, that token needs to be accessible to any client so they can actually load the content. Meaning if person is making a tool to upload data to Resonite - they can just as easily get the token mechanism to this too.

Effectively though, if you want to upload significant amount of data, you have to purchase the storage - that's one thing we're actually selling, so I don't see this being too bad for us right now - if you want more storage, you have to pay for it.

There are other ways this can be combated too - we limit how many accounts can user create, so making more to get more storage becomes harder to do. We can restrict things there more as well.

For some of the threats - I don't see this affecting them much. If there's copyrighted content hosted, DMCA deals with that. Even if the URL wouldn't be accessible like this, the copyrighted content would still be an issue - it doesn't change anything there.

ResoniteInstaller.exe example doesn't work, because you can't name the files - it'll just be a random hash.

jae1911 commented 2 months ago

I don't really see how would you actually combat this in the first place - the clients need to be able to download the assets.

Discord introduced an expiration on medias, which could also be done in this case. For instance, when accessed a media will only be accessible for say a week (I don't have exact numbers) and eliminates more long-term hotlinking. The media itself would be refreshed next time a client wants to access it.

Even if we were to add some kind of authentication token, that token needs to be accessible to any client so they can actually load the content. Meaning if person is making a tool to upload data to Resonite - they can just as easily get the token mechanism to this too.

The authentication part would be to access the medias as well, which would make direct hotlinking harder. Like for instance, nobody could just use https://assets.resonite.com/45c8bafeb9a53df7f491198d2e71529701bcf1cd51805782089fac1d32869f9b to host Big Buck Bunny outside of clients. Paired with expiration, it would make it just hard enough to make it not worth it to do that, which will definitely become an issue as Resonite grows.

Frooxius commented 2 months ago

Discord introduced an expiration on medias, which could also be done in this case. For instance, when accessed a media will only be accessible for say a week (I don't have exact numbers) and eliminates more long-term hotlinking. The media itself would be refreshed next time a client wants to access it.

That doesn't work - it would mean we would have to delete user's stored content automatically after some time! This is something we fundamentally cannot do.

If you save content into your account, we can't just delete it after some random time from the cloud, because that would cause that content to be broken!

We only ever delete content if it's actually deleted from the user account.

The authentication part would be to access the medias as well, which would make direct hotlinking harder. Like for instance, nobody could just use https://assets.resonite.com/45c8bafeb9a53df7f491198d2e71529701bcf1cd51805782089fac1d32869f9b to host Big Buck Bunny outside of clients. Paired with expiration, it would make it just hard enough to make it not worth it to do that, which will definitely become an issue as Resonite grows.

I think this is already an issue that solves itself by limiting how much you can actually upload to your account. Free accounts get just 1 GB - if you want anything bigger than that, you have to pay for more.

We could make further restrictions by limiting what kind of content can free accounts upload too to make it harder as well, without having to add authentication.

Our system doesn't treat media much differently from other assets - it's all mostly just binary blobs to it. If we add authentication across the board right now, that will likely significantly increase the costs for processing authentication for everything.

Once this becomes a problem, we'll likely make some changes/restrictions, but right now this would cost us engineering hours and a lot of additional server costs, which makes it not worth it.

jae1911 commented 2 months ago

That doesn't work - it would mean we would have to delete user's stored content automatically after some time! This is something we fundamentally cannot do.

Oh no, not at all, the media remains online but the access URL does expire and is then refreshed by the client.

Our system doesn't treat media much differently from other assets - it's all mostly just binary blobs to it. If we add authentication across the board right now, that will likely significantly increase the costs for processing authentication for everything. Once this becomes a problem, we'll likely make some changes/restrictions, but right now this would cost us engineering hours and a lot of additional server costs, which makes it not worth it.

Fair enough.

Frooxius commented 2 months ago

Oh no, not at all, the media remains online but the access URL does expire and is then refreshed by the client.

That still doesn't really fit into our model at all. The clients need to be able to access it for the content to work. If they can't - then it's as good as deleted.

What would constitute refresh here? Just Resonite client accessing it? This brings back the whole token thing - someone making a tool could just automate that part of the process.

If we had the token system with authentication, then the expiry would be kinda irrelevant - it's already not accessible from the direct URL anyway, so there's no point in expiring that.

I think the main issue is that you're seeing Resonite more as Discord/Matrix kind of mechanism, but we're actually closer to things like Dropbox in terms of handling storage, so I think a lot of the concepts will not match.

jae1911 commented 2 months ago

but we're actually closer to things like Dropbox in terms of handling storage

Ah, I see then