⚠️ This post links to an external website. ⚠️
This post is part of a collection on UUIDs.
What is IDOR?
Indirect Object Reference (IDOR) occurs when a resource can be accessed directly by its ID even when the user does not have proper authorization to access it. IDOR is a common mistake when using a separate service for storing files, such as a publicly readable Amazon S3 bucket. The web application may perform access control checks correctly, but the storage service does not.
Here’s vulnerable Django code which allows a user to view their latest billing statement:
# Vulnerable!@login_requireddef view_latest_bill(request):bill = Bill.objects.filter(owner=request.user).order_by("date").desc()[0]url = f'https://example.us-east-1.s3.amazonaws.com/bill-{bill.id}'return render(request, 'template.html', { url: url })While Django ensures the user is logged in and only provides them with bills they own, S3 has no concept of Django users, and performs no such authorization checks.
A simple attack would start from a known URL and increment the bill ID:
$ curl https://my-bucket.us-east-1.s3.amazonaws.com/bill-100[ attacker sees their own bill ]$ curl https://my-bucket.us-east-1.s3.amazonaws.com/bill-101[ attacker sees another user's bill ]The attacker can keep trying bill IDs, potentially accessing the entire collection of bills.
UUIDs to the rescue?
What if we changed the Django model to use UUIDs for the primary key instead of an auto-increment? The new URLs will look like: my-bucket.us-east-1.s3.amazonaws.com/bill-9c742b6a-3401-4f3d-bee7-6f5086c6811f. UUIDs aren’t guessable, so the attacker can’t just “add one” to the URL to access other user’s files, right?
class Bill(models.Model):- id = models.AutoField(primary_key=True)+ id = models.UUIDField(primary_key=True, default=uuid.uuid4)Unfortunately, this is only a partial fix.
Even when URLs are unguessable, that doesn’t mean an attacker can’t learn them. A classic example starts with a former employee who used their personal computer for work. Hopefully their user account was quickly disabled, blocking them from accessing the company’s web application. But sensitive URLs may still exist in their browser history. Even a non-technical attacker can pull off this attack, just by clicking through their browser history. Thankfully, many companies require employees to use company-issued devices when performing work, so this attack may be limited to former employees who violated that rule.
The accidental leaking of URLs is probably a more reasonable concern. For example, if only managers are authorized to view bills you need to be careful not to leak the bill ID in other views where other employees have access.
If you use secret UUIDs, think of them as toxic assets. They taint anything they touch. If they end up in logs, then logs must be kept secret. If they end up in URLs, then browser history must be kept secret. This is no small challenge.
Another concern for leaked UUIDs is rotation. Whenever a secret key is compromised, leaked, or known to have been stored improperly, it should be changed. The same holds true for secret URLs. Make sure you have a way to rotate secret URLs, otherwise you may end up stuck in a compromised state. Again, no small challenge.
If this sounds like a huge pain… it is. Let’s find a better solution.
continue reading on alexsci.com
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.