Are signed URLs enough?
Published: 2023-03-21 09:34:31

Adrienne Fichter wrote an [article about a potential Viseca data leak](https://www.republik.ch/2023/03/20/kreditkarten-abrechnungen-offen-zugaenglich-im-internet). In a [comment](https://www.republik.ch/dialog?t=article&id=e8207a7b-dd4c-4db3-9265-9c97fddcfb4c) I found her technical explanation to be a bit too clumsy.

My initial position in the comment was that signed and expiring URLs don't need to be separately protected with a login. This in itself was very clumsy and incomplete. In the meantime I learned why. Let me elaborate.

# Login-protection

By login-protection I mean session- or token-based authentication followed by authorization. The client transports a secret to a server in a secure way: for example in HTTP header through a TLS connection. The server checks against those credentials for authenticity and for whether the client is authorized to even access the resource.

# Secretive URLs

URLs can transport secret information as well (in the HTTP path). The advantage is that they are easily sharable. This reduces system complexity because no other context has to be exchanged than simply a link to the resource: if you know where it is, you can access it. The disadvantage is exactly that: everyone knowing the URL can access the resource. This means it very important that the secretive URL is non-guessable. Otherwise an attacker could iterate through URL path or query parameters to gain access to resources.

I should mention that hashing or simply encoding (e.g. in base64) a guessable identifier is also bad idea. The result may look random, but it's actually not if the original identifier doesn't contain cryptographically strong randomness.

# Signed URLs

A problem with non-guessable URLs is that they may still be stored in an unintended place, e.g. logs, browser history or a web search index. You may still find Google search results propagating query parameters like `PHPSESSID` even today. The same may happen to HTTP header or body information as well, but it's just more unlikely because it's not intended to be stored.

For that reason it's a security best practice to sign URLs and it's parameters with public-key cryptography. This allows you to transport untampered information like an expiry date to the resource holder. If scope is narrow and the expiry window is short enough, this is as secure as a login-protected resource. The shorter the expiry window, the more secure and also less practical this approach becomes. Sharing a link via email becomes unpractical for example.

The big advantage is that the system design is much simpler. There is no need to leak (complex) resource ownership rules or calls to a file store system. And simple systems are arguably more secure.

# Limitations

The above may sound nice in itself, but signed URLs alone are not safe enough for some applications. It may be that even a short lived resource link should only be conveyed while the mediator shouldn't see the resource at all costs. This is for example the case for financial or medical data which need to be protected better. Authenticity and authorisation of the caller must be checked before resource access again. The file system can still be kept simple if authorisation is being delegated to a guard proxy handling very short-lived signed URLs.

# Conclusion

Non-guessable expiring URLs are good, but not good enough if they should protect very sensitive data. Additional authorisation may be needed even if URLs are short-lived.