Skip to main content

Free 30-min security demo Book Now

Offensive360 Offensive360
Application Security

OWASP Juice Shop Beginner Walkthrough: First 10 Challenges

Step-by-step OWASP Juice Shop walkthrough for beginners: find the scoreboard, crack the login with SQL injection, solve XSS and IDOR — with full technical explanations.

Offensive360 Security Research Team — min read
OWASP Juice Shop juice shop walkthrough juice shop beginner owasp juice shop walkthrough juice shop challenges juice shop solutions juice shop sql injection juice shop xss juice shop idor juice shop guide vulnerable web application web application security security training juice shop scoreboard juice shop setup

This walkthrough covers the first ten OWASP Juice Shop challenges in the order that makes the most sense for beginners — starting with zero-star exploration tasks and building up through SQL injection, XSS, and broken access control. Each challenge includes the exact steps, what happens technically, and why it matters in real applications.

If you haven’t started Juice Shop yet, get it running in under a minute:

docker run --rm -p 3000:3000 bkimminich/juice-shop

Then open http://localhost:3000/ in your browser and keep browser DevTools open (F12) throughout — the Network tab is essential.


Challenge 1: Find the Score Board (⭐)

Category: Security Through Obscurity

The scoreboard lists every Juice Shop challenge. It is deliberately not linked from the navigation — finding it is your first task.

Solution:

Navigate directly to:

http://localhost:3000/#/score-board

A success notification pops up: you’ve solved your first challenge. The scoreboard is now your mission control — it shows all 100+ challenges, their difficulty (1–6 stars), category, and completion status.

Why it matters: The scoreboard URL is embedded in Juice Shop’s Angular JavaScript bundle. Any attacker who inspects main.js can enumerate every route in the application — including admin routes. Applications that rely on “hidden URLs” without authentication are relying on security through obscurity, which is not a security control.

In real engagements, finding hidden routes by reading JavaScript source is standard reconnaissance. Route definitions, API calls, and configuration values in frontend code are visible to anyone who looks.


Challenge 2: Privacy Policy (⭐)

Category: Awareness

Solution:

Navigate to http://localhost:3000/#/privacy-security/privacy-policy. You can also find the link at the bottom of most Juice Shop pages.

Simply reading it completes the challenge. This one teaches you to explore every part of an application methodically — don’t just test the obvious inputs. In real assessments, reading privacy policies, terms of service, and help pages sometimes reveals technology stack details, internal system names, and data processing disclosures useful for an attacker.


Challenge 3: Bonus Payload (⭐)

Category: XSS — Cross-Site Scripting

Solution:

Paste this payload into the search bar and press Enter:

<iframe width="100%" height="166" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/771984076&color=%23ff5500">

A SoundCloud embed appears in the search results — this is a stored XSS via the search endpoint reflecting the user’s input unsanitized back into the page.

The simpler version also works for the challenge:

<iframe src="javascript:alert('xss')">

Why it matters: Any time a web application reflects user input back into an HTML page without encoding it, XSS is possible. The search bar appears to be a safe input field — it’s just for filtering products. But because the search term is reflected in the page without HTML encoding, injecting an <iframe> or <script> tag turns user input into executable HTML.

In production applications, reflected XSS in search bars is one of the most common findings. It enables attackers to craft malicious URLs that, when clicked by a victim, execute JavaScript in the victim’s browser — accessing their cookies, performing authenticated API calls, or redirecting them.


Challenge 4: DOM XSS (⭐)

Category: XSS — DOM-Based

Solution:

Type the following in the search bar:

<iframe src="javascript:alert(`xss`)">

Note the backtick syntax — this is required for the DOM XSS version because the Angular application processes the search term client-side through a JavaScript template context. Regular quote characters may be encoded, but backtick-wrapped strings in this specific context bypass the encoding.

Why it matters: DOM-based XSS is harder for automated scanners to find than reflected XSS because the vulnerability exists in client-side JavaScript, not server-rendered HTML. The server may never even see the payload — it’s processed entirely in the browser. Finding DOM XSS requires reading the client-side JavaScript to understand how URL fragments, search terms, and navigation inputs are handled.


Challenge 5: Zero Stars (⭐)

Category: Improper Input Validation

Goal: Submit a product review with a zero-star rating. The UI normally prevents this — you cannot click below one star.

