100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Web Application Security
60 minintermediate

Practice — Exploiting Access Control Bugs in OWASP Juice Shop

What You'll Build

In this hands-on lab you will run OWASP Juice Shop, a deliberately vulnerable web application built for security training, and use it to find and exploit real broken-access-control flaws in a safe, legal environment. You will confirm an IDOR, attempt a vertical privilege escalation, and then reason about the server-side fix each flaw requires.

Analogy🏏Cricket
💪 Think of it like fitness: Assessment day is when the training gets tested for real, you take the map of your programme and put each targeted lift under load to see which strengths hold and which weaknesses are genuine, recording every number. Just as the measured test turns a plan into proven results, using your attack-surface map to probe injection, authentication, and API authorization, and confirming each real flaw with captured evidence, turns recon into demonstrated findings. This reveals where knowledge becomes proof: you deliberately load each mapped weakness and record exactly what gives way.

The goal is not merely to break things but to connect the theory from Module 1 to observable behaviour. By watching an id change leak another user's data, and by seeing a hidden admin route respond to a direct call, you will internalise why authorisation must be re-verified on the server for every request. You will finish by writing the remediation you would ship.

Analogy🏏Cricket
🏏 Think of it like cricket: A disciplined bowling attack does not spray deliveries everywhere and hope; guided by the scouting report, it targets each batter's flagged weakness, confirms the ball is doing what was planned, and records every dismissal for the analysts. Just as that planned, evidence-backed attack turns a dossier into wickets rather than wasted overs, working your test plan area by area, confirming each real flaw by safely triggering it, and documenting it rigorously turns recon into evidenced findings. This reveals the method: targeted, confirmed, and recorded beats spray-and-pray every time.

Prerequisites

  • Docker installed, or Node.js 18+ if you prefer running Juice Shop directly from source.
  • A modern browser with developer tools, since you will inspect and modify requests.
  • Completion of the Module 1 readings on broken access control and IDOR, whose concepts this lab exercises directly.
  • An understanding that you must only ever test applications you own or are explicitly authorised to test, such as Juice Shop locally.

Setup & Project Structure

Run Juice Shop locally in a container so it is isolated and disposable. The application starts on port 3000 and ships with a catalogue, user accounts, and an admin area, all intentionally flawed. Keep your browser's developer tools open on the Network tab throughout, because the exercise is about observing and altering the requests the site makes rather than only clicking the interface.

Analogy🏏Cricket
📷 Think of it like photography: A professional does not trust memory on a shoot; every frame is captured with its settings, the aperture, the shutter, the exact scene, so the shot can be reproduced and proven later. Just as that per-frame metadata makes each image a self-contained, repeatable record, working your test plan area by area and capturing the exact request, the response that proves impact, the reproduction steps, and the affected endpoint makes each finding a self-contained record. This reveals the discipline: evidence recorded at the moment of capture is what makes a finding stand up in the report.
bash
# Run OWASP Juice Shop locally in Docker (isolated, disposable)
docker run --rm -p 3000:3000 bkimminich/juice-shop

# Then open the app and its developer tools:
#   http://localhost:3000      (the application)
#   F12 -> Network tab         (watch every request/response)

# Register two separate accounts so you have your own data
# plus a 'victim' account whose data you will try to reach.

Step 1 — Foundation: Establish a Baseline

First, register two accounts, then log in as the first and browse to something tied to your identity, such as your basket or a saved address. Watch the Network tab and note the exact request the browser sends, including the endpoint and any numeric identifier in the URL or JSON body. This captured request is your baseline: the legitimate call whose identifier you will later tamper with.

Analogy🏏Cricket
💪 Think of it like fitness: Before changing anything, a good coach records your baseline, your normal lift, pace, and form, so any later change can be measured against a known starting point. Just as that reference footage makes a deviation in technique instantly visible, your captured normal request makes the effect of tampering instantly visible. Just as the coach notes the exact numbers, the load and the reps, you note the exact request, the endpoint and any numeric identifier in the URL or body. This reveals why you establish normal behaviour first: the legitimate call is the baseline whose identifier you will later change to expose the flaw.
http
# Example of a captured baseline request (your ids will differ)
GET /rest/basket/6 HTTP/1.1
Host: localhost:3000
Authorization: Bearer <your-jwt>

# Note the object id in the path (here, basket 6).
# This is the identifier you will change in the next step.

Step 2 — Core Logic: Confirm the IDOR

Now change the identifier in your captured request to a neighbouring value and replay it, either by editing and resending from the developer tools or with a command-line tool. If the server returns another user's basket rather than an error, you have confirmed an IDOR: the endpoint acted on the id without verifying you own that basket. Record the request, the response, and exactly what data leaked.

