Introduction
Broken Access Control (BAC) might sound like a minor issue, something easily spotted, but it’s actually one of the most frequently overlooked security flaws. While many focus on threats like Remote Code Execution (RCE) or Cross-site Scripting (XSS), BAC silently allows unauthorized users to perform actions they shouldn’t, often without any complex attack. A simple forgotten backend check can lead to sensitive data exposure or elevated permissions, just by slightly modifying the target web address.
In this post, we’ll walk through how you can test for Broken Access Control using Open Worldwide Application Security Project (OWASP) Juice Shop—an intentionally vulnerable web application that makes it easy (and safe) to demonstrate these issues in practice.
Understanding Broken Access Control
Access control directs who can do what in a system. When it’s broken, users can act outside their intended permissions. Users might be able to read other users’ data, modify other roles, or access administrative functionality without authorization. OWASP defines this category broadly and it includes:
- Vertical privilege escalation: Accessing higher privilege functions (e.g., a user accessing admin functions).
- Horizontal privilege escalation: Accessing same role resources (e.g., viewing another user’s order).
- IDOR (Insecure Direct Object Reference): Accessing data by manipulating object references like user IDs or filenames.
- Forced browsing: Accessing hidden resources or unlinked pages directly.
While it might be hard to understand these concepts at first, Juice Shop does a great job showcasing these problems in a safe, intentionally vulnerable playground.
Testing for Broken Access Control
For this simulation, you will need to install Juice Shop in your local environment and use Burp Suite to capture traffic while interacting with it.
Gaining Privileged Access
Juice Shop is a deliberately vulnerable web application that exhibits the classic Forced Browsing and Vertical Privilege Escalation vulnerability. Imagine if someone could access admin functions by just visiting a URL; that would be a security nightmare. Fortunately, we can demonstrate this in Juice Shop without the risk.
You can test this by attempting to access hidden resources or unlinked pages directly using keywords such as “admin,” “root,” or other common path names in the URL. In our case, the Administration page can be accessed by visiting the “/#/administration” path. This page was not linked anywhere in the standard UI, yet entering the URL directly allowed full access to the user listing and the ability to remove customer feedback.
Note that this vulnerability is accessible if you are already logged in or tagged as an admin role user inside OWASP Juice Shop. However, given that this is hidden in the user interface even if you log in as an admin user, we can infer that it was not meant to be exposed to users (including admin users). In some real-world scenarios, some web applications allow access to the affected endpoint to all users as long as they enter the correct address.
But you’re probably curious how we can access this page using a regular, low-privileged accountFirst, inspect how the authentication works. Upon logging in, a token will be sent to your browser and subsequently attached to every HTTP request made to Juice Shop.
At this point, you will have to study JWT, but let’s assume that you already know it. What do you think would happen if we change the JWT role parameter or claim to something else, like “admin”?
You guessed it right. Modifying the JWT and changing it to “admin” allowed us to access the “/#/administration” page while logged in as a regular user. All you need to do is use Burp Suite’s JWT Editor extension, modify the role parameter or JWT claim to “admin,” go to your browser’s local storage, and replace the token key with the modified JWT, and Voila! You now have access to the Administration page even as a regular user.
Viewing and Tampering Another User’s Basket
This is an example of Insecure Direct Object Reference (IDOR) and Horizontal Privilege Escalation. Imagine if you have an e-commerce site and anyone can add or delete items in another user’s shopping cart. That would leave your customers confused.
To test this vulnerability, log in as a regular user and inspect HTTP requests and responses related to user basket actions. In Burp Suite, notice that visiting your own basket generates a “GET /rest/basket/6” request to Juice Shop. Immediately, you can see from that request that our basket has an ID of “6.” Out of curiosity, if we change the basket ID to another number, will we be able to access other users’ baskets? It turns out we can.
There are a couple of ways to test this, but by going to the browser’s Developer Tools > Storage > Session Storage, we can see a “bid” parameter. Modifying it to another number, in our case “3,” and refreshing the page would let us access basket #3—with no ownership check, just the data. This is an example of a horizontal IDOR vulnerability, where users at the same privilege level can access each other’s data by simply modifying object references.
Alternatively, the details for basket #3 can also be accessed by repeating the original HTTP request in Burp Suite and modifying the ID to “3”.
We were able to see the details of the other user’s basket, but how do we tamper with it? Let’s go back to Burp Suite and study the HTTP request and response flow. Notice that, besides viewing your own basket, adding items to our basket requires a “BasketId” parameter. This is the key to the attack. What if we modify the “BasketId” before sending the request? Will we be able to modify another user’s basket successfully? The short answer is yes, but it is not as easy as it sounds.
But before we do the attack, we have the following in basket #3. Remember, our basket is basket #6.
Now, let’s modify the “add to basket” request and change the “BasketId” to a different number. However, you will notice that trying to change it won’t modify the basket content of our target.
So, what should we do? There are many things you can try, but to cut a long story short, you might discover that adding a second “BasketId” would push the request and modify our target’s basket as well.
This tells us that if the backend interprets the requests, and if it finds another “basketID,” it will apply the same action to it. Do you see where I’m going with this? Perhaps adding more “basketID” values would enable a multi-basket attack, but I will leave that for you to try.
This means that ignoring access control measures can lead to numerous issues in your web application, potentially affecting multiple accounts by disclosing sensitive information or, as in our case, the contents of a user’s basket.
Forged user reviews
In Juice Shop, as with almost every e-commerce site, users are allowed to write and submit reviews. This generally benefits both the store owner and enhances the overall user experience. But what if someone could forge a user review? What if a customer review was written and attributed to someone else, perhaps a high-profile user of the site? That would greatly affect the product’s performance, right? This is what we wanted to achieve here: post a user review and attribute it to a different user.
Now, you’ll notice that whenever you write and submit a product review, this PUT request is sent.
Remember our previous attack that affected another user’s basket? How about the attack where we found the admin email address (see Gaining Privileged Access)? Let’s test that. What would happen if we modify the author before sending it to the endpoint? Would that change the author itself? Let’s see.
And what do you know, we were able to post a review using a different user! And we can confirm that by browsing the exact product in the web application.
So, the lesson here? Yes, broken access control also helps attackers forge account actions.
Directory enumeration and restricted file download
One common pitfall of improperly implemented access control is that restricted directories and their included files become accessible for download. This vulnerability is often found in applications rushed to production or those that don’t undergo regular security testing. While this may be harder to find in the real world today, this vulnerability still exists in some web applications. But fret not, Juice Shop exhibits this weakness.
If you’ve explored Juice Shop before, you might have stumbled upon various directories, including the `/ftp/` directory. You’ll notice that accessing this directory reveals a number of files without requiring any additional authentication. You can even access some of the files enumerated.
Clearly, some of these files are not intended to be accessed, which in itself indicates an access control violation.
If you further explore the directory, you’ll discover that attempting to access files with extensions other than “.md” or “.pdf” results in a restriction notification. As curious individuals, we’ll want to bypass this. Fortunately, Juice Shop is vulnerable to null-byte injection.
Null-byte injection is essentially an implementation-related vulnerability stemming from a weakness in the framework, underlying library, logic, or a combination of all these three. To perform a null-byte injection, we need to append a null-byte (`%00`) to the filename, hoping that the application won’t sanitize our request.
Initially, adding `%00` to the end of the URL might not yield results, perhaps because the server expects a valid file extension. To address this, let’s append a `.pdf` extension.
Still not working, right? Perhaps something is blocking our request. Let’s see if encoding will help us get through. Let us encode % and see what happens.
Well, what do you know, it works! Now we can access the restricted file and see its content. Clearly this is a violation of access controls.
How to Prevent Broken Access Control?
If you’re building or maintaining web applications, Broken Access Control (BAC) is one of the most important risks to address. Here’s what you can do to avoid the issues above:
Enforce Access Controls on the Server Side
- Don’t rely on client-side code or hidden links.
- Every sensitive operation should include server-side checks against the user’s authenticated identity and role.
Use Context-Aware Authorization and Centralize Access Control Logic
- Implement logic that not only checks the user’s role but also whether the user owns the resource in the specific transaction context. For example, confirm “user.id == order.ownerId” before returning order data.
- Centralize your authorization logic into a single reusable library or service. This ensures that robust authorization rules are applied consistently. This also simplifies maintenance.
Adopt a “Deny by Default” and Least Privilege Principle
- Don’t assign admin rights unless explicitly needed.
- Make roles granular and restrictive by default.
Implement Indirect and Unpredictable Resource Identifiers
- Use randomly generated identifiers like UUIDs/GUIDs.
- Implement an indirect reference map that translates a public identifier to a real database ID only after the authorization check has passed.
Apply Rate Limiting and Throttling
- Apply rate limiting to endpoints, especially to sensitive ones such as authentication and data access, to slow down attackers trying to bruteforce identifiers
- Block IPs or users that exhibit anomalous behavior or exceed reasonable request thresholds
Implement a Secure Development Lifecycle (SDLC)
- Include security unit tests and access control checks as part of your CI/CD pipeline.
- Use test accounts with varying roles to test for both vertical and horizontal privilege escalation.
Monitor and Log Access Violations
- Set up alerts for unusual access patterns or repeated unauthorized attempts.
- Log every access control failure, including the user, IP address, and specific resource they are trying to access.
Perform regular security assessments
- Perform regular Web Application Penetration Tests (VAPT) against your web applications.
- Engage qualified professionals to perform penetration testing at least annually or after any significant changes to the environment.
Final Thoughts
Broken Access Control topped the OWASP Top 10 list for a reason: it’s one of the most common and dangerous issues that plague web applications. While OWASP Juice Shop is intentionally vulnerable, the lessons it teaches are very real. If you are a developer, product owner, or cybersecurity professional, the insights from Juice Shop offer a humbling reminder of why access controls must be built defensively and verified thoroughly.
Looking for support to assess your web applications? If your goal is to get a real-world, adversarial assessment of your security posture, including your access controls, Scrubbed can help you perform Web Application Penetration Testing. We can test Broken Access Controls and other vulnerabilities to help you secure your applications.
Not your cup of tea? We also offer other information security related services such as IT audit, Security Awareness Training, and SOC assessment support.
Get started in securing your organization. Contact us at https://scrubbed.net/contact-us/ (Risk Advisory).