How I Sneaked Into the Shop Ownerโs Admin โ and Deleted โCarlosโ
This one felt like a heist movie โ except it was a PortSwigger lab, so totally legal and zero real-world damage. Imagine a small online shop. The owner is always active, and his son Carlos runs a loud, bossy account on the site that keeps spamming sales posts. In the lab, our objective is simple (and perfectly safe): get into the admin panel and delete the user carlos
. Let me tell you how the scene played out โ like a little story.

The shop looks normal: a clean shopfront, product cards, checkout. Near the top of the site thereโs a hidden route everyone talks about in the lab โ /admin
โ which should be the ownerโs private control room. When I tried going to /admin
my browser hit a wall: a plain โaccess deniedโ page. The page looked boring. That boringness was the kind of clue a curious person canโt ignore.

The front-end was acting like a polite bouncer โ โNo entry, mate.โ But the bouncer looked generic, like a static block page. My detective brain went: maybe the front-end is blocking the door, but the real admin room inside might still exist. In layered web architectures (CDN/proxy โ front-end โ back-end), sometimes the front-end blocks a path while the back-end still exposes it โ especially if some routing information is passed along by headers. So I set up a little experiment in my lab tools.
Tools and characters in the scene
Me: curious tester (ethical, lab-only)
Tools: Burp Suite (Proxy & Repeater) and a browser for screenshots
Target: PortSwigger lab site (the shop)
Goal: access admin panel and delete
carlos
(lab-only)

1) Start intercepting
In Burp, enable Proxy โ Intercept โ Intercept is on.
Open the lab site in your browser. Burp will stop the outgoing HTTP request and show it in the Intercept tab.
Click the Intercept tab so you can edit the raw HTTP request before forwarding.
2) Confirm the header controls what the back-end sees
You should see a capture request.
Observe the response in your browser (or check Proxy โ HTTP history): you should get a Not Found style response.
Why: the back-end is reading
X-Original-URL
and returning content based on it./invalid
yields Not Found.
- ย
Edit the request in Intercept as follows:
Change the request-line path to
/
(so the front-end will accept/route it).Add the header:
X-Original-URL: /invalid
Click Forward (or Go) to send this edited request to the server.

3) Force the back-end to show the admin
Go back to Proxy โ Intercept and capture another request (or use the same flow again so you can edit).
Edit the request.
Forward the edited request.
Check the browser or HTTP history โ the response body should now contain the admin panel HTML.
Why: the back-end trusted the
X-Original-URL
value and served the admin page even though the front-end blocks direct/admin
requests.

4) Delete carlos
โ do it from Intercept
Now perform the delete action by intercepting the adminโs Delete button click (or manually craft the request in Intercept):
If you click Delete in the admin UI while intercept is on, Burp will capture the outgoing delete request. Edit that captured request OR craft it manually like in image:
Forward the edited request.
Observe the response in the browser or Proxy โ HTTP history โ the lab should show success and
carlos
should be removed.Why: the back-end processed
/admin/delete
(as indicated by the header) and acted on the query parameterusername=carlos
.

Backend vs Front-end โ quick recap (why this works)
Front-end (proxy/router/CDN): blocks direct
/admin
access and shows a generic block page. It normally rewrites or sets headers to tell the back-end the original path.Back-end (app server/framework): trusts the
X-Original-URL
header to determine routing. If it doesnโt re-check authentication/authorization and trusts that header from the client, a tester can set it and bypass the front-end block.Core issue: inconsistent enforcement of access controls across layers and trusting client-controllable headers.
Conclusion
Since you worked entirely inside Intercept, the flow is: capture โ edit request-line and add X-Original-URL
โ forward โ observe response โ repeat for delete. In this PortSwigger lab the back-end honored the X-Original-URL
header, allowing you to view the admin panel and delete carlos
. The real takeaway for production systems: never trust headers coming from unverified clients โ enforce server-side authentication and authorization for all sensitive actions and strip/validate proxy headers.