BBLABSBBLABS
LaboratoriosAprender desde 0FuncionesPreciosTestimoniosDetrás de BBLABS
  1. Home
  2. Labs
  3. self_svg_XSS — Self-XSS → Bot-Assisted ATO via SVG upload
Medium15 min

self_svg_XSS — Self-XSS → Bot-Assisted ATO via SVG upload

By @gorka

Chain an SVG upload, a `blob:` URL, a chat invite and a headless admin helper bot to turn a Self-XSS into full admin account takeover

$750

That's what a company paid for this bug on HackerOne. Here it is, rebuilt for you to find it yourself.

1.8K views35 completedUpdated Nov 2026
Log in to start

Learn to find this bug

This bug paid $750 on HackerOne.

Create your account and practice real bugs that got paid. Download the environment, find it and learn the exact technique — your path to your first bounty.

650

hunters training

50

labs from real hacks

380

completions

$12,000

paid out for these bugs

40 flags captured this week
Create account
I already have an account

Access to all labs · no commitment · cancel anytime

Hackers who solved it· 8

JM1
@overtone5 days ago
lydiel2
@lydiel18 days ago
espejoramirezhugo3
@espejoramirezhugo24 days ago
zuk4r1
@zuk4r128 days ago
gh0stn4m3sec
@gh0stn4m3secSep 2026
sharat chandra
@sharat chandraSep 2026
jose.medac
@jose.medacSep 2026
elc0ket
@elc0ketSep 2026

Objectives

1
Identify how file previews are rendered (→ `window.open(URL.createObjectURL(blob))`)
2
Realize that SVGs opened as blob-URL documents execute `<script>`
3
Confirm that JWT auth tokens are kept in `localStorage['nc_token']`
4
Notice the in-app chat-invite feature and the admin helper bot
5
Craft an SVG that exfiltrates the admin JWT to `/api/exfil/<your id>`
6
Invite the admin, wait for the bot, harvest the token, hit `/api/admin`

Information

Platform
HackerOne
Difficulty
Medium
Duration
15 min
Bounty
$750
Completed
35
Creator
gorka@gorka
Collaborators
antoniorivera@antoniorivera
Updated
Nov 2026

Download the environment

Reproduce it and find the bug yourself

Create account

Tools

Burp Suite

Prerequisites

  • Python 3 with `requests` (for `exploit.py`)
  • Familiarity with browsers'

Tags

XSS

Achievement you'll earn

Solve this lab to unlock this shareable achievement

Solve this lab to unlock this shareable achievement

Community writeups

Free · no account

The checklist I run on every new target

47 checks ordered by cost: first what can get you in trouble, then the cheap stuff, and finally the expensive stuff — which is where the big bounties are. I'll send it to your inbox right now.

Unsubscribe in one click, from any email.

Attack Chain

Root causes (what makes the chain work)

  1. Unsanitized SVG upload. The server preserves Content-Type: image/svg+xml
    and serves uploads inline (files.ts).
  2. Top-level blob-URL open. FileAttachment.tsx builds a blob URL from the
    downloaded file and calls window.open(blobUrl). A blob URL loaded as a
    document inherits the creator's origin, so the SVG's <script> runs inside
    NeuroChat's origin.
  3. JWT in localStorage. auth.ts returns the token in the JSON response
    body and the client stores it in localStorage['nc_token'] — reachable from
    any script running in the origin.
  4. Open chat invites. Any user can invite anyone (including admin@) into
    any chat they own.
  5. Eager admin helper. A headless Chromium bot loads the chat and clicks the
    "Open in new tab" button on each attachment, firing the payload.

How to solve

1) Exploration

  • Sign in as attacker, upload an SVG that visibly renders (e.g. a simple shape)
  • Click Open in new tab — observe it opens on a blob: URL
  • Inspect Network tab: /api/files/:id returns Content-Type: image/svg+xml

2) Proof of script exec

Upload an SVG such as:

<svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
  <text y="25">hi</text>
  <script>alert(document.domain)</script>
</svg>

Click Open in new tab → alert pops on localhost:1338 → Self-XSS confirmed.

3) Weaponize

Your user id is visible in any decoded JWT (or in /admin if seen, but you are
not admin yet — use atob(token.split('.')[1])). Build an SVG that POSTs your
localStorage to /api/exfil/<id> (see exploit.py).

4) Deliver

Upload the weaponized SVG to a chat. Invite admin@neurochat.ai. The bot polls
every ~15s; it will accept, visit the chat, and click the attachment.

5) Harvest

Open /stolen in the UI (or poll /api/exfil). A capture with
email = admin@neurochat.ai will appear.

6) Takeover

Click Hijack session on that capture (or copy the token into
localStorage['nc_token']). Browse to /admin → flag.

Or: just run the exploit

python3 exploit.py

Proof of Concept (automated)

exploit.py automates steps 1–6 end-to-end. Typical run:

[1] Login as attacker@neurochat.ai
    ✓ logged in as #1 (Alex Morgan) · role=user
[2] Create attacker-owned chat
    ✓ chat id = 5
[3] Craft SVG payload (exfil → /api/exfil/1)
    ✓ 1.4 KB
[4] Upload dashboard-mockup.svg
    ✓ mime preserved as image/svg+xml
[5] Post message referencing file
[6] Invite admin@neurochat.ai
[7] Poll /api/exfil for captured admin token
    ✓ captured admin JWT
[8] Hit /api/admin with stolen JWT
      FLAG{e7a15c…}

The community

This isn't a platform with users.It's people breaking the same things you are.

Inside people ask, share what they found and solve together what would block anyone on their own. It's free to join: no account, no plan, no email required.

Join the BBLABS community on Discord
Join the Discord

Free and open. You don't need a BBLABS account to join.

BBLABS LogoBBLABS

Laboratorios de hacking basados en hackeos reales. Aprende practicando sobre entornos vulnerables, con la resolución explicada paso a paso.

Producto

  • Funcionalidades
  • Precios
  • Labs
  • Aprender desde 0
  • Blog
  • Detrás de BBLABS

Legal

  • Términos
  • Privacidad
  • Cookies
  • Entrar
  • Crear cuenta

Para cualquier duda, bug, soporte o sugerencia puedes escribir a team@bblabs.es

© 2026 BBLABS. Todos los derechos reservados.