Reputation: 2660
I'm interested in social networks and have stumbled upon something which makes me curious.
How does facebook keep people from playing with URLs and gaining access to photos they should not?
Let me expand, here's an altered example of a facebook image URL that came up on my feed-
https://fbcdn-sphotos-g-a.akamaihd.net/hphotos-ak-prn1/s480x480/{five_digit_number}_{twelve_digit_number}_{ten_digit_number}_n.jpg
So, those with more web application experience will presumably know the answer to this, I suspect it's well understood, but what is to stop me from changing the numbers and seeing other people's photos that possibly I'm not supposed to?
[I understand that this doesn't work, I'm just trying to understand how they maintain security and avoid this problem]
Many thanks in advance,
Nick
Upvotes: 9
Views: 3263
Reputation: 2268
For the security by obscurity option there is one drawback, once an actor has the URL to the actual resource, there needs to be a mechanism in place to revoke it.
This scenario might be, User 1 blocks User 2 on a social site, but user 2 secretly saved all the URL's to User 1's media and hence still has access at a URL level.
To circumvent this, I recommend using an intermediate rotating directory level as part of the URL fabrication. If the rotating key is associated with the owner of the resource, then a new URL can be constructed every time security changes.
User 1 and User 2 are friends on a social media site
User 1 uploads an image (myimage.jpg) on a social site
The system saves the physical image to the file system under a new unique file name and directory structure /UserFiles/<User1 ID>/<Rotating User Key>/Images/<Stupidly long unguessable filename>.jpg
The filename is stored in a database so that when we ask for User1's pictures, we are served with the URL
User 2 visits User 1 and opens their social media gallery
User 2 received the URLs for all user 1's uploaded images as part of a web page
User 2 (sneaky) saves all the exact image URLs into notepad so they can look at them outside of the context of the User1's social media gallery
User 1 blocks user 2 on the social media site.
User 2 requests user 1's social media gallery from the server and is rejected as they are blocked.
User 2 uses the saved URL's they copied to notepad earlier and pastes them directly into the browser
User 2 can still view the images, even though they are blocked.
We saved the physical file to /UserFiles/<User1 ID>/<Rotating User Key>/Images/<Stupidly long unguessable filename>.jpg
As part of the User record in the database have a field Rotating_User_Key, probably a UUID or something unguessable
When security changes, we generate a new NEW Rotating User Key and update the directory structure in the physical file system.
/UserFiles/<User1 ID>/<NEW Rotating User Key>/Images/<Stupidly long unguessable filename>.jpg
We save the NEW Rotating User Key to the user store, so we can construct further URLs for User1's resources.
User 2 is blocked at website level and their saved URL's are invalid.
Upvotes: 1
Reputation: 14428
There's a couple ways you can achieve it.
The first is link to a script or action that authenticates the request, and then returns an image. You can find an example with ASP.NET MVC here. The downside is it's pretty inefficient, and you run the risk of twice the bandwidth for each request (once so your server can grab the image from wherever it's stored, and once to serve it to your users).
The second option, you can do like Facebook and just generate obscure url's for each photo. As Thomas said in his comment, you're not going to guess a 27 digit number.
The third option I think is the best, especially if you're using something like Microsoft Azure or Amazon S3. Azure Blob Storage supports Shared Access Signatures, which let's you generate temporary url's for private files. These can be set to expire in a few minutes, or last a lifetime. The files are served directly to the user, and there's no risk if the url leaks after the expiration period.
Amazon S3 has something similar with Query String Authentication.
Ultimately, you need to figure out your threat model, and make a decision weighing the pros and cons of each approach. On Facebook, these are images that have presumably been shared with hundreds of friends. There's a significantly lower expectation of privacy, and so maybe authenticating every request is overkill. A random, hard to guess URL is probably sufficient, and let's them serve data through their CDN, and minimizes the amount of processing per request. With Option 3, you're still going to have overhead of generating those signed URL's.
Upvotes: 9