Forced Browsing

An anonymous attacker pulls a full employee PII export from an "internal" route that has no auth check at all, then you ship the fix.

What Is Forced Browsing?

Forced browsing is the simplest broken-access-control failure: a route exists on the server, is not linked from the UI, and is reachable by anyone who guesses the path. There is no session check, no role check, often no rate limit. The fix is not a longer URL, it is the same auth-and-authz gate every other route gets. This exercise puts you on both sides. As Bob, an anonymous threat actor with no foothold, you run a content-discovery wordlist against Kelvara's people platform and find /api/internal/employee-export answering 200 OK with the full employee directory, names, work emails, SSN tails, salaries. You send no Authorization header, no cookie, no API key, and the server answers anyway. As Alice, the application security engineer who catches the outbound data-loss alert, you walk in cold, open the handler, see that it never checked anything, and ship the fix: an authentication-plus-role gate that runs before any data is read. Replaying the exact request against the patched build now returns a 403. The exercise closes with quiz questions on what distinguishes forced browsing from horizontal and vertical escalation, why a directory name is not a control, and the durable framework-level defense that makes a missing check fail closed.

What You'll Learn in Forced Browsing

Forced Browsing — Training Steps

  1. Size up the target

    Bob is a financially motivated attacker. He finds companies that have left something exposed on the public internet, then sells what he pulls out or uses it to get at their money. Today he is targeting Kelvara, a people platform companies run their payroll and HR on. He starts where anyone would, on the public site, sizing the company up before he looks for a way in.

  2. Map the API tree

    Nothing on the public site is unusual: a sign-in, a product tour, a support page. But an app answers far more paths than it links to. Anything a developer left reachable stays reachable by anyone who goes looking, so Bob maps every path the portal's API actually responds to.

  3. Open the export route

    The one path that answered without a challenge is a URL like any other. Bob needs no tool for this: he types the discovered path straight into the browser and hits enter, the same as opening any page.

  4. The whole directory, no login

    The response is not an error page. The browser renders it inline: Kelvara's entire employee directory, thousands of records, handed to a request that carried no sign-in at all.

  5. Knowledge check

    You watched a guessed URL return sensitive data to a request with no credentials. Lock in why the endpoint was reachable.

  6. The DLP alert lands

    You own Kelvara's people portal. Overnight, outbound data-loss monitoring tripped on a response that carried the full employee directory, SSNs and salaries included, off the network. Security operations has emailed you the details.

  7. Open the export handler

    The handler that builds the employee export is what you need to change. Open it and look at what it does between the request arriving and the data going out.

  8. Spot the missing gate

    The handler reads every employee record and returns it. Read it top to bottom and look for the access check. There is nothing between the request and the query.

  9. Knowledge check

    You have seen the handler run from request to data with nothing in between. Lock in what actually keeps a route like this private.

  10. Add the access check

    Put a real gate at the top of the handler. It resolves the caller's session, confirms they hold the hr_admin role, and rejects everything else before the database query ever runs. The path stays the same; the check, not the folder name, is now what protects the data.