134

I want to expose a resource on the web. I want to protect this resource: to make sure it is only accessible to certain individuals.

I could set up some kind of password-based authentication. For example, I could only allow access to the resource through a web server that checks incoming requests for correct credentials (perhaps against some backing database of users) before serving up the file.

Alternately I could just use a private URL. That is, I could simply host the resource at some impossible-to-guess path, for example https://example.com/23idcojj20ijf..., which restricts access to those who know the exact string.

From the perspective of an evildoer who wants to access this resource, are these approaches equivalent? If not, what makes them different? And as far as maintainability, are there pros and cons to either approach that I should be aware of before implementing one or the other?

D.W.
  • 466

7 Answers7

208

A private URL is somewhat weaker than authentication with credentials, even if the bit size of the URL is the same as that of the credentials. The reason is the URL may more easily "leak". It is cached in the browser, logged on the server and so on. If you have outbound links, the private URL may show up in the referrer header on other sites. (It can also be seen by people looking over your shoulder.)

If it leaks (by accident or due to carelessness by the user), it may end up being public and even indexed by Google, which would allow an attacker to easily search for all leaked URLs to your site!

For this reason, private URLs are typically used only for one-shot operations like password resets, and typically they are only active for a limited time.


There is a related thread over at Information security: Are random URLs a safe way to protect profile photos? - one answer shares this story: Dropbox disables old shared links after tax returns end up on Google. So it is not just a theoretical risk.

JacquesB
  • 61,955
  • 21
  • 135
  • 189
48

Note:

A lot of people seem to be confusing a "private" URL with authentication. Also, there seems to be some confusion that sending the link via a trusted entity is an attempt at two-factor authentication. To be clear, we're talking about a publicly accessible resource, albeit one that is sufficiently hard to guess.

When using a private URL, you should always assume that it can be compromised -- you should design such a URL so that even if it is compromised, the resource will not leak information to the attacker.


Private/hard to guess URLs are not equivalent to password-based authentication. By nature, private URLs are not private at all -- they are publicly accessible resources. I think the term "private" URL is a misnomer, rather they're "obscure" URLs.

There are certain cases where using a "private" URL is acceptable, but they are inherently less secure than traditional authentication methods such as password authentication or key-based authentication.

Some of the places I've commonly seen "private" URLs used are:

  1. Password Reset emails
  2. Certificate Generation emails
  3. Account / email confirmation emails
  4. Delivery of purchased content (ebooks, etc)
  5. Other misc things like flight check-in, print boarding pass, use private URLs in addition to traditional authentication

The commonality here is that random URLs are typically only good for one-shot operations. Also, traditional authentication and random URLs are not mutually exclusive -- indeed, they can be used in conjunction with each other to provide additional security when delivering a resource.


As Robert Harvey has pointed out, the only way to securely use a random/private URL is to generate the page dynamically and submit the URL to the user in a way such that the user can be considered semi-authenticated. This could be email, SMS, etc.

A randomly generated/private URL typically has a few properties:

  1. It should expire after a reasonable amount of time
  2. It should be a single-use URL: IE it should expire after the first time it's accessed.
  3. It should defer the user's authentication to some other entity that it trusts to securely authenticate the user. (By sending the link via email or SMS, etc)
  4. It should be impossible for a modern computer to brute force the URL in the timeframe preceding expiration -- either by rate limiting the API that exposes the resource or by creating a url endpoint with sufficient entropy such that it cannot be guessed.
  5. It should not leak information about the user. IE: If the page is to reset a password: the page should not display the requestors account information. If Alice requests a password reset link and Bob somehow guesses the URL, Bob should have no way of knowing whose password he is resetting.
  6. If it does leak information about the user, it should be used on top of traditional authentication, for instance a page may consider a user authenticated if they have a cookie set or if their session_id is still valid.

Different resources require different levels of security. If you want to share a secret recipe with some friends, for instance, it would be acceptable to use a random/private URL to share it with them. However, if the resource could be used to steal somebody's identity or compromise their accounts with other service providers, you'd likely care much more about restricting access to that resource.

