thumbor / thumbor

thumbor is an open-source photo thumbnail service by globo.com
http://thumbor.org
MIT License
9.96k stars 825 forks source link

Allow user to specify what fields are in the HMAC signature. #135

Closed danharvey closed 11 years ago

danharvey commented 11 years ago

We've got a use case where we want external users to be able to pass in different size parameters with a range but not different sources.

Using Thumbor's security at the moment this is tricky as all the fields are signed. We think one way to do this might be to specify the fields in the url which we want to be in the HMAC in the config.

This way we can just put the source url in this and allow users to still specify different sizes.

Has anyone else looked at doing this, or if we provide a pull request would this be something you'd want to put in the project?

diogomonica commented 11 years ago

I would advise against changing anything that does not protect the whole URL by default.

I think what you are asking is not having the resize component of the URL be part of the HMAC, right? (the 300x200)

Removing the sizing component from the HMAC effectively eliminates the DoS protection entirely, and you would be better off just to turn it off completely.

rafaelcaricio commented 11 years ago

Hi @danharvey,

If you would like to use this way I can tell you to use thumbor in unsafe mode, but you have to take care by yourself of all security implications of that as @diogomonica advised.

Maybe what you want can be better handled by a nginx doing rewrite to a thumbor unsafe url in the backend.

danharvey commented 11 years ago

Yes we're wanting to not have the resize component in the HMAC. I disagree that this will remove -all- protection that the HMAC gives you as you're still controlling the upstream source images.

What it does protect from is other people using your Thumbor server as an image proxy, so they can only request different sizes in a defined range rather than any.

With this issue I was mostly interested in seeing if we could add this flexibility to Thumbor. As you say if not we will write our own proxy API that does the same thing, we'd rather just not have to run another daemon in front of Thumbor.

One possible way to achieve this might be to make the string the HMAC uses a pluggable class so users could implement their own if they desire? or even a pluggable url parsing class to map from url => others? This would be useful for people who are moving from other image services to Thumbor.

This all does add complexity to Thumbor though.

heynemann commented 11 years ago

Still even if you allowed only sizes ranging from 1 to 999 in each dimension it amounts to a staggering ~1M different images per url you generated.

Unless you are running a "google-style" farm for thumbor, it would be trivial to write a DoS attack on your endpoint.

If all you want is to prevent proxying, just use the allowed domains setting and thumbor will prevent unauthorized domains in the original images (thus preventing people from using you as a proxy).

I strongly advise against leaving a range for users to generate images, though, unless as I said you have a humongous farm for thumbor (and if you do please we would like to know more about it).

If you can elaborate more on the problem we might be able to help you cover it in a different way?

Sorry for not being very helpful, but security is a top concern for thumbor.

Cheers, Bernardo Heynemann

Bernardo Heynemann Developer @ globo.com

On Sat, Nov 17, 2012 at 4:29 AM, Dan Harvey notifications@github.comwrote:

Yes we're wanting to not have the resize component in the HMAC. I disagree that this will remove -all- protection that the HMAC gives you as you're still controlling the upstream source images.

What it does protect from is other people using your Thumbor server as an image proxy, so they can only request different sizes in a defined range rather than any.

With this issue I was mostly interested in seeing if we could add this flexibility to Thumbor. As you say if not we will write our own proxy API that does the same thing, we'd rather just not have to run another daemon in front of Thumbor.

One possible way to achieve this might be to make the string the HMAC uses a pluggable class so users could implement their own if they desire? or even a pluggable url parsing class to map from url => others? This would be useful for people who are moving from other image services to Thumbor.

This all does add complexity to Thumbor though.

— Reply to this email directly or view it on GitHubhttps://github.com/globocom/thumbor/issues/135#issuecomment-10448473.

danharvey commented 11 years ago

That's true, and we don't have a huge server farm unfortunately...

The use case for this is we have a separation between the API of our site and different clients using it (the website, iOS, other developers, etc...) and we don't know what image resolutions or cropping they will want.

