- Kali Linux VM running in VirtualBox
- Internet access in Kali
- Basic terminal knowledge
- Enough RAM (~2–4 GB recommended for Node.js + ZAP)
- Install OWASP ZAP
- command run:
sudo apt update && sudo apt upgrade -y
sudo apt install zaproxy -y
- command run:
zaproxy &
- Install Node.js and npm:
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs build-essential git
- clone juice Shop:
- command run:
git clone https://github.com/juice-shop/juice-shop.git
cd juice-shop
npm install --legacy-peer-deps
npm start
- Open OWASP ZAP and go to:
- Tools → Options → Network-->Server Certificates
- Export the ZAP Root Certificate (OWASP-ZAP-Cert.cer) to your local machine.
- Configure Firefox to use ZAP as a proxy:
- Address: 127.0.0.1
- Port: 8080
- Import ZAP certificate into Firefox:
- Preferences → Privacy & Security → Certificates → View Certificates → Authorities → Import
- Select OWASP-ZAP-Cert.cer and trust it to identify websites
- Restart FireFox
- Result: Firefox traffic is routed through ZAP, HTTPS sites load correctly, and Juice Shop (http://localhost:3000) is ready for security testing.
- Log in Page:
http://127.0.0.1:3000/#/login - Product Page:
http://127.0.0.1:3000/#/ - custom feedback section:
http://127.0.0.1:3000/#/contact - complaint section:
http://127.0.0.1:3000/#/complain - customer support chat:
http://127.0.0.1:3000/#/chatbot - about section:
http://127.0.0.1:3000/#/about - photo section:
http://127.0.0.1:3000/#/photo-wall - deluxe membership:
http://127.0.0.1:3000/#/deluxe-membership - cart section:
http://127.0.0.1:3000/#/basket - profile section:
http://127.0.0.1:3000/profile - order history:
http://127.0.0.1:3000/#/order-history - recycle:
http://127.0.0.1:3000/#/recycle - address:
http://127.0.0.1:3000/#/address/saved - payment options:
http://127.0.0.1:3000/#/saved-payment-methods - digital wallet:
http://127.0.0.1:3000/#/wallet - privacy policy:
http://127.0.0.1:3000/#/privacy-security/privacy-policy - request data expert:
http://127.0.0.1:3000/#/privacy-security/data-export - request data ensure:
http://127.0.0.1:3000/dataerasure - change password:
http://127.0.0.1:3000/#/privacy-security/change-password - two factor authentication:
http://127.0.0.1:3000/#/privacy-security/two-factor-authentication - last login ip:
http://127.0.0.1:3000/#/privacy-security/last-login-ip
- scan with spyder
- First, I ran ZAP’s Spider on the Juice Shop target (http://127.0.0.1:3000) to automatically crawl and map all pages, forms, and API endpoints.
- After the Spider finished, I ran the AJAX Spider to discover dynamic endpoints generated by JavaScript, ensuring that all hidden or AJAX-loaded pages were identified.
- These steps provided a complete map of the application, which is essential before performing an active vulnerability scan.
- After mapping the Juice Shop application with Spider and AJAX Spider, I ran ZAP’s Active Scan using the default scan policy.
- This policy includes automated checks for the OWASP Top 10 vulnerabilities, such as SQL Injection, Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), and Broken Access Control.
- The Active Scan sent crafted requests to all discovered endpoints, forms, and API parameters to identify potential security weaknesses.
- Scan results are available in the Alerts tab, showing the vulnerability type, affected URL/parameter, severity, and evidence for each finding.
- Objective: Test login form for SQL Injection vulnerability.
- Opened Juice Shop login page in browser (http://127.0.0.1:3000/#/login)
- Submitted the following payload in the login form manually:
- command run:
{"email":"' OR '1'='1","password":"x"}
- Login succeeded without valid credentials.
- Manual test confirmed that SQL Injection allows authentication bypass.
Capture the same request in ZAP Requester to reproduce the vulnerability and document it professionally.
- Captured the login request using ZAP Break mode to ensure all headers, cookies, and CSRF tokens were included.
- Sent malicious SQL payloads in the email field while keeping the password arbitrary.
- Observed server response and authentication token returned for successful injection.
- command run:
{"email":"' OR '1'='1' --","password":"x"}
{"email":"' OR 1=1--","password":"x"}
{"email":"' OR 1=1/*","password":"x"}
- Server returned authentication tokens despite incorrect credentials.
- SQL injection bypassed login validation, demonstrating critical vulnerability.
- Successfully gained unauthorized access to restricted areas.
- Critical security risk: allows attackers to bypass authentication and access user accounts, potentially exposing sensitive data.
- Use parameterized queries / prepared statements instead of string concatenation.
- Implement input validation and sanitization for all user inputs.
- Enable multi-factor authentication and monitor suspicious login attempts.
- Endpoint / Location: Search box (UI) — search request (client-side query), GET /api/products (query parameter)
- Payload (used):
<img src=x onerror=alert(1)>
Submitting the above payload in the Juice Shop search box causes the injected tag to be reflected in the search results and executed by the browser (an alert box appears). This indicates the application is reflecting user input into HTML without proper output encoding or sanitization, allowing arbitrary script execution in the context of the victim’s browser.
- Open Juice Shop UI at http://127.0.0.1:3000.
- Focus the search input (top bar).
- Enter: and press Enter / submit.
- Observe the JavaScript alert popup (proof of script execution).
- Reflected XSS can be used to run arbitrary JavaScript in users’ browsers. Impacts include session theft, account takeover, UI redressing, phishing, and performing actions on behalf of authenticated users. Severity depends on context — for search results visible to other users or admins, severity is High.
- Severity: High (context-dependent; treat as high until further containment analysis)
- Output Encode: Ensure all user-provided data rendered in HTML is safely encoded (HTML-encode special characters such as <, >, &, ").
- Input Validation: Apply server-side validation to disallow HTML tags in fields that should be plain text (search queries should be treated as plain text).
- Use a Safe Rendering Library: If rendering user content as HTML is required, sanitize it with a vetted library (e.g., DOMPurify) and restrict allowed tags/attributes.
- Content Security Policy: Implement a strict CSP (e.g., disallow inline scripts) to reduce impact of injected scripts.
- Escape on Output in Templates: Use framework-safe output encoding (Angular built-in sanitizer or templating auto-escaping).
- Endpoint: POST /rest/feedback
- Payloads attempted (one at a time):
<script>alert('stored-xss')</script>
<img src=x onerror=alert('stored-xss')>
"><svg/onload=alert('stored-xss')>
<a href="javascript:alert('xss')">click</a>
<div style="width:expression(alert('xss'))">
<img src="data:image/svg+xml,<svg/onload=alert('xss')>">
- All payloads were submitted successfully.
- Feedback confirmation page showed "Thank you for your feedback."
- No JavaScript executed; payloads were displayed as plain text.
- Feedback inputs are sanitized and rendered safely, preventing stored XSS.
- Maintain Angular DOM sanitization and output encoding for future updates.
- Severity: High
- Status: Confirmed
During testing of user-accessible endpoints in the Juice Shop application, it was observed that the /rest/basket/ endpoint does not properly enforce access control. Authenticated users were able to retrieve data belonging to other users by sequentially modifying the numeric id parameter in requests.
-
This allows unauthorized access to sensitive information including:
- User baskets
- Product names, quantities, and prices
- User IDs
-
No authorization checks are applied on the server side to verify that the requesting user owns the requested basket
- Log in as any valid user (e.g., User ID 24).
- Capture a legitimate basket request in ZAP or browser DevTools:
GET http://127.0.0.1:3000/rest/basket/<user_basket_id>
Authorization: Bearer <valid_token>
- Modify the id parameter to other numeric values (e.g., /rest/basket/1, /rest/basket/2, /rest/basket/3).
- Send the modified request.
- Observe that the server returns the full basket data for the requested id, regardless of the authenticated user.
{
"status":"success",
"data":{
"id":3,
"UserId":3,
"Products":[
{
"id":4,
"name":"Raspberry Juice (1000ml)",
"description":"Made from blended Raspberry Pi, water and sugar.",
"price":4.99,
"BasketItem":{"ProductId":4,"BasketId":3,"id":5,"quantity":1}
}
]
}
}
- Full disclosure of other users’ basket data without consent.
- Sensitive user information exposure (UserId, product orders).
- Potential escalation: combined with other vulnerabilities, could allow manipulation of other users’ baskets.
- Enforce strict server-side authorization: verify that the requesting user owns the resource before returning data.
- Avoid exposing sequential IDs without validation.
- Apply authorization checks on all GET, PUT, DELETE endpoints that handle user-specific data.
- Evaluate whether the /rest/user/change-password endpoint is vulnerable to CSRF attacks (state-changing requests without proper authentication or token validation).
- Copied the request from DevTools for a password change.
- Created csrf_test.html with a form submitting to /rest/user/change-password using POST method.
- Filled the form with dummy values (current=dummyOld123, new=dummyNewExtreme456, repeat=dummyNewExtreme456).
- Opened the HTML file in a browser session without being logged in.
- Submitted the form.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSRF Test - Juice Shop</title>
</head>
<body>
<h2>CSRF Test Form</h2>
<p>This form submits a dummy password change request to test CSRF handling.</p>
<form action="http://127.0.0.1:3000/rest/user/change-password" method="POST">
<!-- Dummy password fields -->
<input type="hidden" name="current" value="dummyOld123">
<input type="hidden" name="new" value="dummyNewExtreme456">
<input type="hidden" name="repeat" value="dummyNewExtreme456">
<!-- Optional: CSRF token if captured from DevTools -->
<!-- <input type="hidden" name="csrf" value="PASTE_YOUR_TOKEN_HERE"> -->
<input type="submit" value="Extreme CSRF Test">
</form>
<p>Open this page in a browser where you are NOT logged in. Click "Extreme CSRF Test" to submit.</p>
</body>
</html>
500 Error: Unexpected path: /rest/user/change-password
at /home/kali/Downloads/juice-shop/build/routes/angular.js:42:18
- The request was blocked.
- The application enforces CSRF protections (route validation, token/origin checks).
- The server did not process the CSRF form submission.
- CSRF mitigation is in place; arbitrary password changes without authentication are not possible.
- Attempting state-changing actions without a valid session or token is correctly rejected.
- No CSRF vulnerability found on the /rest/user/change-password endpoint.
- Juice Shop properly validates the request path and origin for state-changing actions.
- csrf_test.html form (dummy values used).
- Server response captured in ZAP: 500 Error.
- Screenshot of browser submission with rejection message.
- Continue monitoring CSRF protections during upgrades.
- Always ensure CSRF tokens are required for sensitive endpoints.
Test the file upload functionality to check whether malicious or unexpected file types can be uploaded and executed. This helps identify file upload vulnerabilities, including arbitrary code execution or content rendering issues.
#/photo-wall (Photo Wall upload feature)
File upload URL observed in requests: http://127.0.0.1:3000/assets/public/images/uploads/
| File | Method | Result |
|---|---|---|
| test.txt renamed to test.jpg | Upload attempt | Rejected / Not rendered |
| payload.svg | Upload attempt | Rejected / Not rendered |
| payload.jpeg | Upload attempt | Rejected / Not rendered |
| payload.png | Upload attempt | Rejected / Not rendered |
| payload.jpg | Upload attempt | Rejected / Not rendered |
- Prepared test files with different extensions (.jpg, .jpeg, .png, .svg) to bypass simple extension checks.
- Attempted uploads via the Photo Wall interface in Juice Shop.
- Observed uploaded file URLs in the browser and attempted direct access.
- Captured all requests and responses in ZAP for documentation.
- The server rejected all file types, including .jpg, .jpeg, .png, and .svg.
- Attempting to access the uploaded files directly returned no content or blocked response.
- Error messages indicate Juice Shop enforces file validation and filtering.
- Requests captured in ZAP serve as evidence of the server handling file uploads securely.
- The Photo Wall file upload feature is protected against malicious or unexpected file uploads.
- No vulnerabilities were identified during this test.
- The server demonstrates robust validation for uploaded file types.
- Vulnerability: Information Disclosure (sensitive files/directories)
- Tested Endpoints / Paths:
| Path | Observed Response |
|---|---|
| /robots.txt | Disallowed /ftp listed → screenshot captured |
| /config | HTTP 200 OK → screenshot captured |
| /.env | HTTP 404 / blocked → screenshot captured |
| /.git/ | HTTP 404 / blocked → screenshot captured |
| /admin | HTTP 404 / blocked → screenshot captured |
| /backup | HTTP 404 / blocked → screenshot captured |
| /server-status | HTTP 403 / blocked → screenshot captured |
- The robots.txt file discloses /ftp path.
- Other common sensitive paths were blocked or returned 404/403 errors.
- No stack trace or detailed server info exposed.
- Screenshots captured in ZAP demonstrate responses for each path.
- No direct exploit possible, but presence of sensitive endpoints can aid an attacker in reconnaissance.
- Restrict access to sensitive directories and configuration files.
- Remove unnecessary files from webroot.
- Ensure robots.txt does not list sensitive paths.
- Monitor access logs for repeated probing attempts.
This security assessment of the Juice Shop application was conducted entirely within a controlled lab environment using Kali Linux, OWASP ZAP, Node.js and Juice Shop. Both automated scanning and manual testing methodologies were employed to evaluate the application against common web vulnerabilities
- Environment & Setup
- Kali Linux VM with sufficient resources (~4 GB RAM).
- Juice Shop running locally via Node.js (npm start) at http://localhost:3000.
- OWASP ZAP configured as proxy; Firefox traffic routed through ZAP with proper root certificate installed.
- Automated Scanning
- Spider and AJAX Spider crawled all pages, forms, and API endpoints.
- Active Scan identified potential vulnerabilities according to OWASP Top 10.
- Manual Testing
- SQL Injection (Login Form): Critical — allowed authentication bypass using payloads like
' OR '1'='1. - Reflected XSS (Search Box): High — scripts reflected in search results; executed in browser.
- Stored XSS (Feedback Form): Not exploitable — Angular sanitization prevents execution.
- Broken Access Control (IDOR / Basket API): High — sequential IDs exposed other users’ basket data.
- CSRF (Change Password Endpoint): Not vulnerable — server rejects unauthorized requests without valid session or CSRF token.
- File Upload (Photo Wall): Secure — invalid/malicious files rejected; no arbitrary file execution possible.
- Sensitive Information Discovery: Low — /robots.txt exposed /ftp, but other paths blocked; no critical info disclosed.
- Impact & Recommendations
- Critical: SQL Injection — use parameterized queries, input validation, MFA.
- High: Reflected XSS, Broken Access Control — sanitize inputs, enforce server-side authorization, implement CSP.
- Medium/Low: Info disclosure — restrict sensitive directories, remove unnecessary files.
- Continuous monitoring, secure coding practices, and periodic vulnerability assessments recommended.
- Juice Shop demonstrates a mix of vulnerable and secure components, providing a realistic lab scenario for learning web security.
- Critical vulnerabilities like SQL Injection and IDOR emphasize the importance of server-side input validation and access control.
- Most security protections such as CSRF mitigation, file upload validation, and XSS sanitization in feedback were effective.
- The exercise successfully combined automated scanning, manual testing, and documentation, resulting in a thorough web application security assessment