Web Hacking: Client-Side and Server-Side Vulnerability Classes
A map of web vulnerability classes, split by client-side and server-side, for planning what to study next.
Web Hacking: Client-Side and Server-Side Vulnerability Classes#
The web has changed. In 2025, we aren't just dealing with simple SQL injections in PHP scripts. We are facing complex Single Page Applications (SPAs), serverless architectures, and AI-driven defenses. This guide covers the essentials for the modern web hacker.
The Modern Tech Stack#
- Frontend: React, Vue, Svelte, and HTMX are dominant. Understanding the Virtual DOM and client-side routing is crucial.
- Backend: Node.js, Go, and Rust have replaced much of the legacy PHP/Java code.
- Infrastructure: Kubernetes and Serverless (AWS Lambda, Cloudflare Workers) are the new normal.
Key Vulnerability Classes#
1. Client-Side Vulnerabilities#
- DOM XSS: With heavy client-side logic, DOM-based XSS is king.
- CORS Misconfigurations: Exploiting overly permissive Access-Control-Allow-Origin headers.
2. API Security#
- Broken Object Level Authorization (BOLA): The #1 API threat. Accessing other users' data by changing an ID.
- Mass Assignment: Overwriting internal fields (like
isAdmin) during object creation.
3. Supply Chain Attacks#
- Dependency Confusion: Tricking build systems into installing malicious internal packages from public registries.
- Malicious NPM Packages: The risk of
npm installis higher than ever.
Tools You Need#
- Burp Suite Pro: Still the undisputed champion.
- Caido: The lightweight, Rust-based alternative gaining traction.
- Nuclei: For fast, template-based scanning.
Conclusion#
Web hacking in 2025 requires a developer's mindset. You need to understand how applications are built to break them effectively.
Client-Side Study Path#
- Read a rendered page's network requests and find where JSON is parsed.
- Trace that JSON into template sinks:
innerHTML,document.write,eval,setTimeout(string). - Pull the front-end bundle and search for
dangerouslySetInnerHTMLand jQuery.html(. - Check
Access-Control-Allow-Originhandling fornulland reflected origins.
Server-Side Study Path#
- Map routes: every
/api/call, every parameter, every verb. - Diff responses for the same object across two accounts (BOLA probes).
- Send extra keys in JSON bodies; watch for mass-assignment acceptance.
- Test pagination and sort parameters for SQL errors.
DOM XSS Lab Sketch#
<script> const q = new URLSearchParams(location.search).get('q'); document.getElementById('out').innerHTML = q; // sink </script>
Payload arrives through the fragment or query. The sink renders HTML, so <img src=x onerror=alert(1)> fires without any server change.
BOLA Probe Setup#
| Account | Resource id | Expected | Finding |
|---|---|---|---|
| A | 1001 | 200 (own) | - |
| B | 1001 | 403 | A returns B's object -> BOLA |
| B | 1002 | 200 (own) | - |
If B reads A's object, that is Broken Object Level Authorization. Report the two request/response pairs verbatim.
Mass Assignment Probes#
POST /api/user/create {"email":"a@b.c","password":"x","role":"admin","isAdmin":true}
Watch whether the server binds the whole body to the model. Response echoing "role":"admin" on GET /api/user/me confirms persistence.
Supply Chain Checks#
- Compare the lockfile against the registry for internal names. An attacker registers a near-name package (
acme-internals-utilsvsacme-internal-utils). - Review
scriptsinpackage.jsonof third-party packages; postinstall runs on install. - Pin versions and enable a private registry proxy that blocks unknown names.
API Test Cases#
| Area | Positive | Negative |
|---|---|---|
| Auth | Login works, token returns | Missing token -> 401 |
| BOLA | Own object readable | Other's object -> 403 |
| Verb tampering | GET works | TRACE/PUT rejected |
| Pagination | Default page returns | Huge page -> error |
| Mass assignment | Create allowed fields | role/isAdmin ignored |
GraphQL Probes#
{ user(id: "1001") { email role } }
Change the id and check whether the ACL holds. Introspection queries (__schema) often leak the type map; most production servers should disable them.
CORS Deep Check#
curl -I -H 'Origin: null' https://target/api
If the response carries Access-Control-Allow-Origin: null with Allow-Credentials: true, a sandboxed iframe can read the API. Same for reflected origins ending in your domain.
Rate Limits#
Burst the login and OTP endpoints. No rate limit plus no lockout means the OTP is brute-forceable. Report the attempt counter and the lockout window that does not exist.
Content Negotiation Bugs#
Some endpoints switch parsers on Content-Type. Sending JSON in an XML slot, or vice versa, can bypass a WAF that only inspects one content type. Document which types the endpoint accepts and which ones the WAF inspects.
Lab Routine#
- Pick one vulnerability class per week.
- Stand up a deliberately vulnerable app locally.
- Write the exploit by hand, then reproduce with a tool.
- Record the request/response pair as evidence.
SPA Attack Surface#
Single-page apps put logic in the bundle. Look for:
- Client-side route guards that anyone can bypass by calling the API directly.
- Role checks in the JS only, never enforced by the server.
- JWTs carrying long-lived roles.
- Hidden features that enable with a query param.
JWT Checks#
# Decode the payload cut -d. -f2 token | tr '_-' '/+' | base64 -d 2>/dev/null | jq . # Testalg=none
Weak secrets and alg=none are the two classic breaks. Flag the claims that carry roles without an expiry.
File Handling#
Download endpoints that take a filename and read from disk are path-traversal candidates:
/download?file=../../../../etc/passwd
Encoded traversal (%2e%2e%2f) tests whether the decoding step happens before validation.
WebSockets#
WS upgrades reuse the same auth story as the HTTP API. Missing origin checks on the upgrade let any site open a socket as the user. Message frames carry JSON; fuzz the schema like REST.
2025 Recon Priorities#
| Signal | Where |
|---|---|
| Subdomain takeover | CNAME to dangling bucket |
| Exposed staging | Nonstandard port, no robots |
| API leaks | JS bundle sourcemaps |
| Legacy PHP | Response header X-Powered-By with version |
Recon before manual testing; the most obvious targets are often not the weakest ones.
API Contract Diffing#
Save the OpenAPI spec, diff it against the actual traffic. Every undocumented endpoint is surface. Every documented endpoint missing from traffic is a gate to probe.
Per-App Checklist#
Walk each surface before moving on:
- All routes enumerated from the bundle or the OpenAPI spec
- Two-account diff on every object endpoint
- Mass-assignment probe with extra keys
- CORS preflight tested with null and reflected origins
- Rate limits probed on auth endpoints
- Content-type confusion documented
Reference Tables#
| Layer | Probe |
|---|---|
| Client | Trace a JSON payload into a sink |
| API | Two-account object read |
| Auth | JWT weak-secret decode check |
| Infra | Old PHP version header |
Reminders#
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
- confirm before reporting
Command Cheatsheet#
curl -I https://target curl -I -H 'Origin: null' https://target jwt_tool token.jwt -T
Final Notes#
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
- confirm, document, report
Short Notes#
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
- document the observation, then the conclusion
Weekly Lab Targets#
| Day | Target |
|---|---|
| Mon | DOM XSS lab |
| Tue | BOLA two-account diff |
| Wed | Mass assignment probes |
| Thu | CORS preflight matrix |
| Fri | Supply-chain review of lockfiles |
Closing Notes#
- Verify each observation with a second independent check.
- Prefer packet, request/response, or log evidence over prose.
- Tie the finding to the control that should have caught it.
- Redact secrets but keep the request shape visible.
- Never quote a payload you have not actually tested.
- Keep one repro per file; name it clearly.
- Update the matrix when a new tool or a new gadget appears.
- Shorten CI runs; the tool should fit in a normal deploy.
- Confirm a false positive before you report it.
- A finding without evidence is folklore.
- Document the exact time delta or row count.
- Record the binary version or framework version in the report.
- Every tool output in the report ties to a command.
- The evidence tree should let a second reader replay the finding.
- Log the encoding and the raw bytes with the finding.
- If a fix closes one probe, re-run the others to be sure.
- Closing one instance rarely closes the class.
- Rotate pretexts and rate limits so the test keeps signal.
- Track report rate, not click rate, for awareness campaigns.
- Keep capture files short; slice the interesting window.
- ZAP baselines belong in CI, full scans on staging.
- Burst the auth endpoint, then verify no lockout.
- Diff lockfiles before running a supply-chain claim.
- Parameter pollution hides in headers and cookies too.
- Checksum your dependencies and rotate keys on a schedule.
- Time-based blind is slow; always pair it with a boolean check.
- Show the GRANTS output; it proves reachability limits.
- DOM sinks are data-flow endpoints, not just payload targets.
- Trusted Types and CSP sit on the same defense line.
- Stash the tshark JSON slice with the pcap for reference.
- A short pcap with notes beats a ten-minute capture.
- Name files with date, host, and window.
- A flat periodic line in the IO graph is a beacon candidate.
- Spike bursts in Burp are usually manual, not scanner.
- Tune Nuclei rate limits so the range is not blocked.
- sqlmap risk/level flags widen the payload classes.
- Arjun finds parameters that do not appear in the URL.
- Keep WordPress plugin nonces in a separate test case.
- XML-RPC is the slow, quiet way in. Disable it if unused.
- Backup files in the docroot are findings by themselves.
- Upload extension checks should run on the normalized name.
- Homoglyphs hide inside scope lists and allowlists.
- Normalize at the edge, log raw, never filter before decode.
- UTF-7 and legacy codecs keep bypassing naive filters.
- A fullwidth probe that passes is a bug in the pipeline.
- Rotate keys, pin versions, and rotate them again after a patch.
- Prototype pollution turns one key into a global change.
__proto__is the first key to block; checkconstructortoo.- Run
npm lsdeep; the vulnerable path is rarely the top level. - Refuse
constructor.prototypekeys at every merge point. - Freeze Object.prototype for the server if you must merge.
What do you think?
React to show your appreciation