Solution:

  1. Log in to any account (register one first if needed)
  2. Navigate to the Contact Us page: http://localhost:3000/#/contact
  3. Notice the star rating widget — you cannot drag it to zero
  4. Open DevTools → Network tab
  5. Set the rating to one star (minimum) and write any comment
  6. Click Submit
  7. In the Network tab, find the POST request to /api/Feedbacks/
  8. The request body contains: {"comment":"...","rating":1,"captchaId":...,"captcha":"..."}
  9. Use the browser console to resend the request with "rating":0:
fetch('/api/Feedbacks/', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + localStorage.getItem('token')
  },
  body: JSON.stringify({
    comment: "Zero stars!",
    rating: 0,
    captchaId: 1,
    captcha: "..."  // Use the captcha value from the intercepted request
  })
}).then(r => r.json()).then(console.log)

Alternatively, intercept the request in Burp Suite and change "rating":1 to "rating":0 before forwarding.

Why it matters: Client-side input validation — like the star rating widget minimum — is a user experience feature, not a security control. Any server-side API that accepts numeric values must validate them server-side too. A server that trusts the client’s rating value can receive 0, -1, or any other value the attacker sends directly to the API.


Challenge 6: Login Admin (⭐⭐)

Category: SQL Injection

Goal: Log in to the admin account without knowing the admin’s password.

Solution:

  1. Navigate to http://localhost:3000/#/login
  2. In the Email field, enter:
    ' OR 1=1--
  3. In the Password field, enter anything (it doesn’t matter)
  4. Click Sign In

You are now logged in as the admin.

What happened technically:

The application builds a SQL query to check credentials:

SELECT * FROM Users WHERE email = '[input]' AND password = '[hash]'

After your injection, this becomes:

SELECT * FROM Users WHERE email = '' OR 1=1-- AND password = '...'

Breaking this down:

  • ' — closes the email string
  • OR 1=1 — adds a condition that is always true, making the entire WHERE clause return all rows
  • -- — SQL comment that removes the password check entirely

The query returns all users. The application logs you in as the first result — the admin.

Why it matters: SQL injection in login forms is found in legacy PHP, classic ASP, and older Java applications that use string concatenation to build queries. The fix is always the same: parameterized queries (prepared statements) where the user’s input is passed as a parameter, never embedded in the SQL string.

# VULNERABLE
cursor.execute(f"SELECT * FROM Users WHERE email = '{email}' AND password = '{pw}'")

# SECURE — parameterized query
cursor.execute("SELECT * FROM Users WHERE email = ? AND password = ?", (email, pw))

Challenge 7: View Basket (⭐⭐)

Category: Broken Access Control / IDOR

Goal: View another user’s shopping basket — not your own.

Solution:

  1. Log in as any user (the admin from the previous challenge, or a new account)
  2. Add any item to your basket
  3. Open DevTools → Network tab
  4. Click the basket icon in the navigation
  5. Watch for the request: GET /rest/basket/[ID] (where ID is your user’s basket ID, e.g., 1)
  6. In the browser console, request a different basket ID:
fetch('/rest/basket/2', {
  headers: {
    'Authorization': 'Bearer ' + localStorage.getItem('token')
  }
}).then(r => r.json()).then(console.log)

If another user has basket ID 2, you receive their basket contents. The server does not verify that you are authorized to view basket ID 2 — it just returns whatever basket is requested.

Why it matters: IDOR (Insecure Direct Object Reference) — also called BOLA (Broken Object Level Authorization) in API security contexts — is the #1 vulnerability in OWASP’s API Security Top 10. It occurs whenever an API returns resources based on a user-controlled identifier without verifying authorization.

In real e-commerce applications, this allows any authenticated customer to access other customers’ orders, addresses, payment information, and personal data. The pattern is identical: change a numeric ID in an API request and receive someone else’s data.

The fix: Server-side authorization. Before returning basket ID 2, verify that the authenticated user owns basket 2. This is a single database join:

SELECT * FROM Baskets WHERE id = 2 AND UserId = [authenticated_user_id]

Challenge 8: Password Strength (⭐⭐)

Category: Broken Authentication

Goal: Log in to the admin account using the admin’s actual password (not SQL injection).

Solution:

The admin’s email is admin@juice-sh.op (found through the application or the scoreboard hints). The admin password is weak enough to appear in common password lists.

Try the most common default: admin123.

Steps:

  1. Navigate to http://localhost:3000/#/login
  2. Email: admin@juice-sh.op
  3. Password: admin123

You’re in. The admin account uses a password that appears in any standard wordlist.

Why it matters: Applications without brute-force protection are vulnerable to credential stuffing and password spraying attacks. Juice Shop has no rate limiting on the login endpoint — an attacker can attempt thousands of passwords per minute without being blocked. Weak default credentials (admin123, password, 123456) are always tried first in real attacks.

