Interactive security vulnerability labs — learn by exploiting
Insecure Direct Object Reference
Access another user's information by manipulating object references.
SolvedClient-Side Access Controls
Bypass client-side restrictions to perform unauthorized actions.
SolvedCross-Site Scripting
Inject malicious scripts into a vulnerable web page.
SolvedCross-Site Request Forgery
Force a victim to perform an unwanted action.
Solved████████
This lab is locked. Or is it?
SolvedInsecure Direct Object Reference (IDOR) occurs when an application exposes internal object references (like database IDs) to users, allowing them to access resources belonging to other users.
You are a user with ID 3. By changing the ID in the URL to 1, you can access another user's profile—including sensitive information.
A user profile viewer. Log in, find the id parameter in the browser URL bar, and try changing it.
The API endpoint /api/viewUser?id=X does not verify that the requesting user is authorized to view the specified profile.
?id=5)id parameter to a nearby value (e.g., ?id=4 or ?id=6)If you open DevTools (F12) → Network tab and inspect the raw API response, you'll notice the server sends back more data than what's displayed on the page. APIs often leak sensitive fields that the frontend simply chooses not to render.
An Insecure Direct Object Reference (IDOR) vulnerability was identified in the user profile endpoint at /api/viewUser. The endpoint accepts a user ID parameter without verifying the requesting user is authorized to view that profile, allowing any authenticated user to access other users' personal information.
?id=5)id parameter to access another user's profile:
An attacker can enumerate user IDs to access any user's personal information including name, email, and phone number. This constitutes a data breach affecting all users of the platform. Sequential IDs make enumeration trivial, allowing bulk data extraction.
Broken Access Control occurs when an application enforces restrictions only on the client-side (in the browser) but not on the server. A user can bypass these UI restrictions to perform actions they shouldn't be allowed to do.
You have a "Read-Only" role. The buttons to edit and delete are grayed out in the UI, but the server doesn't actually check your role—so if you re-enable the buttons, the actions work.
disabled attribute from the buttonsA notes manager where you're a read-only user. All buttons are disabled—or are they? Open DevTools and find out.
Open Lab →The application only enforces access controls on the client-side using the HTML disabled attribute. The server-side API endpoints do not check the user's role at all.
disabled attribute on the button elementdisabledManually removing disabled from each element works, but in a real bug bounty report you'd want a reproducible exploit a client or triager can run instantly. Open DevTools (F12) → Console and paste this one-liner:
document.querySelectorAll('[disabled]').forEach(el => el.removeAttribute('disabled'))What this does:
document.querySelectorAll('[disabled]') — finds every element on the page that has the disabled attribute.forEach(el => ...) — iterates over each oneel.removeAttribute('disabled') — removes the attribute, re-enabling the elementAll buttons and inputs are now enabled. Click any action button to confirm the server actually processes the request—this is not just a UI trick. Notes are really created, updated, and deleted on the server.
A Broken Access Control vulnerability exists where user permissions are enforced only via the HTML disabled attribute on the client-side. The server-side API endpoints (/api/notes) perform no role-based authorization checks, allowing read-only users to create, modify, and delete notes.
Any user with a read-only role can bypass client-side restrictions to perform full CRUD operations on all notes. This undermines the entire role-based access control system. A malicious read-only user could modify or delete critical security documentation, create misleading entries, or exfiltrate data through note creation.
Cross-Site Scripting (XSS) occurs when an application includes untrusted data in a web page without proper sanitization. An attacker can inject HTML and JavaScript code that executes in the victim's browser.
An attacker sends a link to a victim. When the victim clicks it, the attacker's JavaScript runs in the victim's browser—stealing their session token.
<script> tagdocument.cookieA notes app with search. Log in, then try searching. Notice the q parameter in the URL—what happens if you put something unexpected in there?
The search endpoint at /lab/xss/search?q=... reflects the query parameter directly into the HTML response without sanitization, enabling Reflected XSS.
session_token cookie is set)<script>alert('pwned ',document.cookie)</script>/lab/xss/search?q=<script>alert('pwned ',document.cookie)</script>When the victim visits this URL, the JavaScript executes in their browser, and an alert box displays pwned along with their session token. In a real attack, the token would be sent to an attacker-controlled server instead of displayed in an alert.
A Reflected Cross-Site Scripting (XSS) vulnerability was identified in the search functionality at /lab/xss/search. The q query parameter is reflected directly into the HTML response without sanitization, allowing arbitrary JavaScript execution in the context of an authenticated user's browser session.
session_token cookie)pwned (the session cookie is passed as the second argument and visible in the console)An attacker can craft a malicious link that, when visited by an authenticated user, executes arbitrary JavaScript in their browser. This enables session hijacking via cookie theft, performing actions on behalf of the victim, or redirecting them to a phishing page. Since the session token is accessible to JavaScript (not HttpOnly), full account takeover is achievable.
Cross-Site Request Forgery (CSRF) occurs when an attacker tricks an authenticated user into making an unintended request to a web application. Because the browser automatically includes cookies, the server treats it as a legitimate action.
An attacker sends a link to a victim. When the victim clicks the link, their account gets deleted—because the browser sends the session cookie along with the request automatically.
GET requestAn account settings page with a "Delete Account" button. Log in, then look at how the deletion works. Could someone trick you into clicking a link?
Open Lab →The account deletion endpoint uses a GET request at /deleteAccount with no CSRF token or confirmation. Since GET requests can be triggered by simply navigating to a URL, an attacker can trick a victim into deleting their own account.
/deleteAccountAn attacker sends this link to the victim (via email, chat, etc.). When the authenticated victim clicks it, their browser sends the session cookie automatically, and the server deletes their account.
GET request (should be POST/DELETE)A Cross-Site Request Forgery (CSRF) vulnerability exists in the account deletion functionality. The /deleteAccount endpoint accepts unauthenticated GET requests and relies solely on the session cookie for authorization, with no CSRF token or confirmation mechanism.
An attacker can craft a malicious link that, when clicked by an authenticated victim, permanently deletes their account. The link can be distributed via phishing emails, social media, or embedded in a webpage as an image tag. No user interaction beyond clicking the link is required. This vulnerability affects all authenticated users of the platform.
You've learned about IDOR, Broken Access Control, XSS, and CSRF. Now put your skills together.
Use what you've learned in the previous labs to find the password for the user with ID 100.
What is the password for user ID 100?