8

Pretty much all authentication schemes boil down to proving that you know a secret. You authenticate yourself to some service by proving that you know a secret password, or a secret URL or,...

Some more advanced protocols (e.g., OAUTH, Kerberos, ...) enable you to prove that you know the secret without actually transmitting the secret. This is important because there are more ways to obtain an "unguessable" secret besides guessing it.

I could be sitting in the same Internet cafe as yourself, eavesdropping on your WiFi connection when you type in your "unguessable" URL. At that point, if you weren't using SSL, or if I can exploit the latest new bug in your SSL implementation, then I would know your secret too.

Solomon Slow
  • 1,231
3

Lots of good answers already in this thread, but to directly address the question:

From the perspective of an evildoer who wants to access this resource, are these approaches equivalent? If not, what makes them different?

Let me establish a definition. "Authentication" is the providing of credentials to prove a claim of identity. Access control is usually based on the identification of the user.

Your secret URL is not bound to a specific user. As others have pointed out, it could end up in a proxy's log file, or a search request that gets indexed by google, or many other ways it could leak out.

On the other hand, a password is tied to a unique user account. You have the ability to reset it, or only allow it to be used form the user's home location, or known IP address, or any number of other controls.

A username/password gives you much more granular control of the access.

Access control allows an identity (subject) access to a resource (object). In your URL example the identity is "anyone who ever gets the URL, via any means."

Go with the username/password if you can. URLs leak out in all sorts of unexpected ways over time.

JesseM
  • 139
1

A secret URL is just as secure as a secret password. However, passwords are easier to keep secret than URLs, because everyone and their programs knows that passwords must remain secret.

For instance, your browser will not show a password on screen, only store passwords with your permission, and offer means to protect that password storage (such as encrypted storage unlocked by a master password). In contrast, it will always show URLs on screen, may possibly leak them through the referrer header, and store them automatically in your browsing history without any further protection.

Likewise, HTTP proxies will not usually log passwords, while URLs are commonly logged.

Using URLs for authentication also means that sharing URLs shares authentication, which makes it hard to individually revoke (or record) access.

And of course, secret URLs inherit all weaknesses of secret passwords. In particular, using a password for authentication will reveal that password to the server and anyone able to read your communication.

meriton
  • 4,338
1

Another item not noted anywhere is throttling of 'guesses'. For most password authentication systems, you get a limited number of attempts at guessing a password for a user before further authentication attempts are either locked out, or limited.

While you could do something similar with 'guesses' against your URL scheme, it would be somewhat harder to implement. If there is a recognizable pattern to your URL generation, then it may be hard to stop someone setting up to work their way through your 'random' URL space.

Paddy
  • 2,633
0

There's another aspect which I didn't see mentioned yet - URL shorteners.

In a recent publication (April 2016), it was claimed that URL shortener services completely nullify the increased security provided by random generated "unguessable" URLs. The URL space of the shorterner service is considerably smaller than your randomly generated URL - meaning that any such "secure" URL shared with a shortener service can be guessed in an easier fashion than anticipated.

To illustrate - let's assume your random URL is 128bit long (i.e a guid). Also, let's assume that your random number generator is really strong and that you generate those bits in a uniform way. Guessing a 128bit number is very hard and can take a considerable time - your URL is effectively 128bit key protected.

Then, let's assume someone shared this URL on the google URL shortener. Today that service emits a 10 character long ID, composed of letters and numbers. (26+10)^10 ~= 3.6*10^15 < 2^52 - so we've effectively halved the key strength from 128 bit to 52 bit.

Add to that fact that the generators do not use the entire space due to other consideration and you can mount an effective attack that combines brute force with side channels (most likely pre-allocated random URL buffers).

The original article: http://arxiv.org/pdf/1604.02734v1.pdf
A blog post summarizing the article (by the author): https://freedom-to-tinker.com/blog/vitaly/gone-in-six-characters-short-urls-considered-harmful-for-cloud-services/

Ran Biron
  • 457