The fixes: Enforce strong password requirements at account creation, implement rate limiting on authentication endpoints (block or slow-down after 5–10 failed attempts), and add account lockout after sustained failure.


Challenge 9: Confidential Document (⭐)

Category: Sensitive Data Exposure

Goal: Access a confidential file that should not be publicly accessible.

Solution:

Navigate to:

http://localhost:3000/ftp/

A directory listing appears — the web server is configured to show the contents of the /ftp/ directory to anyone who visits the URL. Download acquisitions.md to complete the challenge.

Why it matters: Directory listing vulnerabilities are found in Apache (Options +Indexes), Nginx (autoindex on), and misconfigured S3/cloud storage buckets with public ListBucket permission. Finding publicly accessible /backup/, /files/, /uploads/, or /documents/ directories is standard enumeration practice in real assessments. A single confidential document — financial data, acquisition plans, customer records — found in a publicly accessible path is a critical severity finding.

The fix: Disable directory listing at the web server level. Ensure uploaded and exported files are stored outside the web root or behind authentication middleware.


Challenge 10: Reflected XSS (⭐⭐)

Category: XSS — Reflected

Goal: Execute a reflected XSS payload via the order tracking URL.

Solution:

The order tracking page accepts an order ID in the URL and reflects it back in the page. Inject a payload in the tracking ID parameter:

  1. Navigate to http://localhost:3000/#/track-result?id=<iframe src="javascript:alert('xss')">

The iframe renders in the page, completing the reflected XSS challenge.

Alternatively via the Track Order form:

  1. Go to http://localhost:3000/#/track-result
  2. Enter the following as the order ID: <iframe src="javascript:alert('xss')">
  3. Click Track

Why it matters: Reflected XSS occurs when user-supplied input is embedded in a server response without sanitization. It differs from stored XSS in that the payload is not saved to the database — the victim must visit a specially crafted URL. Attackers use reflected XSS to steal cookies, redirect users, or perform actions on behalf of the victim by distributing malicious links via email or social engineering.

The fix: HTML-encode all user-supplied values before embedding them in page output. Modern frameworks (React, Angular) do this automatically for most outputs — but bypasses exist when developers explicitly use raw HTML rendering (dangerouslySetInnerHTML in React, [innerHTML] binding in Angular, @Html.Raw() in ASP.NET Razor).


What to Work on Next

After completing these ten challenges, you’ve covered the most fundamental web application vulnerability classes: injection, XSS in all three forms, IDOR, broken authentication, and sensitive data exposure.

For your next session, filter the Juice Shop scoreboard to show only unsolved ⭐⭐ (two-star) challenges and work through them. The recommended two-star progression:

  1. Login Jim (⭐⭐) — log in as Jim without his password using the password reset flow
  2. Admin Registration (⭐⭐) — register an account that has admin role
  3. Five-Star Feedback (⭐⭐⭐) — delete a five-star review (IDOR on the feedback API)

When you’re comfortable with two-star challenges, move to three-star — which introduces JWT token manipulation, XXE injection, and multi-step business logic attacks.

For detailed walkthroughs of specific challenge categories, see:


Frequently Asked Questions

How long does it take to complete all Juice Shop challenges?

Working through all 100+ Juice Shop challenges takes most practitioners 20–40 hours spread across multiple sessions, depending on prior security knowledge. The one- and two-star challenges can be completed in a few hours. Five- and six-star challenges can take hours each.

Can I do Juice Shop without Docker?

Yes — if you have Node.js 18+ installed, clone the repository and run npm install && npm start. Docker is faster for initial setup, but both methods work identically.

Should I use Burp Suite for Juice Shop?

Burp Suite Community Edition is highly recommended for Juice Shop challenges beyond one-star difficulty. Intercepting, modifying, and replaying HTTP requests is essential for IDOR testing, JWT manipulation, and API parameter tampering. The Community Edition (free) is sufficient for all Juice Shop challenges.

Where can I find official Juice Shop solutions?

The official companion guide, Pwning OWASP Juice Shop, is available free at pwning.owasp-juice.shop. It covers every challenge with full solutions and explanations.


Offensive360 DAST is benchmarked against OWASP Juice Shop challenges on every release — verifying that our scanner automatically finds SQL injection, XSS, IDOR, sensitive data exposure, and the other vulnerability classes represented in the scoreboard. Book a demo to see authenticated scanning results on your own application.

Offensive360 Security Research Team

Application Security Research

Find vulnerabilities before attackers do

Run Offensive360 SAST and DAST against your applications and get a full vulnerability report in minutes.