We currently use a CDN infront directly infront of our Thumbor servers via a load balancer. We're using the full HMAC so have a fixed set of images they can use, and are using the Thumbor url externally.

We want to open up control to them, without causing any security issues as you've mentioned. We could add a check infront that the request is from a valid API user, but then all image requests have to first hit our servers which defeats part of the point of the CDN.

I'm thinking the safest most performant way would be to hit our servers then do a redirect to Thumbor with a full signed url to pass back. The only issue then is we've got two round trips to load each image, but at least the image data comes via the CDN.

Any thoughts welcome!

Thanks, Dan

heynemann commented 11 years ago

Well,

Without more detail on your infrastructure it's a litte longshot, but here is how I'd do it (and how we are doing it at globo.com):

1) We have a CDN in front of thumbor. Every single image request that comes in gets "staticized' after rendering. This way the next time our CDN serves it, it's a simple file request. This obviously has a storage cost, but storage is the cheaper thing for us. 2) If the image is not found, thumbor gets called to answer for it. One of two things might happen: a) The user request regular cropping. We crop and serve it so it can be staticized. b) The user request smart cropping. We crop without smart, serve the image with a very small expiration, and send a request to a queue to process the smart cropping in the background. The next time this same request arrives, the cropping information will be available, then it's the same as a).

We also have native app users, websites, third-party developers and mobile websites (different infrastructure). What we did is we provided all of them with our private key so they could generate their own URLs. As long as that key is not leaked to public, we are fine.

Even if it leaks, it's just a matter of changing it in thumbor and notifying everyone of it. I know this is not the safest possible way, but until we implement multiple key support in thumbor we can't have one key per user. It would be slower as well to have multiple keys. Gotta figure out if it's worth the trade-off.

We have libraries to generate thumbor urls in Python, Ruby, Node.JS and Java. You can tell your teams to use them. If you are missing any language, let us know and if we can we will help.

Cheers, Bernardo Heynemann

Bernardo Heynemann Developer @ globo.com

On Sun, Nov 18, 2012 at 3:10 AM, Dan Harvey notifications@github.comwrote:

That's true, and we don't have a huge server farm unfortunately...

The use case for this is we have a separation between the API of our site and different clients using it (the website, iOS, other developers, etc...) and we don't know what image resolutions or cropping they will want.

We currently use a CDN infront directly infront of our Thumbor servers via a load balancer. We're using the full HMAC so have a fixed set of images they can use, and are using the Thumbor url externally.

We want to open up control to them, without causing any security issues as you've mentioned. We could add a check infront that the request is from a valid API user, but then all image requests have to first hit our servers which defeats part of the point of the CDN.

I'm thinking the safest most performant way would be to hit our servers then do a redirect to Thumbor with a full signed url to pass back. The only issue then is we've got two round trips to load each image, but at least the image data comes via the CDN.

Any thoughts welcome!

Thanks, Dan

— Reply to this email directly or view it on GitHubhttps://github.com/globocom/thumbor/issues/135#issuecomment-10473940.

danharvey commented 11 years ago

That's handy to know thanks.

The problem we've got is the web browser is the client for us, we render the site client side in Javascript with the templates being local as well. So we would need to pass the key to that, which would make it exposed straight away. We use OAuth2 in the browser to authenticate a user so end up with a session token for the user. What I think we might want is to authenticate against that, but then that blows away using the CDN as we would need to direct to Thumbor with a signed key after checking the session is valid.

We'll discuss this on our side and let you know what we end up doing. Let us know if you have any other thoughts, but I guess this issue ticket as such may not be valid any more?

Thanks, Dan

heynemann commented 11 years ago

If we think of something we'll let you know...

Cheers, Bernardo Heynemann

danielesegato commented 10 years ago

@heynemann Can I ask you what's the CDN service you are using?

heynemann commented 10 years ago

We have our own CDN, @mastro.