Analogy🏏Cricket
♟️ Think of it like chess: A player probes a position by changing a single move and watching how the opponent responds, learning the defence from that one variation. Just as altering one move and observing the reply reveals whether a square is truly guarded, altering one identifier and replaying the request reveals whether the server truly checks ownership. Just as an undefended square the opponent fails to protect exposes the weakness, a basket that returns another user's contents instead of an error confirms the IDOR. This reveals the discipline of the test: change exactly one thing, replay it, and record the request, the response, and precisely what data leaked.
bash
# Replay the baseline with a DIFFERENT id (ownership test)
curl -s http://localhost:3000/rest/basket/7 \
  -H "Authorization: Bearer <your-jwt>"

# If this returns basket 7's contents (not yours, not a 403/404),
# the endpoint is vulnerable: it never checked that you own basket 7.
# Document: request sent, status code, and the leaked fields.

Step 3 — Integration & Enhancement: Attempt Vertical Escalation

Next, probe for privilege escalation. Look for an administration route that the normal interface never links to for your account, then request it directly as your logged-in non-admin user. If the server responds with admin data instead of denying you, that is vertical escalation: a higher-privilege endpoint that was hidden in the UI but never protected on the server. Combine this finding with your IDOR to map the full access-control picture.

Analogy🏏Cricket
🍳 Think of it like cooking: In a restaurant kitchen the walk-in freezer has no sign on the dining-room side, but that absence of a sign is not a lock; a determined guest who finds the door can still pull it open. Just as an unmarked but unlocked door grants access it never should, an admin route the interface simply never links can still answer a direct request from a non-admin. Just as testing it means walking up and trying the handle rather than waiting for a sign, probing it means calling the route directly as your logged-in non-admin user. This reveals that hiding a route in the interface is not the same as protecting it on the server.
bash
# Request an admin-only route directly as a NON-admin user
curl -s http://localhost:3000/rest/admin/application-configuration \
  -H "Authorization: Bearer <your-non-admin-jwt>"

# If admin data returns instead of 403 Forbidden, the endpoint
# relied on the UI hiding it — a vertical privilege escalation.
# Note: exact admin paths vary by Juice Shop version; explore
# the Network tab and the app's own JavaScript for candidates.

Step 4 — Testing & Verification: Write the Fix

Finally, turn attacker into defender. For each confirmed flaw, write the server-side control that would close it: scope the basket lookup to the authenticated user so a mismatched id returns 404, and add an authorisation check to the admin route so non-admins receive 403. Verify your reasoning by describing the request that previously succeeded and explaining precisely why the fixed server would now reject it.

Analogy🏏Cricket
💰 Think of it like finance: An auditor who finds a fraud does not stop at the exposé; they write the control that makes it impossible next time. Just as each finding is paired with a concrete safeguard rather than left as a story, each confirmed flaw is paired with a server-side control: scope the basket lookup to the authenticated user so a mismatched id returns 404, and add a role check so non-admins receive 403. Just as the auditor proves the control by replaying the fraudulent transaction and showing it now fails, you verify by describing the request that once succeeded and why the fixed server now refuses it. This reveals defence is finished only when the exploit no longer works.
javascript
// Remediation for the IDOR: bind the lookup to the caller
app.get('/rest/basket/:id', requireLogin, async (req, res) => {
  const basket = await db.baskets.findOne({
    id: req.params.id,
    userId: req.user.id            // ownership enforced server-side
  });
  if (!basket) return res.status(404).end();  // don't confirm existence
  res.json(basket);
});

// Remediation for the admin route: explicit role check
app.get('/rest/admin/*', requireLogin, (req, res, next) => {
  if (!req.user.roles.includes('admin')) return res.status(403).end();
  next();                          // vertical escalation blocked
});

Warning: Only ever run these techniques against Juice Shop or another system you own or are explicitly authorised to test. Sending tampered requests to applications you do not have written permission to test is illegal in most jurisdictions, regardless of intent. Keep the container local, and never point these tools at a third party's live site.

Extension Challenge: Deepen the lab with three additions. Use the JWT you captured to inspect its payload and consider what an unverified 'none' algorithm token would let you forge, previewing Module 3's JWT lesson. Enumerate several basket ids and quantify how many users you could reach. Finally, write an automated test, in the style of Lesson 1, that logs in as one user and asserts a 404 when requesting another user's basket, so the fix stays enforced.

  • OWASP Juice Shop is a deliberately vulnerable app that provides a safe, legal environment to practise finding and exploiting access-control flaws.
  • Establishing a baseline of normal request behaviour first is what makes the effect of tampering with an identifier observable and clear.
  • Confirming an IDOR means changing a single object identifier and seeing the server return another user's data instead of denying the request.
  • Vertical privilege escalation is reaching an admin route directly that the interface merely hid, proving that hiding is not securing.
  • Every confirmed flaw maps to a concrete server-side fix: scope lookups to the authenticated user and add explicit role checks that fail closed.
  • You must only test systems you own or are explicitly authorised to test; running these techniques against others is illegal regardless of intent.
Lesson 6 of 35
0% complete