Azure Blob SAS URL Exposure: When a Link Is a Master Key
A Shared Access Signature is a signed query string bolted onto an Azure Storage URL. It says, in effect, "whoever holds this link may do X to this resource until time Y." That design is fine until the link leaks — and SAS URLs leak constantly, because developers treat them like ordinary links instead of like credentials.
Read the token before you judge it
A SAS URL looks like this:
https://acct.blob.core.windows.net/container/file.pdf?sv=2022-11-02&sr=c&sp=racwdl&se=2027-01-01T00:00:00Z&sig=...
Every parameter tells you the blast radius:
sp— permissions.ris read;racwdlis read, add, create, write, delete, and list. Write and list are the difference between "one file leaked" and "the whole container is mine."sr— resource scope.bis a single blob;cis the entire container.se— expiry. A token good until 2030 is a very different finding from one that dies in an hour.si— a stored access policy, which can be revoked server-side.
A container-scoped token with sp=racwdl and a multi-year expiry is close to a storage account master key for that container.
Where they hide
Look everywhere a URL can end up:
- Client-side JavaScript and mobile app bundles
- API responses that return a "download link" or "upload URL"
Refererheaders leaking a SAS URL to third-party analytics- Git history, public buckets, Postman collections, and CI logs
- Error pages and PDF/email templates that embed asset links
The Referer case is nasty. If a page loads at a SAS URL and then links out, the full signed URL can travel to another origin in the referrer header. That's a passive leak nobody notices.
Prove impact, carefully
Once you hold a SAS URL, the permissions decide your test. For a read-only single blob, downloading the one file you were already meant to see is not much of a report — unless that file is somebody else's private data. The stronger case is list or write at container scope.
To prove list access without scraping strangers' files, point Azure Storage Explorer or the CLI at the SAS and list one page of blob names:
az storage blob list --container-name container \
--sas-token '<token>' --account-name acct --num-results 5
Seeing filenames you were never authorized to enumerate is enough. If write is present, upload a single harmless canary file to your own clearly-labeled path (bugbounty-poc-<random>.txt) and delete it, rather than tampering with real objects. Never open other tenants' files beyond confirming they exist.
The report
Include the leaked URL source, the decoded permission set, resource scope, and expiry, plus one bounded proof — a listing page or your own uploaded-then-deleted canary. Spell out the worst case a real attacker reaches: mass exfiltration, overwrite of served assets, or ransom of the container.
Fixes worth recommending: short expiries, least-privilege sp (read a single blob, not racwdl on a container), stored access policies so tokens can be revoked, user delegation SAS backed by Entra ID instead of account keys, and never putting SAS URLs where a Referer or log can capture them.
Microsoft's Shared Access Signature overview breaks down every parameter and the user-delegation model. Decode the token first; the query string tells you the severity before you send a single request.